mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
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 commitd81a9e5bc3)
This commit is contained in:
@@ -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');
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user