aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorQAston <none@none>2010-12-27 20:14:54 +0100
committerQAston <none@none>2010-12-27 20:14:54 +0100
commitef968f4b1552c2f1673a2ec79d8cd6b1ec9c2d11 (patch)
treed9909a464e9131ffdbe3a6577f0c907560e5f799 /src/server/game
parentda8d794f4bd6765c45847d93626057e272f7358e (diff)
Core/Unit: Big cleanup in Unit::CalcAbsorbResist
Core/AuraScript: Fix compile time check for AuraScript functions Remove AuraApplication from hook functions parameter list, use GetTarget() and GetTargetApplication() instead Add OnEffectAbsorb hook Scripts: move handlers of Spell Deflection, Savage Defense, Primal Tenacity, Nerves of Steel, Astral shift from core to scripts. --HG-- branch : trunk
Diffstat (limited to 'src/server/game')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp439
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h57
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h2
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp35
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.h1
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp44
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h76
7 files changed, 337 insertions, 317 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 44659254e7c..ab0eb074506 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -1548,6 +1548,8 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
if (!pVictim || !pVictim->isAlive() || !damage)
return;
+ DamageInfo dmgInfo = DamageInfo(this, pVictim, damage, spellInfo, schoolMask, damagetype);
+
// Magic damage, check for resists
if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
{
@@ -1591,32 +1593,25 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
probabilitySum += discreteResistProbability[i];
}
- uint32 damageResisted = damage * i / 10;
-
- *resist += damageResisted;
+ float damageResisted = damage * i / 10;
AuraEffectList const &ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
{
if ((*j)->GetMiscValue() & schoolMask
&& (*j)->IsAffectedOnSpell(spellInfo))
- AddPctN(*resist, -(*j)->GetAmount());
+ AddPctN(damageResisted, -(*j)->GetAmount());
}
AuraEffectList const &ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
{
if ((*j)->GetMiscValue() & schoolMask)
- AddPctN(*resist, -(*j)->GetAmount());
+ AddPctN(damageResisted, -(*j)->GetAmount());
}
+ dmgInfo.ResistDamage(damageResisted);
}
- else
- *resist = 0;
- int32 RemainingDamage = damage - *resist;
- int32 TotalAbsorb = RemainingDamage;
- // Get unit state (need for some absorb check)
- uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS);
// Death Prevention Aura
SpellEntry const* preventDeathSpell = NULL;
int32 preventDeathAmount = 0;
@@ -1625,7 +1620,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
int32 incanterAbsorption = 0;
// Ignore Absorption Auras
- int32 auraAbsorbMod = 0;
+ float auraAbsorbMod = 0;
AuraEffectList const & AbsIgnoreAurasA = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL);
for (AuraEffectList::const_iterator itr = AbsIgnoreAurasA.begin(); itr != AbsIgnoreAurasA.end(); ++itr)
{
@@ -1645,6 +1640,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
auraAbsorbMod = (*itr)->GetAmount();
}
+ RoundToInterval(auraAbsorbMod, 0.0f, 100.0f);
// We're going to call functions which can modify content of the list during iteration over it's elements
// Let's copy the list so we can prevent iterator invalidation
@@ -1652,80 +1648,39 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
vSchoolAbsorbCopy.sort(Trinity::AbsorbAuraOrderPred());
// absorb without mana cost
- for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (RemainingDamage > 0); ++itr)
+ for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
{
AuraEffect * absorbAurEff = (*itr);
// Check if aura was removed during iteration - we don't need to work on such auras
- if (!(absorbAurEff->GetBase()->IsAppliedOnTarget(pVictim->GetGUID())))
+ AuraApplication const * aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(pVictim->GetGUID());
+ if (!aurApp)
continue;
if (!(absorbAurEff->GetMiscValue() & schoolMask))
continue;
SpellEntry const * spellProto = absorbAurEff->GetSpellProto();
- // Frost Warding
- // Chaos Bolt ignore the absorption but still proc Frost Warding mana return
- if ((spellProto->SpellFamilyName == SPELLFAMILY_MAGE) && (spellProto->Category == 56))
- if (AuraEffect * aurEff = pVictim->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_MAGE, 501, EFFECT_0))
- {
- int32 chance = SpellMgr::CalculateSpellEffectAmount(aurEff->GetSpellProto(), EFFECT_1);
+ // get amount which can be still absorbed by the aura
+ int32 currentAbsorb = absorbAurEff->GetAmount();
+ // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety
+ if (currentAbsorb < 0)
+ currentAbsorb = 0;
- if (roll_chance_i(chance))
- {
- pVictim->CastCustomSpell(pVictim, 57776, &RemainingDamage, NULL, NULL, true, NULL, absorbAurEff);
- RemainingDamage = RemainingDamage * auraAbsorbMod / 100;
- continue;
- }
- }
+ uint32 absorb = currentAbsorb;
- if (auraAbsorbMod >= 100) // Do nothing if 100% absorb ignore
- continue;
+ bool defaultPrevented = false;
- // Max Amount can be absorbed by this aura
- int32 currentAbsorb = absorbAurEff->GetAmount();
- // Found empty aura
- if (currentAbsorb <= 0)
- {
- absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
- continue;
- }
-
- currentAbsorb = (100 - auraAbsorbMod) * currentAbsorb / 100;
+ absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, absorb, defaultPrevented);
- // Handle custom absorb auras
- // TODO: try find better way
+ currentAbsorb = absorb;
switch (spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
- // Astral Shift
- if (spellProto->SpellIconID == 3066)
- {
- //reduces all damage taken while stun, fear or silence
- if (unitflag & (UNIT_FLAG_STUNNED | UNIT_FLAG_FLEEING | UNIT_FLAG_SILENCED))
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
- }
- // Nerves of Steel
- if (spellProto->SpellIconID == 2115)
- {
- // while affected by Stun and Fear
- if (unitflag & (UNIT_FLAG_STUNNED | UNIT_FLAG_FLEEING))
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
- }
- // Spell Deflection
- if (spellProto->SpellIconID == 3006)
- {
- // You have a chance equal to your Parry chance
- if ((damagetype == DIRECT_DAMAGE) && roll_chance_f(pVictim->GetUnitParryChance()))
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
- }
// Reflective Shield (Lady Malande boss)
if (spellProto->Id == 41475)
{
- int32 bp = std::min(RemainingDamage, currentAbsorb) / 2;
+ int32 bp = std::min(int32(dmgInfo.GetDamage()), currentAbsorb) / 2;
pVictim->CastCustomSpell(this, 33619, &bp, NULL, NULL, true, NULL, *itr);
break;
}
@@ -1740,34 +1695,25 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
}
break;
}
- case SPELLFAMILY_DRUID:
+ case SPELLFAMILY_MAGE:
{
- // Primal Tenacity
- if (spellProto->SpellIconID == 2253)
+ // possibly create BeforeEffectAbsorb for this?
+ // Frost ward and Fire Ward
+ if (spellProto->Category == 56)
{
- //reduces all damage taken while Stunned
- if ((pVictim->GetShapeshiftForm() == FORM_CAT) && (unitflag & UNIT_FLAG_STUNNED))
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
- }
- // Savage Defense
- if (spellProto->SpellIconID == 146)
- {
- if (RemainingDamage < currentAbsorb)
- currentAbsorb = RemainingDamage;
-
- RemainingDamage -= currentAbsorb;
+ // Frost Warding
+ if (AuraEffect * aurEff = pVictim->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_MAGE, 501, EFFECT_0))
+ {
+ int32 chance = SpellMgr::CalculateSpellEffectAmount(aurEff->GetSpellProto(), EFFECT_1);
- absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL); // guarantee removal
- continue;
- }
- // Moonkin Form passive
- if (spellProto->Id == 69366)
- {
- //reduces all damage taken while Stunned
- if (unitflag & UNIT_FLAG_STUNNED)
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
+ if (roll_chance_i(chance))
+ {
+ int32 bp = dmgInfo.GetDamage();
+ pVictim->CastCustomSpell(pVictim, 57776, &bp, NULL, NULL, true, NULL, absorbAurEff);
+ dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
+ continue;
+ }
+ }
}
break;
}
@@ -1809,7 +1755,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
case 5065: // Rank 1
case 5064: // Rank 2
{
- int32 bp = CalculatePctN(std::min(RemainingDamage, currentAbsorb), aurEff->GetAmount());
+ int32 bp = CalculatePctN(std::min(int32(dmgInfo.GetDamage()), currentAbsorb), aurEff->GetAmount());
pVictim->CastCustomSpell(this, 33619, &bp, NULL, NULL, true, NULL, *itr);
break;
}
@@ -1828,13 +1774,13 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
if (!pVictim->ToPlayer())
continue;
- int32 remainingHealth = pVictim->GetHealth() - RemainingDamage;
+ int32 remainingHealth = pVictim->GetHealth() - dmgInfo.GetDamage();
uint32 allowedHealth = pVictim->CountPctFromMaxHealth(35);
// If damage kills us
if (remainingHealth <= 0 && !pVictim->ToPlayer()->HasSpellCooldown(66235))
{
// Cast healing spell, completely avoid damage
- RemainingDamage = 0;
+ dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
uint32 defenseSkillValue = pVictim->GetDefenseSkillValue();
// Max heal when defense skill denies critical hits from raid bosses
@@ -1852,26 +1798,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
{
// Reduce damage that brings us under 35% (or full damage if we are already under 35%) by x%
uint32 damageToReduce = (pVictim->GetHealth() < allowedHealth)
- ? RemainingDamage
+ ? dmgInfo.GetDamage()
: allowedHealth - remainingHealth;
- RemainingDamage -= CalculatePctN(damageToReduce, currentAbsorb);
+ dmgInfo.AbsorbDamage(CalculatePctN(damageToReduce, currentAbsorb));
}
continue;
}
break;
}
- case SPELLFAMILY_SHAMAN:
- {
- // Astral Shift
- if (spellProto->SpellIconID == 3066)
- {
- //reduces all damage taken while stun, fear or silence
- if (unitflag & (UNIT_FLAG_STUNNED | UNIT_FLAG_FLEEING | UNIT_FLAG_SILENCED))
- AddPctN(RemainingDamage, -currentAbsorb);
- continue;
- }
- break;
- }
case SPELLFAMILY_DEATHKNIGHT:
{
switch (spellProto->Id)
@@ -1885,14 +1819,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
if (AuraEffect const * aurEff = caster->GetAuraEffect(58635, 0))
AddPctN(absorbed, aurEff->GetAmount());
- RemainingDamage -= absorbed;
+ dmgInfo.AbsorbDamage(absorbed);
}
continue;
case 52284: // Will of the Necropolis
case 52285:
case 52286:
{
- int32 remainingHp = int32(pVictim->GetHealth() - RemainingDamage);
+ int32 remainingHp = int32(pVictim->GetHealth() - dmgInfo.GetDamage());
// min pct of hp is stored in effect 0 of talent spell
uint32 rank = sSpellMgr->GetSpellRank(spellProto->Id);
@@ -1902,8 +1836,8 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
// Damage that would take you below [effect0] health or taken while you are at [effect0]
if (remainingHp < minHp)
{
- uint32 absorbed = uint32(currentAbsorb * RemainingDamage * 0.01f);
- RemainingDamage -= absorbed;
+ uint32 absorbed = uint32(currentAbsorb * dmgInfo.GetDamage() * 0.01f);
+ dmgInfo.AbsorbDamage(absorbed);
}
continue;
}
@@ -1911,24 +1845,24 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
{
// damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
// This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power.
- int32 absorbed = CalculatePctN(RemainingDamage, currentAbsorb);
- RemainingDamage -= absorbed;
+ int32 absorbed = CalculatePctN(dmgInfo.GetDamage(), currentAbsorb);
+ dmgInfo.AbsorbDamage(absorbed);
int32 bp = absorbed * 2 / 10;
pVictim->CastCustomSpell(pVictim, 49088, &bp, NULL, NULL, true, NULL, *itr);
continue;
}
case 50462: // Anti-Magic Shell (on single party/raid member)
- AddPctN(RemainingDamage, -currentAbsorb);
+ dmgInfo.AbsorbDamage(CalculatePctN(dmgInfo.GetDamage(), currentAbsorb));
continue;
case 50461: // Anti-Magic Zone
if (Unit * caster = absorbAurEff->GetCaster())
{
- int32 absorbed = CalculatePctN(RemainingDamage, currentAbsorb);
+ int32 absorbed = CalculatePctN(dmgInfo.GetDamage(), currentAbsorb);
int32 canabsorb = caster->GetHealth();
if (canabsorb < absorbed)
absorbed = canabsorb;
- RemainingDamage -= absorbed;
+ dmgInfo.AbsorbDamage(absorbed);
}
continue;
default:
@@ -1940,163 +1874,154 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
break;
}
- // currentAbsorb - damage can be absorbed by shield
- // If need absorb less damage
- if (RemainingDamage < currentAbsorb)
- currentAbsorb = RemainingDamage;
+ if (defaultPrevented)
+ continue;
+
+ // Apply absorb mod auras
+ AddPctF(currentAbsorb, -auraAbsorbMod);
+
+ // absorb must be smaller than the damage itself
+ currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
- RemainingDamage -= currentAbsorb;
+ dmgInfo.AbsorbDamage(currentAbsorb);
// Fire Ward or Frost Ward or Ice Barrier (or Mana Shield)
// for Incanter's Absorption converting to spell power
- if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellFamilyFlags[EFFECT_2] & 0x8)
+ if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellFamilyFlags[2] & 0x8)
incanterAbsorption += currentAbsorb;
- // Reduce shield amount
- absorbAurEff->SetAmount(absorbAurEff->GetAmount() - currentAbsorb);
- // Need remove it later
- if (absorbAurEff->GetAmount() <= 0)
- absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
+ // Check if our aura is using amount to count damage
+ if (absorbAurEff->GetAmount() >= 0)
+ {
+ // Reduce shield amount
+ absorbAurEff->SetAmount(absorbAurEff->GetAmount() - currentAbsorb);
+ // Aura cannot absorb anything more - remove it
+ if (absorbAurEff->GetAmount() <= 0)
+ absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
+ }
}
-
if (auraAbsorbMod < 100) // Do nothing if 100% absorb ignore
{
- bool existExpired = false;
-
// absorb by mana cost
- AuraEffectList const & vManaShield = pVictim->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD);
-
- for (AuraEffectList::const_iterator itr = vManaShield.begin(); (itr != vManaShield.end()) && (RemainingDamage > 0); ++itr)
+ AuraEffectList vManaShieldCopy(pVictim->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD));
+ for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
{
+ AuraEffect * absorbAurEff = *itr;
+ // Check if aura was removed during iteration - we don't need to work on such auras
+ if (!(absorbAurEff->GetBase()->IsAppliedOnTarget(pVictim->GetGUID())))
+ continue;
// check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
+ if (!(absorbAurEff->GetMiscValue() & schoolMask))
continue;
- int32 currentAbsorb;
+ // get amount which can be still absorbed by the aura
+ int32 currentAbsorb = absorbAurEff->GetAmount();
- if (RemainingDamage >= (*itr)->GetAmount())
- currentAbsorb = (*itr)->GetAmount();
- else
- currentAbsorb = RemainingDamage;
+ AddPctF(currentAbsorb, -auraAbsorbMod);
- currentAbsorb = (100 - auraAbsorbMod) * currentAbsorb / 100;
+ // absorb must be smaller than the damage itself
+ currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
- if (float manaMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier((*itr)->GetSpellProto(), (*itr)->GetEffIndex(), (*itr)->GetCaster()))
- {
- int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier);
- if (currentAbsorb > maxAbsorb)
- currentAbsorb = maxAbsorb;
+ int32 manaReduction = currentAbsorb;
- int32 manaReduction = int32(currentAbsorb * manaMultiplier);
- pVictim->ApplyPowerMod(POWER_MANA, manaReduction, false);
- }
+ // lower absorb amount by talents
+ if (float manaMultiplier = SpellMgr::CalculateSpellEffectValueMultiplier(absorbAurEff->GetSpellProto(), absorbAurEff->GetEffIndex(), absorbAurEff->GetCaster()))
+ manaReduction = float(manaReduction) * manaMultiplier;
+
+ int32 manaTaken = -pVictim->ModifyPower(POWER_MANA, -manaReduction);
+
+ // take case when mana has ended up into account
+ currentAbsorb = float(currentAbsorb)*(float(manaTaken) / float(manaReduction));
// Mana Shield (or Fire Ward or Frost Ward or Ice Barrier)
// for Incanter's Absorption converting to spell power
- if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && (*itr)->GetSpellProto()->SpellFamilyFlags[EFFECT_2] & 0x8)
+ if (absorbAurEff->GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && absorbAurEff->GetSpellProto()->SpellFamilyFlags[2] & 0x8)
incanterAbsorption += currentAbsorb;
- (*itr)->SetAmount((*itr)->GetAmount() - currentAbsorb);
- if (((*itr)->GetAmount() <= 0) || (pVictim->GetPower(POWER_MANA) <= 1))
- existExpired = true;
+ dmgInfo.AbsorbDamage(currentAbsorb);
- RemainingDamage -= currentAbsorb;
+ absorbAurEff->SetAmount(absorbAurEff->GetAmount() - currentAbsorb);
+ if ((absorbAurEff->GetAmount() <= 0))
+ absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
}
-
- if (existExpired)
- for (AuraEffectList::const_iterator itr = vManaShield.begin(); itr != vManaShield.end();)
- {
- AuraEffect * auraEff = (*itr);
- ++itr;
-
- if ((auraEff->GetAmount() <= 0) || (pVictim->GetPower(POWER_MANA) <= 1))
- {
- uint32 removedAuras = pVictim->m_removedAurasCount;
- auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
- if (removedAuras + 1 < pVictim->m_removedAurasCount)
- itr = vManaShield.begin();
- }
- }
}
- // Do nothing if 100% absorb ignore
- if (auraAbsorbMod < 100)
- if (pVictim != this) // only split damage if not damaging yourself
+ // split damage auras - only when not damaging self
+ if (pVictim != this)
+ {
+ // We're going to call functions which can modify content of the list during iteration over it's elements
+ // Let's copy the list so we can prevent iterator invalidation
+ AuraEffectList vSplitDamageFlatCopy(pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
+ for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
{
- // We're going to call functions which can modify content of the list during iteration over it's elements
- // Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamageFlatCopy(pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
- for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (RemainingDamage >= 0); ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(pVictim->GetGUID())))
- continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
+ // Check if aura was removed during iteration - we don't need to work on such auras
+ if (!((*itr)->GetBase()->IsAppliedOnTarget(pVictim->GetGUID())))
+ continue;
+ // check damage school mask
+ if (!((*itr)->GetMiscValue() & schoolMask))
+ continue;
- // Damage can be splitted only if aura has an alive caster
- Unit * caster = (*itr)->GetCaster();
- if (!caster || (caster == pVictim) || !caster->IsInWorld() || !caster->isAlive())
- continue;
+ // Damage can be splitted only if aura has an alive caster
+ Unit * caster = (*itr)->GetCaster();
+ if (!caster || (caster == pVictim) || !caster->IsInWorld() || !caster->isAlive())
+ continue;
- int32 currentAbsorb;
- if (RemainingDamage >= (*itr)->GetAmount())
- currentAbsorb = (*itr)->GetAmount();
- else
- currentAbsorb = RemainingDamage;
- currentAbsorb = (100 - auraAbsorbMod) * currentAbsorb / 100;
+ int32 splitDamage = (*itr)->GetAmount();
- RemainingDamage -= currentAbsorb;
+ // absorb must be smaller than the damage itself
+ splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
- uint32 splitted = currentAbsorb;
- uint32 splitted_absorb = 0;
- DealDamageMods(caster, splitted, &splitted_absorb);
+ dmgInfo.ModifyDamage(-splitDamage);
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
+ uint32 splitted = splitDamage;
+ uint32 splitted_absorb = 0;
+ DealDamageMods(caster, splitted, &splitted_absorb);
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellProto(), false);
- }
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
- // We're going to call functions which can modify content of the list during iteration over it's elements
- // Let's copy the list so we can prevent iterator invalidation
- AuraEffectList vSplitDamagePctCopy(pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
- for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (RemainingDamage >= 0); ++itr)
- {
- // Check if aura was removed during iteration - we don't need to work on such auras
- if (!((*itr)->GetBase()->IsAppliedOnTarget(pVictim->GetGUID())))
- continue;
- // check damage school mask
- if (!((*itr)->GetMiscValue() & schoolMask))
- continue;
+ CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellProto(), false);
+ }
- // Damage can be splitted only if aura has an alive caster
- Unit * caster = (*itr)->GetCaster();
- if (!caster || (caster == pVictim) || !caster->IsInWorld() || !caster->isAlive())
- continue;
+ // We're going to call functions which can modify content of the list during iteration over it's elements
+ // Let's copy the list so we can prevent iterator invalidation
+ AuraEffectList vSplitDamagePctCopy(pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
+ 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(pVictim->GetGUID())))
+ continue;
+ // check damage school mask
+ if (!((*itr)->GetMiscValue() & schoolMask))
+ continue;
- uint32 splitted = CalculatePctN(RemainingDamage, (*itr)->GetAmount());
- AddPctN(splitted, -auraAbsorbMod);
+ // Damage can be splitted only if aura has an alive caster
+ Unit * caster = (*itr)->GetCaster();
+ if (!caster || (caster == pVictim) || !caster->IsInWorld() || !caster->isAlive())
+ continue;
- RemainingDamage -= int32(splitted);
+ int32 splitDamage = CalculatePctN(dmgInfo.GetDamage(), (*itr)->GetAmount());
- uint32 split_absorb = 0;
- DealDamageMods(caster, splitted, &split_absorb);
+ // absorb must be smaller than the damage itself
+ splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
- SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
+ dmgInfo.ModifyDamage(-splitDamage);
- CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
- DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellProto(), false);
- }
- }
+ uint32 splitted = splitDamage;
+ uint32 split_absorb = 0;
+ DealDamageMods(caster, splitted, &split_absorb);
- TotalAbsorb = (TotalAbsorb - RemainingDamage > 0) ? TotalAbsorb - RemainingDamage : 0;
+ SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
+
+ CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
+ DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellProto(), false);
+ }
+ }
// Apply death prevention spells effects
if (auraAbsorbMod < 100) // Do nothing if 100% absorb ignore
- if (preventDeathSpell && (RemainingDamage >= int32(pVictim->GetHealth())))
+ if (preventDeathSpell && (dmgInfo.GetDamage() >= int32(pVictim->GetHealth())))
{
switch(preventDeathSpell->SpellFamilyName)
{
@@ -2108,9 +2033,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
pVictim->CastSpell(pVictim, 31231, true);
pVictim->ToPlayer()->AddSpellCooldown(31231, 0, time(NULL) + 60);
- // with health > 10% lost health until health == 10%, in other case no losses
uint32 health10 = pVictim->CountPctFromMaxHealth(10);
- RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
+
+ // hp > 10% - absorb hp till 10%
+ if (pVictim->GetHealth() > health10)
+ dmgInfo.AbsorbDamage(dmgInfo.GetDamage() - pVictim->GetHealth() + health10);
+ // hp lower than 10% - absorb everything
+ else
+ dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
}
break;
}
@@ -2122,14 +2052,15 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff
int32 healAmount = int32(pVictim->CountPctFromMaxHealth(preventDeathAmount));
pVictim->RemoveAurasDueToSpell(preventDeathSpell->Id);
pVictim->CastCustomSpell(pVictim, 48153, &healAmount, NULL, NULL, true);
- RemainingDamage = 0;
+ dmgInfo.AbsorbDamage(dmgInfo.GetDamage());
}
break;
}
}
}
- *absorb = RemainingDamage > 0 ? (damage - RemainingDamage - *resist) : (damage - *resist);
+ *resist = dmgInfo.GetResist();
+ *absorb = dmgInfo.GetAbsorb();
// Incanter's Absorption, if have affective absorbing
if (incanterAbsorption)
@@ -13550,50 +13481,6 @@ void Unit::SetMaxPower(Powers power, uint32 val)
SetPower(power, val);
}
-void Unit::ApplyPowerMod(Powers power, uint32 val, bool apply)
-{
- ApplyModUInt32Value(UNIT_FIELD_POWER1+power, val, apply);
-
- // group update
- if (GetTypeId() == TYPEID_PLAYER)
- {
- if (this->ToPlayer()->GetGroup())
- this->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
- }
- else if (this->ToCreature()->isPet())
- {
- Pet *pet = ((Pet*)this);
- if (pet->isControlled())
- {
- Unit *owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
- }
- }
-}
-
-void Unit::ApplyMaxPowerMod(Powers power, uint32 val, bool apply)
-{
- ApplyModUInt32Value(UNIT_FIELD_MAXPOWER1+power, val, apply);
-
- // group update
- if (GetTypeId() == TYPEID_PLAYER)
- {
- if (this->ToPlayer()->GetGroup())
- this->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
- }
- else if (this->ToCreature()->isPet())
- {
- Pet *pet = ((Pet*)this);
- if (pet->isControlled())
- {
- Unit *owner = GetOwner();
- if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
- owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
- }
- }
-}
-
uint32 Unit::GetCreatePowers(Powers power) const
{
// POWER_FOCUS and POWER_HAPPINESS only have hunter pet
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 15b248a5fff..465ab7aa729 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -806,6 +806,60 @@ struct CleanDamage
MeleeHitOutcome hitOutCome;
};
+class DamageInfo
+{
+private:
+ Unit * const m_attacker;
+ Unit * const m_victim;
+ DamageEffectType const m_damageType;
+ SpellEntry const * const m_spellInfo;
+ SpellSchoolMask const m_schoolMask;
+ uint32 m_damage;
+ uint32 m_absorb;
+ uint32 m_resist;
+ uint32 m_block;
+public:
+ explicit DamageInfo(Unit * _attacker, Unit * _victim, uint32 _damage, SpellEntry const * _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType)
+ : m_attacker(_attacker), m_victim(_victim), m_damage(_damage), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask), m_damageType(_damageType)
+ {
+ m_absorb = 0;
+ m_resist = 0;
+ m_block = 0;
+ }
+ void ModifyDamage(int32 amount)
+ {
+ amount = std::min(amount, int32(GetDamage()));
+ m_damage += amount;
+ }
+ void AbsorbDamage(uint32 amount)
+ {
+ amount = std::min(amount, GetDamage());
+ m_absorb += amount;
+ m_damage -= amount;
+ }
+ void ResistDamage(uint32 amount)
+ {
+ amount = std::min(amount, GetDamage());
+ m_resist += amount;
+ m_damage -= amount;
+ }
+ void BlockDamage(uint32 amount)
+ {
+ amount = std::min(amount, GetDamage());
+ m_block += amount;
+ m_damage -= amount;
+ }
+ Unit * GetAttacker() const { return m_attacker; };
+ Unit * GetVictim() const { return m_victim; };
+ DamageEffectType const GetDamageType() const { return m_damageType; };
+ SpellEntry const * GetSpellInfo() const { return m_spellInfo; };
+ SpellSchoolMask const GetSchoolMask() const { return m_schoolMask; };
+ uint32 GetDamage() const { return m_damage; };
+ uint32 GetAbsorb() const { return m_absorb; };
+ uint32 GetResist() const { return m_resist; };
+ uint32 GetBlock() const { return m_block; };
+};
+
// Struct for use in Unit::CalculateMeleeDamage
// Need create structure like in SMSG_ATTACKERSTATEUPDATE opcode
struct CalcDamageInfo
@@ -1214,9 +1268,8 @@ class Unit : public WorldObject
uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); }
void SetPower(Powers power, uint32 val);
void SetMaxPower(Powers power, uint32 val);
+ // returns the change in power
int32 ModifyPower(Powers power, int32 val);
- void ApplyPowerMod(Powers power, uint32 val, bool apply);
- void ApplyMaxPowerMod(Powers power, uint32 val, bool apply);
uint32 GetAttackTime(WeaponAttackType att) const
{
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index 80809c9d0bb..02b5825d5ec 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -60,6 +60,7 @@ class AuraEffect
void ResetPeriodic(bool resetPeriodicTimer = false) { if (resetPeriodicTimer) m_periodicTimer = m_amplitude; m_tickNumber = 0;}
bool IsPeriodic() const { return m_isPeriodic; }
+ void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; }
bool IsAffectedOnSpell(SpellEntry const *spell) const;
void SendTickImmune(Unit * target, Unit *caster) const;
@@ -72,7 +73,6 @@ class AuraEffect
void CleanupTriggeredSpells(Unit * target);
- static bool IsPeriodicAuraType(uint32 type);
// add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras
void HandleShapeshiftBoosts(Unit * target, bool apply) const;
private:
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 4a7ec595f28..5068de484af 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -1656,12 +1656,12 @@ bool Aura::CallScriptEffectApplyHandlers(AuraEffect const * aurEff, AuraApplicat
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
- (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY);
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_APPLY, aurApp);
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectApply.end(), effItr = (*scritr)->OnEffectApply.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
- (*effItr).Call(*scritr, aurEff, aurApp, mode);
+ (*effItr).Call(*scritr, aurEff, mode);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented();
@@ -1675,12 +1675,12 @@ bool Aura::CallScriptEffectRemoveHandlers(AuraEffect const * aurEff, AuraApplica
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
- (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE);
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_REMOVE, aurApp);
std::list<AuraScript::EffectApplyHandler>::iterator effEndItr = (*scritr)->OnEffectRemove.end(), effItr = (*scritr)->OnEffectRemove.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
- (*effItr).Call(*scritr, aurEff, aurApp, mode);
+ (*effItr).Call(*scritr, aurEff, mode);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented();
@@ -1694,12 +1694,12 @@ bool Aura::CallScriptEffectPeriodicHandlers(AuraEffect const * aurEff, AuraAppli
bool preventDefault = false;
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
- (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC);
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_PERIODIC, aurApp);
std::list<AuraScript::EffectPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectPeriodic.end(), effItr = (*scritr)->OnEffectPeriodic.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
- (*effItr).Call(*scritr, aurEff, aurApp);
+ (*effItr).Call(*scritr, aurEff);
}
if (!preventDefault)
preventDefault = (*scritr)->_IsDefaultActionPrevented();
@@ -1728,7 +1728,7 @@ void Aura::CallScriptEffectCalcAmountHandlers(AuraEffect const * aurEff, int32 &
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT);
- std::list<AuraScript::EffectCalcAmountHandler>::iterator effEndItr = (*scritr)->OnEffectCalcAmount.end(), effItr = (*scritr)->OnEffectCalcAmount.begin();
+ std::list<AuraScript::EffectCalcAmountHandler>::iterator effEndItr = (*scritr)->DoEffectCalcAmount.end(), effItr = (*scritr)->DoEffectCalcAmount.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
@@ -1743,7 +1743,7 @@ void Aura::CallScriptEffectCalcPeriodicHandlers(AuraEffect const * aurEff, bool
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC);
- std::list<AuraScript::EffectCalcPeriodicHandler>::iterator effEndItr = (*scritr)->OnEffectCalcPeriodic.end(), effItr = (*scritr)->OnEffectCalcPeriodic.begin();
+ std::list<AuraScript::EffectCalcPeriodicHandler>::iterator effEndItr = (*scritr)->DoEffectCalcPeriodic.end(), effItr = (*scritr)->DoEffectCalcPeriodic.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
@@ -1758,7 +1758,7 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const * aurEff, Spell
for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
{
(*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD);
- std::list<AuraScript::EffectCalcSpellModHandler>::iterator effEndItr = (*scritr)->OnEffectCalcSpellMod.end(), effItr = (*scritr)->OnEffectCalcSpellMod.begin();
+ std::list<AuraScript::EffectCalcSpellModHandler>::iterator effEndItr = (*scritr)->DoEffectCalcSpellMod.end(), effItr = (*scritr)->DoEffectCalcSpellMod.begin();
for(; effItr != effEndItr ; ++effItr)
{
if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
@@ -1768,6 +1768,23 @@ void Aura::CallScriptEffectCalcSpellModHandlers(AuraEffect const * aurEff, Spell
}
}
+void Aura::CallScriptEffectAbsorbHandlers(AuraEffect * aurEff, AuraApplication const * aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented)
+{
+ for(std::list<AuraScript *>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_EFFECT_ABSORB, aurApp);
+ std::list<AuraScript::EffectAbsorbHandler>::iterator effEndItr = (*scritr)->OnEffectAbsorb.end(), effItr = (*scritr)->OnEffectAbsorb.begin();
+ for(; effItr != effEndItr ; ++effItr)
+ {
+ if ((*effItr).IsEffectAffected(m_spellProto, aurEff->GetEffIndex()))
+ (*effItr).Call(*scritr, aurEff, dmgInfo, absorbAmount);
+ }
+ if (!defaultPrevented)
+ defaultPrevented = (*scritr)->_IsDefaultActionPrevented();
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
UnitAura::UnitAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID)
: Aura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 6b619ef2e9a..ab9a56be7fc 100755
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -174,6 +174,7 @@ class Aura
void CallScriptEffectCalcAmountHandlers(AuraEffect const * aurEff, int32 & amount, bool & canBeRecalculated);
void CallScriptEffectCalcPeriodicHandlers(AuraEffect const * aurEff, bool & isPeriodic, int32 & amplitude);
void CallScriptEffectCalcSpellModHandlers(AuraEffect const * aurEff, SpellModifier *& spellMod);
+ void CallScriptEffectAbsorbHandlers(AuraEffect * aurEff, AuraApplication const * aurApp, DamageInfo & dmgInfo, uint32 & absorbAmount, bool & defaultPrevented);
std::list<AuraScript *> m_loadedScripts;
private:
void _DeleteRemovedApplications();
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index ade0c63b2b8..482a185f590 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -431,15 +431,19 @@ bool AuraScript::_Validate(SpellEntry const * entry)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcAmountHandler>::iterator itr = OnEffectCalcAmount.begin(); itr != OnEffectCalcAmount.end(); ++itr)
+ for (std::list<EffectCalcAmountHandler>::iterator itr = DoEffectCalcAmount.begin(); itr != DoEffectCalcAmount.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcPeriodicHandler>::iterator itr = OnEffectCalcPeriodic.begin(); itr != OnEffectCalcPeriodic.end(); ++itr)
+ for (std::list<EffectCalcPeriodicHandler>::iterator itr = DoEffectCalcPeriodic.begin(); itr != DoEffectCalcPeriodic.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
- for (std::list<EffectCalcSpellModHandler>::iterator itr = OnEffectCalcSpellMod.begin(); itr != OnEffectCalcSpellMod.end(); ++itr)
+ for (std::list<EffectCalcSpellModHandler>::iterator itr = DoEffectCalcSpellMod.begin(); itr != DoEffectCalcSpellMod.end(); ++itr)
+ if (!(*itr).GetAffectedEffectsMask(entry))
+ sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+
+ for (std::list<EffectAbsorbHandler>::iterator itr = OnEffectAbsorb.begin(); itr != OnEffectAbsorb.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script`%s` did not match dbc effect data - bound handler won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
@@ -467,9 +471,9 @@ AuraScript::EffectPeriodicHandler::EffectPeriodicHandler(AuraEffectPeriodicFnTyp
pEffectHandlerScript = _pEffectHandlerScript;
}
-void AuraScript::EffectPeriodicHandler::Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraApplication const * _aurApp)
+void AuraScript::EffectPeriodicHandler::Call(AuraScript * auraScript, AuraEffect const * _aurEff)
{
- (auraScript->*pEffectHandlerScript)(_aurEff, _aurApp);
+ (auraScript->*pEffectHandlerScript)(_aurEff);
}
AuraScript::EffectUpdatePeriodicHandler::EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName)
@@ -523,10 +527,21 @@ AuraScript::EffectApplyHandler::EffectApplyHandler(AuraEffectApplicationModeFnTy
mode = _mode;
}
-void AuraScript::EffectApplyHandler::Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraApplication const * _aurApp, AuraEffectHandleModes _mode)
+void AuraScript::EffectApplyHandler::Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraEffectHandleModes _mode)
{
if (_mode & mode)
- (auraScript->*pEffectHandlerScript)(_aurEff, _aurApp, _mode);
+ (auraScript->*pEffectHandlerScript)(_aurEff, _mode);
+}
+
+AuraScript::EffectAbsorbHandler::EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript,uint8 _effIndex)
+ : AuraScript::EffectBase(_effIndex, SPELL_AURA_SCHOOL_ABSORB)
+{
+ pEffectHandlerScript = _pEffectHandlerScript;
+}
+
+void AuraScript::EffectAbsorbHandler::Call(AuraScript * auraScript, AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
+{
+ (auraScript->*pEffectHandlerScript)(aurEff, dmgInfo, absorbAmount);
}
bool AuraScript::_Load(Aura * aura)
@@ -538,7 +553,7 @@ bool AuraScript::_Load(Aura * aura)
return load;
}
-void AuraScript::_PrepareScriptCall(AuraScriptHookType hookType)
+void AuraScript::_PrepareScriptCall(AuraScriptHookType hookType, AuraApplication const * aurApp)
{
m_currentScriptState = hookType;
switch (m_currentScriptState)
@@ -546,16 +561,19 @@ void AuraScript::_PrepareScriptCall(AuraScriptHookType hookType)
case AURA_SCRIPT_HOOK_EFFECT_APPLY:
case AURA_SCRIPT_HOOK_EFFECT_REMOVE:
case AURA_SCRIPT_HOOK_EFFECT_PERIODIC:
+ case AURA_SCRIPT_HOOK_EFFECT_ABSORB:
m_defaultActionPrevented = false;
break;
default:
break;
}
+ m_auraApplication = aurApp;
}
void AuraScript::_FinishScriptCall()
{
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
+ m_auraApplication = NULL;
}
bool AuraScript::_IsDefaultActionPrevented()
@@ -733,3 +751,13 @@ bool AuraScript::HasEffectType(AuraType type) const
return m_aura->HasEffectType(type);
}
+Unit * AuraScript::GetTarget() const
+{
+ return m_auraApplication->GetTarget();
+}
+
+AuraApplication const * AuraScript::GetTargetApplication() const
+{
+ return m_auraApplication;
+}
+
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 48971ffa64a..972f6794436 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -282,6 +282,7 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT,
AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC,
AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD,
+ AURA_SCRIPT_HOOK_EFFECT_ABSORB,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE,*/
};
@@ -296,12 +297,14 @@ class AuraScript : public _SpellScript
public:
#define AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \
- typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const *, AuraApplication const *, AuraEffectHandleModes mode); \
- typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const *, AuraApplication const *); \
+ typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const *, AuraEffectHandleModes); \
+ typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const *); \
typedef void(CLASSNAME::*AuraEffectUpdatePeriodicFnType)(AuraEffect *); \
typedef void(CLASSNAME::*AuraEffectCalcAmountFnType)(AuraEffect const *, int32 &, bool &); \
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::*AuraAbsorbFnType)(AuraEffect *, DamageInfo &); \
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
@@ -316,7 +319,7 @@ class AuraScript : public _SpellScript
{
public:
EffectPeriodicHandler(AuraEffectPeriodicFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName);
- void Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraApplication const * _aurApp);
+ void Call(AuraScript * auraScript, AuraEffect const * _aurEff);
private:
AuraEffectPeriodicFnType pEffectHandlerScript;
};
@@ -356,11 +359,19 @@ class AuraScript : public _SpellScript
{
public:
EffectApplyHandler(AuraEffectApplicationModeFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode);
- void Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraApplication const * _aurApp, AuraEffectHandleModes _mode);
+ void Call(AuraScript * auraScript, AuraEffect const * _aurEff, AuraEffectHandleModes _mode);
private:
AuraEffectApplicationModeFnType pEffectHandlerScript;
AuraEffectHandleModes mode;
};
+ class EffectAbsorbHandler : public EffectBase
+ {
+ public:
+ EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex);
+ void Call(AuraScript * auraScript, AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount);
+ private:
+ AuraEffectAbsorbFnType pEffectHandlerScript;
+ };
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class EffectPeriodicHandlerFunction : public AuraScript::EffectPeriodicHandler { public: EffectPeriodicHandlerFunction(AuraEffectPeriodicFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName) : AuraScript::EffectPeriodicHandler((AuraScript::AuraEffectPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
@@ -369,17 +380,19 @@ class AuraScript : public _SpellScript
class EffectCalcPeriodicHandlerFunction : public AuraScript::EffectCalcPeriodicHandler { public: EffectCalcPeriodicHandlerFunction(AuraEffectCalcPeriodicFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcPeriodicHandler((AuraScript::AuraEffectCalcPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
class EffectCalcSpellModHandlerFunction : public AuraScript::EffectCalcSpellModHandler { public: EffectCalcSpellModHandlerFunction(AuraEffectCalcSpellModFnType _pEffectHandlerScript,uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcSpellModHandler((AuraScript::AuraEffectCalcSpellModFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
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) {} }; \
#define PrepareAuraScript(CLASSNAME) AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME)
public:
bool _Validate(SpellEntry const * entry);
bool _Load(Aura * aura);
- void _PrepareScriptCall(AuraScriptHookType hookType);
+ void _PrepareScriptCall(AuraScriptHookType hookType, AuraApplication const * aurApp = NULL);
void _FinishScriptCall();
bool _IsDefaultActionPrevented();
private:
Aura * m_aura;
+ AuraApplication const * m_auraApplication;
bool m_defaultActionPrevented;
public:
//
@@ -388,44 +401,57 @@ class AuraScript : public _SpellScript
//
// executed when periodic aura effect is applied with specified mode to target
// example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
+ // where function is: void function (AuraEffect const * aurEff, AuraEffectHandleModes mode);
HookList<EffectApplyHandler> OnEffectApply;
- #define AuraEffectApplyFn(F, I, N, M) EffectApplyHandlerFunction((AuraEffectApplicationModeFnType)&F, I, N, M)
+ #define AuraEffectApplyFn(F, I, N, M) EffectApplyHandlerFunction(&F, I, N, M)
// executed when periodic aura effect is removed with specified mode from target
// example: OnEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
- // where function is: void function (AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode);
+ // where function is: void function (AuraEffect const * aurEff, AuraEffectHandleModes mode);
HookList<EffectApplyHandler> OnEffectRemove;
- #define AuraEffectRemoveFn(F, I, N, M) EffectApplyHandlerFunction((AuraEffectApplicationModeFnType)&F, I, N, M)
+ #define AuraEffectRemoveFn(F, I, N, M) EffectApplyHandlerFunction(&F, I, N, M)
// executed when periodic aura effect ticks on target
// example: OnEffectPeriodic += AuraEffectPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
- // where function is: void function (AuraEffect const * aurEff, AuraApplication const * aurApp, AuraEffectHandleModes mode);
+ // where function is: void function (AuraEffect const * aurEff, AuraEffectHandleModes mode);
HookList<EffectPeriodicHandler> OnEffectPeriodic;
- #define AuraEffectPeriodicFn(F, I, N) EffectPeriodicHandlerFunction((AuraEffectPeriodicFnType)&F, I, N)
+ #define AuraEffectPeriodicFn(F, I, N) EffectPeriodicHandlerFunction(&F, I, N)
// executed when periodic aura effect is updated
// example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
- // where function is: void function (AuraEffect const * aurEff, AuraApplication const * aurApp);
+ // where function is: void function (AuraEffect const * aurEff);
HookList<EffectUpdatePeriodicHandler> OnEffectUpdatePeriodic;
- #define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandlerFunction((AuraEffectUpdatePeriodicFnType)&F, I, N)
+ #define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandlerFunction(&F, I, N)
// executed when aura effect calculates amount
- // example: OnEffectCalcAmount += AuraEffectCalcAmounFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // example: DoEffectCalcAmount += AuraEffectCalcAmounFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect * aurEff, int32 & amount, bool & canBeRecalculated);
- HookList<EffectCalcAmountHandler> OnEffectCalcAmount;
- #define AuraEffectCalcAmountFn(F, I, N) EffectCalcAmountHandlerFunction((AuraEffectCalcAmountFnType)&F, I, N)
+ HookList<EffectCalcAmountHandler> DoEffectCalcAmount;
+ #define AuraEffectCalcAmountFn(F, I, N) EffectCalcAmountHandlerFunction(&F, I, N)
// executed when aura effect calculates periodic data
- // example: OnEffectCalcPeriodic += AuraEffectCalcPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // example: DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect const * aurEff, bool & isPeriodic, int32 & amplitude);
- HookList<EffectCalcPeriodicHandler> OnEffectCalcPeriodic;
- #define AuraEffectCalcPeriodicFn(F, I, N) EffectCalcPeriodicHandlerFunction((AuraEffectCalcPeriodicFnType)&F, I, N)
+ HookList<EffectCalcPeriodicHandler> DoEffectCalcPeriodic;
+ #define AuraEffectCalcPeriodicFn(F, I, N) EffectCalcPeriodicHandlerFunction(&F, I, N)
// executed when aura effect calculates spellmod
- // example: OnEffectCalcSpellMod += AuraEffectCalcSpellModFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
+ // example: DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
// where function is: void function (AuraEffect const * aurEff, SpellModifier *& spellMod);
- HookList<EffectCalcSpellModHandler> OnEffectCalcSpellMod;
- #define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandlerFunction((AuraEffectCalcSpellModFnType)&F, I, N)
+ HookList<EffectCalcSpellModHandler> DoEffectCalcSpellMod;
+ #define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandlerFunction(&F, I, N)
+
+ // executed when absorb aura effect is going to reduce damage
+ // example: OnEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
+ // where function is: void function (AuraEffect * aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount);
+ HookList<EffectAbsorbHandler> OnEffectAbsorb;
+ #define AuraEffectAbsorbFn(F, I) EffectAbsorbFunction(&F, I)
+
+ // executed after aura absorbtions reduced damage
+ // example: AfterAbsorb += AuraAbsorbFn(class::function);
+ // where function is: void function (AuraEffect * aurEff, DamageInfo & dmgInfo);
+ //HookList<AbsorbHandler> AfterAbsorb;
+ //#define AuraAbsorbFn(F) EffectAbsorbFunction(&F)
// AuraScript interface - hook/effect execution manipulators
@@ -494,6 +520,14 @@ class AuraScript : public _SpellScript
// check if aura has effect of given aura type
bool HasEffectType(AuraType type) const;
+
+ // AuraScript interface - functions which are redirecting to AuraApplication class
+ // Do not call these in hooks in which AuraApplication is not avalible, otherwise result will differ from expected (the functions will return NULL)
+
+ // returns currently processed target of an aura
+ Unit * GetTarget() const;
+ // returns AuraApplication object of currently processed target
+ AuraApplication const * GetTargetApplication() const;
};
//