aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells
diff options
context:
space:
mode:
authorMalcrom <malcromdev@gmail.com>2012-02-09 16:43:00 -0330
committerMalcrom <malcromdev@gmail.com>2012-02-09 16:43:00 -0330
commitb20c0a1770872caec0f9e8069241e23df005ba60 (patch)
treea4752d89d7bb49c133f12fd1ce66db2f9766fe2f /src/server/game/Spells
parent197b72ccb66083460dee8b542ede83c69259e096 (diff)
parent800cf737500048a0950dcde312b35be08e1ed006 (diff)
Merge branch 'master' of git://github.com/TrinityCore/TrinityCore
Diffstat (limited to 'src/server/game/Spells')
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp36
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.cpp36
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuras.h2
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp68
-rwxr-xr-xsrc/server/game/Spells/Spell.h2
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp63
-rw-r--r--src/server/game/Spells/SpellInfo.cpp17
-rw-r--r--src/server/game/Spells/SpellInfo.h5
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp4
-rwxr-xr-xsrc/server/game/Spells/SpellScript.cpp18
-rwxr-xr-xsrc/server/game/Spells/SpellScript.h23
11 files changed, 190 insertions, 84 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 7c09a2f32c6..1972b625a9f 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2417,7 +2417,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
target->VisitNearbyObject(target->GetMap()->GetVisibilityRange(), searcher);
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
{
- if (!(*iter)->HasUnitState(UNIT_STAT_CASTING))
+ if (!(*iter)->HasUnitState(UNIT_STATE_CASTING))
continue;
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
@@ -2448,7 +2448,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
// blizz like 2.0.x
target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- target->AddUnitState(UNIT_STAT_DIED);
+ target->AddUnitState(UNIT_STATE_DIED);
}
else
{
@@ -2465,7 +2465,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
// blizz like 2.0.x
target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
- target->ClearUnitState(UNIT_STAT_DIED);
+ target->ClearUnitState(UNIT_STATE_DIED);
}
}
@@ -3031,7 +3031,7 @@ void AuraEffect::HandleModConfuse(AuraApplication const* aurApp, uint8 mode, boo
Unit* target = aurApp->GetTarget();
- target->SetControlled(apply, UNIT_STAT_CONFUSED);
+ target->SetControlled(apply, UNIT_STATE_CONFUSED);
}
void AuraEffect::HandleModFear(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3041,7 +3041,7 @@ void AuraEffect::HandleModFear(AuraApplication const* aurApp, uint8 mode, bool a
Unit* target = aurApp->GetTarget();
- target->SetControlled(apply, UNIT_STAT_FLEEING);
+ target->SetControlled(apply, UNIT_STATE_FLEEING);
}
void AuraEffect::HandleAuraModStun(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3051,7 +3051,7 @@ void AuraEffect::HandleAuraModStun(AuraApplication const* aurApp, uint8 mode, bo
Unit* target = aurApp->GetTarget();
- target->SetControlled(apply, UNIT_STAT_STUNNED);
+ target->SetControlled(apply, UNIT_STATE_STUNNED);
}
void AuraEffect::HandleAuraModRoot(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3061,7 +3061,7 @@ void AuraEffect::HandleAuraModRoot(AuraApplication const* aurApp, uint8 mode, bo
Unit* target = aurApp->GetTarget();
- target->SetControlled(apply, UNIT_STAT_ROOT);
+ target->SetControlled(apply, UNIT_STATE_ROOT);
}
void AuraEffect::HandlePreventFleeing(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3072,7 +3072,7 @@ void AuraEffect::HandlePreventFleeing(AuraApplication const* aurApp, uint8 mode,
Unit* target = aurApp->GetTarget();
if (target->HasAuraType(SPELL_AURA_MOD_FEAR))
- target->SetControlled(!(apply), UNIT_STAT_FLEEING);
+ target->SetControlled(!(apply), UNIT_STATE_FLEEING);
}
/***************************/
@@ -3465,7 +3465,7 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
if (GetSpellInfo()->Mechanic == MECHANIC_BANISH)
{
if (apply)
- target->AddUnitState(UNIT_STAT_ISOLATED);
+ target->AddUnitState(UNIT_STATE_ISOLATED);
else
{
bool banishFound = false;
@@ -3477,7 +3477,7 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
break;
}
if (!banishFound)
- target->ClearUnitState(UNIT_STAT_ISOLATED);
+ target->ClearUnitState(UNIT_STATE_ISOLATED);
}
}
@@ -6156,7 +6156,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
if (!caster || !target->isAlive())
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
{
SendTickImmune(target, caster);
return;
@@ -6297,7 +6297,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
if (!caster || !caster->isAlive() || !target->isAlive())
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
{
SendTickImmune(target, caster);
return;
@@ -6363,7 +6363,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster)
if (!caster || !caster->isAlive() || !target->isAlive())
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED))
{
SendTickImmune(target, caster);
return;
@@ -6391,7 +6391,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
if (!caster || !target->isAlive())
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED))
{
SendTickImmune(target, caster);
return;
@@ -6507,7 +6507,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
if (!caster || !caster->isAlive() || !target->isAlive() || target->getPowerType() != powerType)
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
{
SendTickImmune(target, caster);
return;
@@ -6607,7 +6607,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
if (!target->isAlive() || !target->GetMaxPower(powerType))
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED))
{
SendTickImmune(target, caster);
return;
@@ -6638,7 +6638,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
if (!target->isAlive() || !target->GetMaxPower(powerType))
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED))
{
SendTickImmune(target, caster);
return;
@@ -6670,7 +6670,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
if (!caster || !target->isAlive() || target->getPowerType() != powerType)
return;
- if (target->HasUnitState(UNIT_STAT_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
+ if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamage(GetSpellInfo()))
{
SendTickImmune(target, caster);
return;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index b32e346757f..d49ac829ef9 100755
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -520,7 +520,13 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
bool addUnit = true;
// check target immunities
- if (itr->first->IsImmunedToSpell(GetSpellInfo())
+ for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ if (itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex))
+ itr->second &= ~(1 << effIndex);
+ }
+ if (!itr->second
+ || itr->first->IsImmunedToSpell(GetSpellInfo())
|| !CanBeAppliedOn(itr->first))
addUnit = false;
@@ -1855,7 +1861,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
// periodic auras which target areas are not allowed to stack this way (replenishment for example)
- if (m_spellInfo->Effects[i].IsArea() || existingSpellInfo->Effects[i].IsArea())
+ if (m_spellInfo->Effects[i].IsTargetingArea() || existingSpellInfo->Effects[i].IsTargetingArea())
break;
return true;
default:
@@ -2085,6 +2091,30 @@ bool Aura::CallScriptCheckAreaTargetHandlers(Unit* target)
return true;
}
+void Aura::CallScriptDispel(DispelInfo* dispelInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_DISPEL);
+ std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->OnDispel.end(), hookItr = (*scritr)->OnDispel.begin();
+ for (; hookItr != hookItrEnd ; ++hookItr)
+ (*hookItr).Call(*scritr, dispelInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
+void Aura::CallScriptAfterDispel(DispelInfo* dispelInfo)
+{
+ for (std::list<AuraScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end() ; ++scritr)
+ {
+ (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_AFTER_DISPEL);
+ std::list<AuraScript::AuraDispelHandler>::iterator hookItrEnd = (*scritr)->AfterDispel.end(), hookItr = (*scritr)->AfterDispel.begin();
+ for (; hookItr != hookItrEnd ; ++hookItr)
+ (*hookItr).Call(*scritr, dispelInfo);
+ (*scritr)->_FinishScriptCall();
+ }
+}
+
bool Aura::CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode)
{
bool preventDefault = false;
@@ -2342,7 +2372,7 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster)
{
float radius = GetSpellInfo()->Effects[effIndex].CalcRadius(caster);
- if (!GetUnitOwner()->HasUnitState(UNIT_STAT_ISOLATED))
+ if (!GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED))
{
switch (GetSpellInfo()->Effects[effIndex].Effect)
{
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index de743eb2991..4d87abccda3 100755
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -201,6 +201,8 @@ class Aura
// AuraScript
void LoadScripts();
bool CallScriptCheckAreaTargetHandlers(Unit* target);
+ void CallScriptDispel(DispelInfo* dispelInfo);
+ void CallScriptAfterDispel(DispelInfo* dispelInfo);
bool CallScriptEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
bool CallScriptEffectRemoveHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
void CallScriptAfterEffectApplyHandlers(AuraEffect const* aurEff, AuraApplication const* aurApp, AuraEffectHandleModes mode);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 3c73edb880d..45cf64266e1 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1401,13 +1401,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
}
}
-SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask, bool scaleAura)
+SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura)
{
if (!unit || !effectMask)
return SPELL_MISS_EVADE;
- // Recheck immune (only for delayed spells)
- if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))
+ // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
+ // disable effects to which unit is immune
+ for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
+ if (effectMask & (1 << effectNumber) && unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber))
+ effectMask &= ~(1 << effectNumber);
+ if (!effectMask || (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))))
return SPELL_MISS_IMMUNE;
PrepareScriptHitHandlers();
@@ -1447,7 +1451,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask, bool
return SPELL_MISS_EVADE;
// assisting case, healing and resurrection
- if (unit->HasUnitState(UNIT_STAT_ATTACK_PLAYER))
+ if (unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
{
m_caster->SetContestedPvP();
if (m_caster->GetTypeId() == TYPEID_PLAYER)
@@ -1562,7 +1566,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask, bool
}
for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
- if (effectMask & (1 << effectNumber) && !unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) //Handle effect only if the target isn't immune.
+ if (effectMask & (1 << effectNumber))
HandleEffects(unit, NULL, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET);
return SPELL_MISS_NONE;
@@ -2855,20 +2859,6 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
InitExplicitTargets(*targets);
- if (Player* plrCaster = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself())
- {
- //check for special spell conditions
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
- if (!conditions.empty())
- if (!sConditionMgr->IsPlayerMeetToConditions(plrCaster, conditions))
- {
- //SendCastResult(SPELL_FAILED_DONT_REPORT);
- SendCastResult(plrCaster, m_spellInfo, m_cast_count, SPELL_FAILED_DONT_REPORT);
- finish(false);
- return;
- }
- }
-
// Fill aura scaling information
if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING))
{
@@ -3214,8 +3204,8 @@ void Spell::cast(bool skipCheck)
m_spellState = SPELL_STATE_DELAYED;
SetDelayStart(0);
- if (m_caster->HasUnitState(UNIT_STAT_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
- m_caster->ClearUnitState(UNIT_STAT_CASTING);
+ if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
+ m_caster->ClearUnitState(UNIT_STATE_CASTING);
}
else
{
@@ -3581,8 +3571,8 @@ void Spell::finish(bool ok)
if (m_spellInfo->IsChanneled())
m_caster->UpdateInterruptMask();
- if (m_caster->HasUnitState(UNIT_STAT_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
- m_caster->ClearUnitState(UNIT_STAT_CASTING);
+ if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
+ m_caster->ClearUnitState(UNIT_STATE_CASTING);
// Unsummon summon as possessed creatures on spell cancel
if (m_spellInfo->IsChanneled() && m_caster->GetTypeId() == TYPEID_PLAYER)
@@ -4726,6 +4716,14 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_DONT_REPORT;
}
+ // check spell caster's conditions from database
+ if (Player* plrCaster = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself())
+ {
+ ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
+ if (!conditions.empty() && !sConditionMgr->IsPlayerMeetToConditions(plrCaster, conditions))
+ return SPELL_FAILED_DONT_REPORT;
+ }
+
// Don't check explicit target for passive spells (workaround) (check should be skipped only for learn case)
// those spells may have incorrect target entries or not filled at all (for example 15332)
// such spells when learned are not targeting anyone using targeting system, they should apply directly to caster instead
@@ -4769,6 +4767,16 @@ SpellCastResult Spell::CheckCast(bool strict)
}
}
+ //Check for line of sight for spells with dest
+ if (m_targets.HasDst())
+ {
+ float x, y, z;
+ m_targets.GetDst()->GetPosition(x, y, z);
+
+ if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOS(x, y, z))
+ return SPELL_FAILED_LINE_OF_SIGHT;
+ }
+
// check pet presence
for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
@@ -5000,7 +5008,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (strict && m_caster->IsScriptOverriden(m_spellInfo, 6953))
m_caster->RemoveMovementImpairingAuras();
}
- if (m_caster->HasUnitState(UNIT_STAT_ROOT))
+ if (m_caster->HasUnitState(UNIT_STATE_ROOT))
return SPELL_FAILED_ROOTED;
break;
}
@@ -5228,7 +5236,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
Unit* target = m_targets.GetUnitTarget();
- if (m_caster == target && m_caster->HasUnitState(UNIT_STAT_ROOT))
+ if (m_caster == target && m_caster->HasUnitState(UNIT_STATE_ROOT))
{
if (m_caster->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_ROOTED;
@@ -5299,7 +5307,7 @@ SpellCastResult Spell::CheckCast(bool strict)
{
float x, y, z;
m_caster->GetPosition(x, y, z);
- float ground_Z = m_caster->GetMap()->GetHeight(x, y, z);
+ float ground_Z = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z);
if (fabs(ground_Z - z) < 0.1f)
return SPELL_FAILED_DONT_REPORT;
break;
@@ -5401,7 +5409,7 @@ SpellCastResult Spell::CheckCast(bool strict)
}
case SPELL_AURA_PERIODIC_MANA_LEECH:
{
- if (m_spellInfo->Effects[i].IsArea())
+ if (m_spellInfo->Effects[i].IsTargetingArea())
break;
if (!m_targets.GetUnitTarget())
@@ -5455,7 +5463,7 @@ SpellCastResult Spell::CheckCast(bool strict)
SpellCastResult Spell::CheckPetCast(Unit* target)
{
- if (m_caster->HasUnitState(UNIT_STAT_CASTING) && !(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS)) //prevent spellcast interruption by another spellcast
+ if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS)) //prevent spellcast interruption by another spellcast
return SPELL_FAILED_SPELL_IN_PROGRESS;
// dead owner (pets still alive when owners ressed?)
@@ -6630,7 +6638,7 @@ void Spell::HandleLaunchPhase()
continue;
// do not consume ammo anymore for Hunter's volley spell
- if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsAOE())
+ if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsTargetingArea())
usesAmmo = false;
if (usesAmmo)
@@ -6681,7 +6689,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
if (m_damage > 0)
{
- if (m_spellInfo->Effects[i].IsArea())
+ if (m_spellInfo->Effects[i].IsTargetingArea())
{
m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
if (m_caster->GetTypeId() == TYPEID_UNIT)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 2bbc04d6a3b..b20ec345cce 100755
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -643,7 +643,7 @@ class Spell
// effect helpers
void GetSummonPosition(uint32 i, Position &pos, float radius = 0.0f, uint32 count = 0);
- void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties);
+ void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons);
void CalculateJumpSpeeds(uint8 i, float dist, float & speedxy, float & speedz);
SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType& skillid, int32& reqSkillValue, int32& skillValue);
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index d5a9bf923b4..70b1108eff3 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -1338,7 +1338,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
}
//Any effect which causes you to lose control of your character will supress the starfall effect.
- if (m_caster->HasUnitState(UNIT_STAT_CONTROLLED))
+ if (m_caster->HasUnitState(UNIT_STATE_CONTROLLED))
return;
m_caster->CastSpell(unitTarget, damage, true);
@@ -3044,6 +3044,33 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
TempSummon* summon = NULL;
+ // determine how many units should be summoned
+ uint32 numSummons;
+
+ // some spells need to summon many units, for those spells number of summons is stored in effect value
+ // however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc
+ // and in spell attributes, possibly we need to add a table for those)
+ // so here's a list of MiscValueB values, which is currently most generic check
+ switch (properties->Id)
+ {
+ case 64:
+ case 61:
+ case 1101:
+ case 66:
+ case 648:
+ case 2301:
+ case 1061:
+ case 1261:
+ case 629:
+ case 181:
+ case 715:
+ numSummons = (damage > 0) ? damage : 1;
+ break;
+ default:
+ numSummons = 1;
+ break;
+ }
+
switch (properties->Category)
{
case SUMMON_CATEGORY_WILD:
@@ -3051,7 +3078,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
case SUMMON_CATEGORY_UNK:
if (properties->Flags & 512)
{
- SummonGuardian(effIndex, entry, properties);
+ SummonGuardian(effIndex, entry, properties, numSummons);
break;
}
switch (properties->Type)
@@ -3060,7 +3087,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
case SUMMON_TYPE_GUARDIAN:
case SUMMON_TYPE_GUARDIAN2:
case SUMMON_TYPE_MINION:
- SummonGuardian(effIndex, entry, properties);
+ SummonGuardian(effIndex, entry, properties, numSummons);
break;
// Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)
case SUMMON_TYPE_VEHICLE:
@@ -3093,7 +3120,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
summon->SelectLevel(summon->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureInfo()->npcflag);
- summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_PASSIVE);
+ summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
summon->AI()->EnterEvadeMode();
break;
@@ -3102,14 +3129,9 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
{
float radius = m_spellInfo->Effects[effIndex].CalcRadius();
- uint32 amount = damage > 0 ? damage : 1;
- if (m_spellInfo->Id == 18662 || // Curse of Doom
- properties->Id == 2081) // Mechanical Dragonling, Arcanite Dragonling, Mithril Dragonling TODO: Research on meaning of basepoints
- amount = 1;
-
TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
- for (uint32 count = 0; count < amount; ++count)
+ for (uint32 count = 0; count < numSummons; ++count)
{
GetSummonPosition(effIndex, pos, radius, count);
@@ -3131,7 +3153,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
}//switch
break;
case SUMMON_CATEGORY_PET:
- SummonGuardian(effIndex, entry, properties);
+ SummonGuardian(effIndex, entry, properties, numSummons);
break;
case SUMMON_CATEGORY_PUPPET:
summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id);
@@ -3317,7 +3339,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
// Send dispelled spell info
dataSuccess << uint32(itr->first->GetId()); // Spell Id
dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed
- unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), itr->first->GetCasterGUID(), m_caster, itr->second);
+ unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second);
}
m_caster->SendMessageToSet(&dataSuccess, true);
@@ -3360,11 +3382,11 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
return;
// target must be OK to do this
- if (unitTarget->HasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING))
+ if (unitTarget->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING))
return;
unitTarget->SetFacingTo(unitTarget->GetAngle(m_targets.GetDst()));
- unitTarget->ClearUnitState(UNIT_STAT_MOVING);
+ unitTarget->ClearUnitState(UNIT_STATE_MOVING);
if (unitTarget->GetTypeId() == TYPEID_UNIT)
unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
@@ -3834,7 +3856,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
{
SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
if (properties)
- SummonGuardian(effIndex, petentry, properties);
+ SummonGuardian(effIndex, petentry, properties, 1);
return;
}
@@ -6426,7 +6448,7 @@ void Spell::EffectSummonDeadPet(SpellEffIndex /*effIndex*/)
pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
pet->setDeathState(ALIVE);
- pet->ClearUnitState(uint32(UNIT_STAT_ALL_STATE));
+ pet->ClearUnitState(uint32(UNIT_STATE_ALL_STATE));
pet->SetHealth(pet->CountPctFromMaxHealth(damage));
//pet->AIM_Initialize();
@@ -7099,7 +7121,7 @@ void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex)
gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true);
}
-void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties)
+void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians)
{
Unit* caster = m_originalCaster;
if (!caster)
@@ -7118,15 +7140,10 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*
if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING))
level = skill202 / 5;
- //float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
float radius = 5.0f;
- uint32 amount = damage > 0 ? damage : 1;
int32 duration = m_spellInfo->GetDuration();
switch (m_spellInfo->Id)
{
- case 1122: // Inferno
- amount = 1;
- break;
case 49028: // Dancing Rune Weapon
if (AuraEffect* aurEff = m_originalCaster->GetAuraEffect(63330, 0)) // glyph of Dancing Rune Weapon
duration += aurEff->GetAmount();
@@ -7138,7 +7155,7 @@ void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const*
//TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
Map* map = caster->GetMap();
- for (uint32 count = 0; count < amount; ++count)
+ for (uint32 count = 0; count < numGuardians; ++count)
{
Position pos;
GetSummonPosition(i, pos, radius, count);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index fb8018fb5ae..ad465767ab0 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -503,7 +503,7 @@ bool SpellEffectInfo::IsAura(AuraType aura) const
return IsAura() && ApplyAuraName == aura;
}
-bool SpellEffectInfo::IsArea() const
+bool SpellEffectInfo::IsTargetingArea() const
{
return TargetA.IsArea() || TargetB.IsArea();
}
@@ -1061,10 +1061,19 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const
return false;
}
-bool SpellInfo::IsAOE() const
+bool SpellInfo::IsAffectingArea() const
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
- if (Effects[i].IsEffect() && Effects[i].IsArea())
+ if (Effects[i].IsEffect() && (Effects[i].IsTargetingArea() || Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || Effects[i].IsAreaAuraEffect()))
+ return true;
+ return false;
+}
+
+// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example)
+bool SpellInfo::IsTargetingArea() const
+{
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ if (Effects[i].IsEffect() && Effects[i].IsTargetingArea())
return true;
return false;
}
@@ -1604,7 +1613,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b
}
// not allow casting on flying player
- if (target->HasUnitState(UNIT_STAT_IN_FLIGHT))
+ if (target->HasUnitState(UNIT_STATE_IN_FLIGHT))
return SPELL_FAILED_BAD_TARGETS;
if (TargetAuraState && !target->HasAuraState(AuraStateType(TargetAuraState), this, caster))
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 90b79d4da28..65be5981c64 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -279,7 +279,7 @@ public:
bool IsEffect(SpellEffects effectName) const;
bool IsAura() const;
bool IsAura(AuraType aura) const;
- bool IsArea() const;
+ bool IsTargetingArea() const;
bool IsAreaAuraEffect() const;
bool IsFarUnitTargetEffect() const;
bool IsFarDestTargetEffect() const;
@@ -403,7 +403,8 @@ public:
bool IsAbilityLearnedWithProfession() const;
bool IsAbilityOfSkillType(uint32 skillType) const;
- bool IsAOE() const;
+ bool IsAffectingArea() const;
+ bool IsTargetingArea() const;
bool NeedsExplicitUnitTarget() const;
bool NeedsToBeTriggeredByCaster() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 171382ba4f7..ff4eaae42f2 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -104,9 +104,6 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto,
// Hamstring - limit duration to 10s in PvP
if (spellproto->SpellFamilyFlags[0] & 0x2)
return DIMINISHING_LIMITONLY;
- // Improved Hamstring
- else if (spellproto->AttributesEx3 & 0x80000 && spellproto->SpellIconID == 23)
- return DIMINISHING_ROOT;
// Charge Stun (own diminishing)
else if (spellproto->SpellFamilyFlags[0] & 0x01000000)
return DIMINISHING_CHARGE;
@@ -2893,6 +2890,7 @@ void SpellMgr::LoadSpellCustomAttr()
case 64588: // Thrust (Argent Tournament)
case 66479: // Thrust (Argent Tournament)
case 68505: // Thrust (Argent Tournament)
+ case 62709: // Counterattack! (Argent Tournament)
case 62626: // Break-Shield (Argent Tournament, Player)
case 64590: // Break-Shield (Argent Tournament, Player)
case 64342: // Break-Shield (Argent Tournament, NPC)
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 8e20fd21fcf..8a58ce3c52a 100755
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -542,6 +542,14 @@ bool AuraScript::_Validate(SpellInfo const* entry)
if (!entry->HasAreaAuraEffect())
sLog->outError("TSCR: Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+ for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `OnDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
+ for (std::list<AuraDispelHandler>::iterator itr = AfterDispel.begin(); itr != AfterDispel.end(); ++itr)
+ if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect())
+ sLog->outError("TSCR: Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `AfterDispel` of AuraScript won't be executed", entry->Id, m_scriptName->c_str());
+
for (std::list<EffectApplyHandler>::iterator itr = OnEffectApply.begin(); itr != OnEffectApply.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectApply` of AuraScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
@@ -607,6 +615,16 @@ bool AuraScript::CheckAreaTargetHandler::Call(AuraScript* auraScript, Unit* _tar
return (auraScript->*pHandlerScript)(_target);
}
+AuraScript::AuraDispelHandler::AuraDispelHandler(AuraDispelFnType _pHandlerScript)
+{
+ pHandlerScript = _pHandlerScript;
+}
+
+void AuraScript::AuraDispelHandler::Call(AuraScript* auraScript, DispelInfo* _dispelInfo)
+{
+ (auraScript->*pHandlerScript)(_dispelInfo);
+}
+
AuraScript::EffectBase::EffectBase(uint8 _effIndex, uint16 _effName)
: _SpellScript::EffectAuraNameCheck(_effName), _SpellScript::EffectHook(_effIndex)
{
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index a1d8e6563b0..945a62674d9 100755
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -385,6 +385,8 @@ enum AuraScriptHookType
AURA_SCRIPT_HOOK_EFFECT_MANASHIELD,
AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD,
AURA_SCRIPT_HOOK_CHECK_AREA_TARGET,
+ AURA_SCRIPT_HOOK_DISPEL,
+ AURA_SCRIPT_HOOK_AFTER_DISPEL,
/*AURA_SCRIPT_HOOK_APPLY,
AURA_SCRIPT_HOOK_REMOVE, */
};
@@ -400,6 +402,7 @@ class AuraScript : public _SpellScript
#define AURASCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) \
typedef bool(CLASSNAME::*AuraCheckAreaTargetFnType)(Unit* target); \
+ typedef void(CLASSNAME::*AuraDispelFnType)(DispelInfo* dispelInfo); \
typedef void(CLASSNAME::*AuraEffectApplicationModeFnType)(AuraEffect const*, AuraEffectHandleModes); \
typedef void(CLASSNAME::*AuraEffectPeriodicFnType)(AuraEffect const*); \
typedef void(CLASSNAME::*AuraEffectUpdatePeriodicFnType)(AuraEffect*); \
@@ -418,6 +421,14 @@ class AuraScript : public _SpellScript
private:
AuraCheckAreaTargetFnType pHandlerScript;
};
+ class AuraDispelHandler
+ {
+ public:
+ AuraDispelHandler(AuraDispelFnType pHandlerScript);
+ void Call(AuraScript* auraScript, DispelInfo* dispelInfo);
+ private:
+ AuraDispelFnType pHandlerScript;
+ };
class EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook
{
public:
@@ -493,6 +504,7 @@ class AuraScript : public _SpellScript
#define AURASCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \
class CheckAreaTargetFunction : public AuraScript::CheckAreaTargetHandler { public: CheckAreaTargetFunction(AuraCheckAreaTargetFnType _pHandlerScript) : AuraScript::CheckAreaTargetHandler((AuraScript::AuraCheckAreaTargetFnType)_pHandlerScript) {} }; \
+ class AuraDispelFunction : public AuraScript::AuraDispelHandler { public: AuraDispelFunction(AuraDispelFnType _pHandlerScript) : AuraScript::AuraDispelHandler((AuraScript::AuraDispelFnType)_pHandlerScript) {} }; \
class EffectPeriodicHandlerFunction : public AuraScript::EffectPeriodicHandler { public: EffectPeriodicHandlerFunction(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectPeriodicHandler((AuraScript::AuraEffectPeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
class EffectUpdatePeriodicHandlerFunction : public AuraScript::EffectUpdatePeriodicHandler { public: EffectUpdatePeriodicHandlerFunction(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectUpdatePeriodicHandler((AuraScript::AuraEffectUpdatePeriodicFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
class EffectCalcAmountHandlerFunction : public AuraScript::EffectCalcAmountHandler { public: EffectCalcAmountHandlerFunction(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : AuraScript::EffectCalcAmountHandler((AuraScript::AuraEffectCalcAmountFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \
@@ -540,6 +552,17 @@ class AuraScript : public _SpellScript
// where function is: bool function (Unit* target);
HookList<CheckAreaTargetHandler> DoCheckAreaTarget;
#define AuraCheckAreaTargetFn(F) CheckAreaTargetFunction(&F)
+
+ // executed when aura is dispelled by a unit
+ // example: OnDispel += AuraDispelFn(class::function);
+ // where function is: void function (DispelInfo* dispelInfo);
+ HookList<AuraDispelHandler> OnDispel;
+ // executed after aura is dispelled by a unit
+ // example: AfterDispel += AuraDispelFn(class::function);
+ // where function is: void function (DispelInfo* dispelInfo);
+ HookList<AuraDispelHandler> AfterDispel;
+ #define AuraDispelFn(F) AuraDispelFunction(&F)
+
// executed when aura effect is applied with specified mode to target
// should be used when when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe
// example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);