Core/Misc: Fixed resistance calculate for Mutated Transformation and Twilight Bloodbolt (#24717)

Ref: 9f7b464a6a
- Implemented a new SpellScript hook that allow control Resistance/Absorb amount of a damage spell.

(cherry picked from commit d81a9e5bc3)
This commit is contained in:
Keader
2020-06-03 22:05:08 -03:00
committed by Shauren
parent 9286734b55
commit 4110a06e81
10 changed files with 90 additions and 26 deletions

View File

@@ -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');

View File

@@ -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

View File

@@ -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);

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);
}
};