Merge pull request #7811 from Faq/SplitDamage2

Core/Spells: Implementing some hooks for split damage taken, fixes the l...
This commit is contained in:
kandera
2012-09-24 05:24:01 -07:00
7 changed files with 111 additions and 4 deletions
@@ -0,0 +1,3 @@
DELETE FROM spell_script_names WHERE spell_id = 6940;
INSERT INTO spell_script_names (spell_id, ScriptName) VALUES
(6940, 'spell_pal_hand_of_sacrifice');
+7 -4
View File
@@ -1770,8 +1770,10 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
{
// Check if aura was removed during iteration - we don't need to work on such auras
if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
if (!aurApp)
continue;
// check damage school mask
if (!((*itr)->GetMiscValue() & schoolMask))
continue;
@@ -1781,13 +1783,14 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe
if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->isAlive())
continue;
int32 splitDamage = CalculatePctN(dmgInfo.GetDamage(), (*itr)->GetAmount());
uint32 splitDamage = CalculatePctN(dmgInfo.GetDamage(), (*itr)->GetAmount());
(*itr)->GetBase()->CallScriptEffectSplitHandlers((*itr), aurApp, dmgInfo, splitDamage);
// absorb must be smaller than the damage itself
splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
dmgInfo.AbsorbDamage(splitDamage);
uint32 splitted = splitDamage;
uint32 split_absorb = 0;
DealDamageMods(caster, splitted, &split_absorb);
@@ -2327,6 +2327,21 @@ void Aura::CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraAppli
}
}
void Aura::CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount)
{
for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_SPLIT, aurApp);
std::list<AuraScript::EffectSplitHandler>::iterator effEndItr = (*scritr)->OnEffectSplit.end(), effItr = (*scritr)->OnEffectSplit.begin();
for (; effItr != effEndItr; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellInfo, aurEff->GetEffIndex()))
(*effItr).Call(*scritr, aurEff, dmgInfo, splitAmount);
}
(*scritr)->_FinishScriptCall();
}
}
UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, uint64 casterGUID)
: Aura(spellproto, owner, caster, castItem, casterGUID)
{
@@ -217,6 +217,8 @@ class Aura
void CallScriptEffectAfterAbsorbHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
void CallScriptEffectAfterManaShieldHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount);
void CallScriptEffectSplitHandlers(AuraEffect* aurEff, AuraApplication const* aurApp, DamageInfo & dmgInfo, uint32 & splitAmount);
std::list<AuraScript*> m_loadedScripts;
private:
void _DeleteRemovedApplications();
+18
View File
@@ -675,6 +675,10 @@ bool AuraScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `AfterEffectManaShield` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectSplitHandler>::iterator itr = OnEffectSplit.begin(); itr != OnEffectSplit.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError(LOG_FILTER_TSCR, "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSplit` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
return _SpellScript::_Validate(entry);
}
@@ -803,6 +807,17 @@ void AuraScript::EffectManaShieldHandler::Call(AuraScript* auraScript, AuraEffec
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount);
}
AuraScript::EffectSplitHandler::EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex)
: AuraScript::EffectBase(_effIndex, SPELL_AURA_SPLIT_DAMAGE_PCT)
{
pEffectHandlerScript = _pEffectHandlerScript;
}
void AuraScript::EffectSplitHandler::Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount)
{
(auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, splitAmount);
}
bool AuraScript::_Load(Aura* aura)
{
m_aura = aura;
@@ -837,6 +852,7 @@ bool AuraScript::_IsDefaultActionPrevented()
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
return m_defaultActionPrevented;
default:
ASSERT(false && "AuraScript::_IsDefaultActionPrevented is called in a wrong place");
@@ -852,6 +868,7 @@ void AuraScript::PreventDefaultAction()
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
m_defaultActionPrevented = true;
break;
default:
@@ -1033,6 +1050,7 @@ Unit* AuraScript::GetTarget() const
case AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB:
case AURA_SCRIPT_HOOK_EFFECT_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD:
case AURA_SCRIPT_HOOK_EFFECT_SPLIT:
return m_auraApplication->GetTarget();
default:
sLog->outError(LOG_FILTER_TSCR, "Script: `%s` Spell: `%u` AuraScript::GetTarget called in a hook in which the call won't have effect!", m_scriptName->c_str(), m_scriptSpellId);
+17
View File
@@ -423,6 +423,7 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB,
AURA_SCRIPT_HOOK_EFFECT_MANASHIELD,
AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD,
AURA_SCRIPT_HOOK_EFFECT_SPLIT,
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
AURA_SCRIPT_HOOK_DISPEL,
AURA_SCRIPT_HOOK_AFTER_DISPEL
@@ -449,6 +450,7 @@ class AuraScript : public _SpellScript
typedef void(CLASSNAME::*AuraEffectCalcPeriodicFnType)(AuraEffect const*, bool &, int32 &); \
typedef void(CLASSNAME::*AuraEffectCalcSpellModFnType)(AuraEffect const*, SpellModifier* &); \
typedef void(CLASSNAME::*AuraEffectAbsorbFnType)(AuraEffect*, DamageInfo &, uint32 &); \
typedef void(CLASSNAME::*AuraEffectSplitFnType)(AuraEffect*, DamageInfo &, uint32 &); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -540,6 +542,14 @@ class AuraScript : public _SpellScript
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
};
class EffectSplitHandler : public EffectBase
{
public:
EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex);
void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & splitAmount);
private:
AuraEffectSplitFnType pEffectHandlerScript;
};
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
@@ -552,6 +562,7 @@ class AuraScript : public _SpellScript
class EffectApplyHandlerFunction : public AuraScript::EffectApplyHandler { public: EffectApplyHandlerFunction(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode) : AuraScript::EffectApplyHandler((AuraScript::AuraEffectApplicationModeFnType)_pEffectHandlerScript, _effIndex, _effName, _mode) {} }; \
class EffectAbsorbFunction : public AuraScript::EffectAbsorbHandler { public: EffectAbsorbFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectAbsorbHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectManaShieldFunction : public AuraScript::EffectManaShieldHandler { public: EffectManaShieldFunction(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectManaShieldHandler((AuraScript::AuraEffectAbsorbFnType)_pEffectHandlerScript, _effIndex) {} }; \
class EffectSplitFunction : public AuraScript::EffectSplitHandler { public: EffectSplitFunction(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex) : AuraScript::EffectSplitHandler((AuraScript::AuraEffectSplitFnType)_pEffectHandlerScript, _effIndex) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
@@ -676,6 +687,12 @@ class AuraScript : public _SpellScript
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
HookList<EffectManaShieldHandler> AfterEffectManaShield;
// executed when the caster of some spell with split dmg aura gets damaged through it
// example: OnEffectSplit += AuraEffectSplitFn(class::function, EffectIndexSpecifier);
// where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount);
HookList<EffectSplitHandler> OnEffectSplit;
#define AuraEffectSplitFn(F, I) EffectSplitFunction(&F, I)
// AuraScript interface - hook/effect execution manipulators
// prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented)
@@ -47,6 +47,8 @@ enum PaladinSpells
SPELL_FORBEARANCE = 25771,
SPELL_AVENGING_WRATH_MARKER = 61987,
SPELL_IMMUNE_SHIELD_MARKER = 61988,
SPELL_HAND_OF_SACRIFICE = 6940,
};
// 31850 - Ardent Defender
@@ -566,6 +568,52 @@ class spell_pal_exorcism_and_holy_wrath_damage : public SpellScriptLoader
}
};
class spell_pal_hand_of_sacrifice : public SpellScriptLoader
{
public:
spell_pal_hand_of_sacrifice() : SpellScriptLoader("spell_pal_hand_of_sacrifice") { }
class spell_pal_hand_of_sacrifice_AuraScript : public AuraScript
{
PrepareAuraScript(spell_pal_hand_of_sacrifice_AuraScript);
uint32 splitPct;
int32 remainingAmount;
Unit* caster;
bool Load()
{
caster = GetCaster();
if (!caster)
return false;
remainingAmount = caster->GetMaxHealth();
splitPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
return true;
}
void Split(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & splitAmount)
{
remainingAmount -= splitAmount;
if (remainingAmount <= 0)
{
Unit* target = GetTarget();
target->RemoveAura(SPELL_HAND_OF_SACRIFICE);
}
}
void Register()
{
OnEffectSplit += AuraEffectSplitFn(spell_pal_hand_of_sacrifice_AuraScript::Split, EFFECT_0);
}
};
AuraScript* GetAuraScript() const
{
return new spell_pal_hand_of_sacrifice_AuraScript();
}
};
void AddSC_paladin_spell_scripts()
{
new spell_pal_ardent_defender();
@@ -579,4 +627,5 @@ void AddSC_paladin_spell_scripts()
new spell_pal_lay_on_hands();
new spell_pal_righteous_defense();
new spell_pal_exorcism_and_holy_wrath_damage();
new spell_pal_hand_of_sacrifice();
}