From b369bb17933580658c3723e6c31337a5b010f002 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Mar 2016 13:02:59 -0400 Subject: [PATCH] Fixed defensive procs so they now only trigger once per attack round like live. Added live like proc chance modifer based on level difference to target. "Anything above your level will receive full mod. Starting 6 levels below PC level there is a negative 10 % mod applied each level until it reaches 0 and will not proc on anything 15 levels below you or lower." Thanks to Huffin from PEQ for the parse data --- changelog.txt | 2 ++ zone/attack.cpp | 46 +++++++++++++++++++++++++++------------------- zone/bot.cpp | 3 ++- zone/mob.cpp | 5 +++-- zone/mob.h | 4 ++-- zone/mob_ai.cpp | 1 + 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/changelog.txt b/changelog.txt index 09ba48d3b..6ee721e64 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 03/25/2016 == Uleat: Fix for heal rotation 'Stack Overflow' error +Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance). + Live like modifier added that decreases defensive proc chance if you are higher level then your attacker. == 03/24/2016 == Kayen: Fix for AE taunt to use correct range and hate modifier. diff --git a/zone/attack.cpp b/zone/attack.cpp index 858e6aee9..786eb128a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1255,7 +1255,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b CommonBreakInvisibleFromCombat(); if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; @@ -1822,7 +1822,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } if(GetHP() > 0 && !other->HasDied()) - TriggerDefensiveProcs(nullptr, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; @@ -3516,7 +3516,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h } // argument 'weapon' not used -void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { +void Mob::TryDefensiveProc(Mob *on, uint16 hand) { if (!on) { SetTarget(nullptr); @@ -3524,29 +3524,37 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { return; } - bool bDefensiveProc = HasDefensiveProcs(); - - if (!bDefensiveProc) + if (!HasDefensiveProcs()) return; - float ProcChance, ProcBonus; - on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); + if (!on->HasDied() && on->GetHP() > 0){ - if(hand != MainPrimary) - ProcChance /= 2; + float ProcChance, ProcBonus; + on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); - if (bDefensiveProc){ - for (int i = 0; i < MAX_PROCS; i++) { - if (IsValidSpell(DefensiveProcs[i].spellID)) { - float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); - if (zone->random.Roll(chance)) { - ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, - DefensiveProcs[i].base_spellID); - } + if(hand != MainPrimary) + ProcChance /= 2; + + int level_penalty = 0; + int level_diff = GetLevel() - on->GetLevel(); + if (level_diff > 6)//10% penalty per level if > 6 levels over target. + level_penalty = (level_diff - 6) * 10; + + ProcChance -= ProcChance*level_penalty/100; + + if (ProcChance < 0) + return; + + for (int i = 0; i < MAX_PROCS; i++) { + if (IsValidSpell(DefensiveProcs[i].spellID)) { + float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); + if (zone->random.Roll(chance)) { + ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); + CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0,DefensiveProcs[i].base_spellID); } } } + } } void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 8cd82f9f6..6cb27f8e7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2911,6 +2911,7 @@ void Bot::AI_Process() { DoClassAttacks(GetTarget()); if(attack_timer.Check()) { Attack(GetTarget(), MainPrimary); + TriggerDefensiveProcs(GetTarget(), MainPrimary, false); ItemInst *wpn = GetBotItem(MainPrimary); TryWeaponProc(wpn, GetTarget(), MainPrimary); bool tripleSuccess = false; @@ -4865,7 +4866,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b BuffFadeByEffect(SE_NegateIfCombat); if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; diff --git a/zone/mob.cpp b/zone/mob.cpp index 0429cc973..c91ae404f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3399,12 +3399,13 @@ int Mob::GetSnaredAmount() return worst_snare; } -void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, int damage) +void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int damage) { if (!on) return; - on->TryDefensiveProc(weapon, this, hand); + if (!FromSkillProc) + on->TryDefensiveProc(this, hand); //Defensive Skill Procs if (damage < 0 && damage >= -4) { diff --git a/zone/mob.h b/zone/mob.h index dd8a36c89..0407ecd3a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -152,7 +152,6 @@ public: bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); - void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary, int damage = 0); bool AvoidDamage(Mob* attacker, int32 &damage, int hand); virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0); virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); @@ -564,6 +563,7 @@ public: bool lookForAftArc = true); //Procs + void TriggerDefensiveProcs(Mob *on, uint16 hand = MainPrimary, bool SkillProc=false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; @@ -1142,7 +1142,7 @@ protected: void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = MainCharm? bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); + void TryDefensiveProc(Mob *on, uint16 hand = MainPrimary); void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 79c4493ea..918c8afde 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1107,6 +1107,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { DoMainHandAttackRounds(target); + TriggerDefensiveProcs(target, MainPrimary, false); bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) {