From c7f8c9b52bf8496f08de8cc5c29d0eb640ce8897 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 31 Jul 2009 16:12:50 +0400 Subject: [PATCH] Avoid target requirement checks for spells with caster base target selection (self,pet,around). This fix cast fail for some spells, mostly triggered or scripted with unexpected prowided explicit tatrget different from caster. --- src/game/Spell.cpp | 20 ++++++++++++++++---- src/game/SpellMgr.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2e7cf82e6..eafee4451 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -505,6 +505,16 @@ void Spell::FillTargetMap() // but need it support in some know cases switch(m_spellInfo->EffectImplicitTargetA[i]) { + case 0: + switch(m_spellInfo->EffectImplicitTargetB[i]) + { + case 0: + break; + default: + SetTargetMap(i, m_spellInfo->EffectImplicitTargetB[i], tmpUnitMap); + break; + } + break; case TARGET_SELF: switch(m_spellInfo->EffectImplicitTargetB[i]) { @@ -3751,7 +3761,9 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_CASTER_AURASTATE; } - if(target != m_caster) + bool non_caster_target = target != m_caster && !IsSpellWithCasterSourceTargetsOnly(m_spellInfo); + + if(non_caster_target) { // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds if(m_spellInfo->TargetAuraState && !target->HasAuraStateForCaster(AuraState(m_spellInfo->TargetAuraState),m_caster->GetGUID())) @@ -3806,7 +3818,7 @@ SpellCastResult Spell::CheckCast(bool strict) //check creature type //ignore self casts (including area casts when caster selected as target) - if(target != m_caster) + if(non_caster_target) { if(!CheckTargetCreatureType(target)) { @@ -3819,7 +3831,7 @@ SpellCastResult Spell::CheckCast(bool strict) // TODO: this check can be applied and for player to prevent cheating when IsPositiveSpell will return always correct result. // check target for pet/charmed casts (not self targeted), self targeted cast used for area effects and etc - if(m_caster != target && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetCharmerOrOwnerGUID()) + if(non_caster_target && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetCharmerOrOwnerGUID()) { // check correctness positive/negative cast target (pet cast real check and cheating check) if(IsPositiveSpell(m_spellInfo->Id)) @@ -3859,7 +3871,7 @@ SpellCastResult Spell::CheckCast(bool strict) } // check if target is in combat - if (target != m_caster && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat()) + if (non_caster_target && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat()) return SPELL_FAILED_TARGET_AFFECTING_COMBAT; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 7f06e1a90..76c3da926 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -196,6 +196,46 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB); bool IsSingleTargetSpell(SpellEntry const *spellInfo); bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2); +inline bool IsCasterSourceTarget(uint32 target) +{ + switch (target ) + { + case TARGET_SELF: + case TARGET_PET: + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_MASTER: + case TARGET_MINION: + case TARGET_ALL_PARTY: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_SELF_FISHING: + case TARGET_TOTEM_EARTH: + case TARGET_TOTEM_WATER: + case TARGET_TOTEM_AIR: + case TARGET_TOTEM_FIRE: + case TARGET_SUMMON: + case TARGET_AREAEFFECT_CUSTOM_2: + case TARGET_ALL_RAID_AROUND_CASTER: + case TARGET_SELF2: + case TARGET_DIRECTLY_FORWARD: + case TARGET_NONCOMBAT_PET: + case TARGET_IN_FRONT_OF_CASTER_30: + return true; + default: + break; + } + return false; +} + +inline bool IsSpellWithCasterSourceTargetsOnly(SpellEntry const* spellInfo) +{ + for(int i = 0; i < 3; ++i) + if(uint32 target = spellInfo->EffectImplicitTargetA[i]) + if(!IsCasterSourceTarget(target)) + return false; + return true; +} + inline bool IsPointEffectTarget( Targets target ) { switch (target )