diff options
author | Keader <keader.android@gmail.com> | 2020-06-03 22:05:08 -0300 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-01-06 19:59:50 +0100 |
commit | 4110a06e8193329c31cb9d59d346294835fd51a5 (patch) | |
tree | 2b36682f594ced2aaa0dc32c2deadaa2b5252a3b | |
parent | 9286734b553aecfb9c9e794fac5faee412bda700 (diff) |
Core/Misc: Fixed resistance calculate for Mutated Transformation and Twilight Bloodbolt (#24717)
Ref: 9f7b464a6aa5b64bf5ec5c0f586853fbc71029c6
- Implemented a new SpellScript hook that allow control Resistance/Absorb amount of a damage spell.
(cherry picked from commit d81a9e5bc3b3e13b47332b3e7817bd0a0b228cbc)
-rw-r--r-- | sql/updates/world/master/2022_01_06_36_world_2020_06_03_00_world.sql | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 15 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Spells/SpellScript.h | 22 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp | 22 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp | 18 |
10 files changed, 90 insertions, 26 deletions
diff --git a/sql/updates/world/master/2022_01_06_36_world_2020_06_03_00_world.sql b/sql/updates/world/master/2022_01_06_36_world_2020_06_03_00_world.sql new file mode 100644 index 00000000000..92978b2d024 --- /dev/null +++ b/sql/updates/world/master/2022_01_06_36_world_2020_06_03_00_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_blood_queen_twilight_bloodbolt'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(71446,'spell_blood_queen_twilight_bloodbolt'); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ce14d9385da..20fb86d4c05 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1046,7 +1046,7 @@ void Unit::CastStop(uint32 except_spellid) InterruptSpell(CurrentSpellTypes(i), false); } -void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit) +void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit, Spell* spell /*= nullptr*/) { if (damage < 0) return; @@ -1151,7 +1151,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama damageInfo->damage = damage; damageInfo->originalDamage = damage; DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE, BASE_ATTACK, PROC_HIT_NONE); - Unit::CalcAbsorbResist(dmgInfo); + Unit::CalcAbsorbResist(dmgInfo, spell); damageInfo->absorb = dmgInfo.GetAbsorb(); damageInfo->resist = dmgInfo.GetResist(); @@ -1718,13 +1718,12 @@ void Unit::HandleEmoteCommand(uint32 emoteId, Player* target /*=nullptr*/, Trini return victimResistance / (victimResistance + resistanceConstant); } -/*static*/ void Unit::CalcAbsorbResist(DamageInfo& damageInfo) +/*static*/ void Unit::CalcAbsorbResist(DamageInfo& damageInfo, Spell* spell /*= nullptr*/) { if (!damageInfo.GetVictim() || !damageInfo.GetVictim()->IsAlive() || !damageInfo.GetDamage()) return; uint32 resistedDamage = Unit::CalcSpellResistedDamage(damageInfo.GetAttacker(), damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo()); - damageInfo.ResistDamage(resistedDamage); // Ignore Absorption Auras float auraAbsorbMod = 0.f; @@ -1734,6 +1733,11 @@ void Unit::HandleEmoteCommand(uint32 emoteId, Player* target /*=nullptr*/, Trini RoundToInterval(auraAbsorbMod, 0.0f, 100.0f); int32 absorbIgnoringDamage = CalculatePct(damageInfo.GetDamage(), auraAbsorbMod); + + if (spell) + spell->CallScriptOnResistAbsorbCalculateHandlers(damageInfo, resistedDamage, absorbIgnoringDamage); + + damageInfo.ResistDamage(resistedDamage); damageInfo.ModifyDamage(-absorbIgnoringDamage); // We're going to call functions which can modify content of the list during iteration over it's elements diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a3446114b44..a3b4861ea20 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1045,7 +1045,7 @@ class TC_GAME_API Unit : public WorldObject void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss); void HandleProcExtraAttackFor(Unit* victim); - void CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false); + void CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = BASE_ATTACK, bool crit = false, Spell* spell = nullptr); void DealSpellDamage(SpellNonMeleeDamage const* damageInfo, bool durabilityLoss); // player or player's pet resilience (-1%) @@ -1702,7 +1702,7 @@ class TC_GAME_API Unit : public WorldObject static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr); static uint32 CalcArmorReducedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK, uint8 attackerLevel = 0); static uint32 CalcSpellResistedDamage(Unit const* attacker, Unit* victim, uint32 damage, SpellSchoolMask schoolMask, SpellInfo const* spellInfo); - static void CalcAbsorbResist(DamageInfo& damageInfo); + static void CalcAbsorbResist(DamageInfo& damageInfo, Spell* spell = nullptr); static void CalcHealAbsorb(HealInfo& healInfo); void UpdateSpeed(UnitMoveType mtype); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index af14b186ce2..4690176be01 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2609,7 +2609,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) else { // Add bonuses and fill damageInfo struct - caster->CalculateSpellDamageTaken(&damageInfo, spell->m_damage, spell->m_spellInfo, spell->m_attackType, IsCrit); + caster->CalculateSpellDamageTaken(&damageInfo, spell->m_damage, spell->m_spellInfo, spell->m_attackType, IsCrit, spell); Unit::DealDamageMods(damageInfo.attacker, damageInfo.target, damageInfo.damage, &damageInfo.absorb); hitMask |= createProcHitMask(&damageInfo, MissCondition); @@ -8387,6 +8387,19 @@ std::string Spell::GetDebugInfo() const return sstr.str(); } +void Spell::CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) +{ + for (auto scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_RESIST_ABSORB_CALCULATION); + auto hookItrEnd = (*scritr)->OnCalculateResistAbsorb.end(), hookItr = (*scritr)->OnCalculateResistAbsorb.begin(); + for (; hookItr != hookItrEnd; ++hookItr) + hookItr->Call(*scritr, damageInfo, resistAmount, absorbAmount); + + (*scritr)->_FinishScriptCall(); + } +} + namespace Trinity { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 8601e1d5042..e8c3df6bb5f 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -40,6 +40,7 @@ class Aura; class AuraEffect; class BasicEvent; class Corpse; +class DamageInfo; class DynamicObject; class DynObjAura; class GameObject; @@ -629,6 +630,7 @@ class TC_GAME_API Spell int64 GetItemTargetCountForEffect(SpellEffIndex effect) const; std::string GetDebugInfo() const; + void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); protected: bool HasGlobalCooldown() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 7c69542359c..cc830ac492a 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4268,13 +4268,6 @@ void SpellMgr::LoadSpellInfoCorrections() }); }); - // Mutated Transformation (Professor Putricide) - ApplySpellFix({ 70402 }, [](SpellInfo* spellInfo) - { - // Resistance is calculated inside of SpellScript - spellInfo->AttributesEx4 |= SPELL_ATTR4_IGNORE_RESISTANCES; - }); - // Empowered Flare (Blood Prince Council) ApplySpellFix({ 71708 }, [](SpellInfo* spellInfo) { diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 671ea468227..60b25458bf3 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -191,6 +191,16 @@ SpellCastResult SpellScript::CheckCastHandler::Call(SpellScript* spellScript) return (spellScript->*_checkCastHandlerScript)(); } +SpellScript::OnCalculateResistAbsorbHandler::OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType onResistAbsorbCalculateHandlerScript) +{ + pOnCalculateResistAbsorbHandlerScript = onResistAbsorbCalculateHandlerScript; +} + +void SpellScript::OnCalculateResistAbsorbHandler::Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) +{ + return (spellScript->*pOnCalculateResistAbsorbHandlerScript)(damageInfo, resistAmount, absorbAmount); +} + SpellScript::EffectHandler::EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : _SpellScript::EffectNameCheck(_effName), _SpellScript::EffectHook(_effIndex) { diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 665be327fbc..1c5ee34f7f8 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -189,6 +189,7 @@ enum SpellScriptHookType SPELL_SCRIPT_HOOK_CHECK_CAST, SPELL_SCRIPT_HOOK_BEFORE_CAST, SPELL_SCRIPT_HOOK_ON_CAST, + SPELL_SCRIPT_HOOK_ON_RESIST_ABSORB_CALCULATION, SPELL_SCRIPT_HOOK_AFTER_CAST, SPELL_SCRIPT_HOOK_CALC_CRIT_CHANCE }; @@ -208,6 +209,7 @@ class TC_GAME_API SpellScript : public _SpellScript typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \ typedef void(CLASSNAME::*SpellOnCalcCritChanceFnType)(Unit const* victim, float& chance); \ + typedef void(CLASSNAME::*SpellOnResistAbsorbCalculateFnType)(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); \ typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); \ typedef void(CLASSNAME::*SpellDestinationTargetSelectFnType)(SpellDestination&); @@ -310,6 +312,15 @@ class TC_GAME_API SpellScript : public _SpellScript SpellDestinationTargetSelectFnType DestinationTargetSelectHandlerScript; }; + class TC_GAME_API OnCalculateResistAbsorbHandler + { + public: + OnCalculateResistAbsorbHandler(SpellOnResistAbsorbCalculateFnType _pOnCalculateResistAbsorbHandlerScript); + void Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount); + private: + SpellOnResistAbsorbCalculateFnType pOnCalculateResistAbsorbHandlerScript; + }; + #define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ class CastHandlerFunction : public SpellScript::CastHandler { public: CastHandlerFunction(SpellCastFnType _pCastHandlerScript) : SpellScript::CastHandler((SpellScript::SpellCastFnType)_pCastHandlerScript) { } }; \ class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) { } }; \ @@ -317,6 +328,7 @@ class TC_GAME_API SpellScript : public _SpellScript class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) { } }; \ class BeforeHitHandlerFunction : public SpellScript::BeforeHitHandler { public: BeforeHitHandlerFunction(SpellBeforeHitFnType pBeforeHitHandlerScript) : SpellScript::BeforeHitHandler((SpellScript::SpellBeforeHitFnType)pBeforeHitHandlerScript) { } }; \ class OnCalcCritChanceHandlerFunction : public SpellScript::OnCalcCritChanceHandler { public: OnCalcCritChanceHandlerFunction(SpellOnCalcCritChanceFnType onCalcCritChanceHandlerScript) : SpellScript::OnCalcCritChanceHandler((SpellScript::SpellOnCalcCritChanceFnType)onCalcCritChanceHandlerScript) {} }; \ + class OnCalculateResistAbsorbHandlerFunction : public SpellScript::OnCalculateResistAbsorbHandler { public: OnCalculateResistAbsorbHandlerFunction(SpellOnResistAbsorbCalculateFnType _onCalculateResistAbsorbScript) : SpellScript::OnCalculateResistAbsorbHandler((SpellScript::SpellOnResistAbsorbCalculateFnType)_onCalculateResistAbsorbScript) { } }; \ class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) { } }; \ class DestinationTargetSelectHandlerFunction : public SpellScript::DestinationTargetSelectHandler { public: DestinationTargetSelectHandlerFunction(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::DestinationTargetSelectHandler((SpellScript::SpellDestinationTargetSelectFnType)_DestinationTargetSelectHandlerScript, _effIndex, _targetType) { } }; @@ -358,6 +370,11 @@ class TC_GAME_API SpellScript : public _SpellScript HookList<CheckCastHandler> OnCheckCast; #define SpellCheckCastFn(F) CheckCastHandlerFunction(&F) + // example: OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(class::function); + // where function is void function(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) + HookList<OnCalculateResistAbsorbHandler> OnCalculateResistAbsorb; + #define SpellOnResistAbsorbCalculateFn(F) OnCalculateResistAbsorbHandlerFunction(&F) + // example: OnEffect**** += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier); // where function is void function(SpellEffIndex effIndex) HookList<EffectHandler> OnEffectLaunch; @@ -410,8 +427,9 @@ class TC_GAME_API SpellScript : public _SpellScript // 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched // 7. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map // 8. OnCalcCritChance - executed just after specified effect handler call - when spell missile is launched - called for each target from spell target map - // 9. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest - // 10. BeforeHit - executed just before spell hits a target - called for each target from spell target map + // 9. OnCalculateResistAbsorb - executed when damage resist/absorbs is calculated - before spell hit target + // 10. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest + // 11. BeforeHit - executed just before spell hits a target - called for each target from spell target map // 12. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map // 13. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map // 14. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 758c45b13b5..f4f01d78fff 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -860,6 +860,27 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg_target : public SpellScriptLo } }; +// 71446, 71478, 71479, 71480 - Twilight Bloodbolt +class spell_blood_queen_twilight_bloodbolt : public SpellScript +{ + PrepareSpellScript(spell_blood_queen_twilight_bloodbolt); + + void HandleResistance(DamageInfo const& damageInfo, uint32& resistAmount, int32& /*absorbAmount*/) + { + Unit* caster = damageInfo.GetAttacker();; + Unit* target = damageInfo.GetVictim(); + uint32 damage = damageInfo.GetDamage(); + uint32 resistedDamage = Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_SHADOW, nullptr); + resistedDamage += Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_ARCANE, nullptr); + resistAmount = resistedDamage; + } + + void Register() override + { + OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(spell_blood_queen_twilight_bloodbolt::HandleResistance); + } +}; + class achievement_once_bitten_twice_shy_n : public AchievementCriteriaScript { public: @@ -902,6 +923,7 @@ void AddSC_boss_blood_queen_lana_thel() new spell_blood_queen_pact_of_the_darkfallen(); new spell_blood_queen_pact_of_the_darkfallen_dmg(); new spell_blood_queen_pact_of_the_darkfallen_dmg_target(); + RegisterSpellScript(spell_blood_queen_twilight_bloodbolt); new achievement_once_bitten_twice_shy_n(); new achievement_once_bitten_twice_shy_v(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 0a3939e8046..94717c7dbd2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -1665,21 +1665,19 @@ class spell_abomination_mutated_transformation : public SpellScript { PrepareSpellScript(spell_abomination_mutated_transformation); - /* Resist system always pick the min resist value for spells with multiple schools. - But following some combat logs of retail, this spell is a exception and need get the sum of both schools. */ - void HandleResistance(SpellEffIndex /*effIndex*/) + void HandleResistance(DamageInfo const& damageInfo, uint32& resistAmount, int32& /*absorbAmount*/) { - Unit* caster = GetCaster(); - uint32 damage = GetHitDamage(); - Unit* target = GetHitUnit(); - damage -= Unit::CalcSpellResistedDamage(caster, target, GetHitDamage(), SPELL_SCHOOL_MASK_SHADOW, nullptr); - damage -= Unit::CalcSpellResistedDamage(caster, target, GetHitDamage(), SPELL_SCHOOL_MASK_NATURE, nullptr); - SetHitDamage(damage); + Unit* caster = damageInfo.GetAttacker();; + Unit* target = damageInfo.GetVictim(); + uint32 damage = damageInfo.GetDamage(); + uint32 resistedDamage = Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_SHADOW, nullptr); + resistedDamage += Unit::CalcSpellResistedDamage(caster, target, damage, SPELL_SCHOOL_MASK_NATURE, nullptr); + resistAmount = resistedDamage; } void Register() override { - OnEffectHitTarget += SpellEffectFn(spell_abomination_mutated_transformation::HandleResistance, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(spell_abomination_mutated_transformation::HandleResistance); } }; |