diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 4ed969efa..9d02eb7ff 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -373,13 +373,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi else m_originalCasterGUID = m_caster->GetGUID(); - if(m_originalCasterGUID == m_caster->GetGUID()) - m_originalCaster = m_caster; - else - { - m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID); - if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL; - } + UpdateOriginalCasterPointer(); for(int i = 0; i < 3; ++i) m_currentBasePoints[i] = m_spellInfo->EffectBasePoints[i]; @@ -947,9 +941,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) return; // Get original caster (if exist) and calculate damage/healing from him data - Unit *caster = m_originalCaster ? m_originalCaster : m_caster; - - // Skip if m_originalCaster not available + Unit *caster = GetAffectiveCaster(); if (!caster) return; @@ -1061,7 +1053,9 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (!unit || !effectMask) return; - Unit* realCaster = m_originalCaster ? m_originalCaster : m_caster; + Unit* realCaster = GetAffectiveCaster(); + if (!realCaster) + return; // Recheck immune (only for delayed spells) if (m_spellInfo->speed && ( @@ -1308,9 +1302,9 @@ void Spell::SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList& targetUni uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[effIndex]; - if(m_originalCaster) + if (Unit* realCaster = GetAffectiveCaster()) { - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + if(Player* modOwner = realCaster->GetSpellModOwner()) { modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this); modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); @@ -1593,7 +1587,7 @@ void Spell::SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList& targetUni else { Unit* pUnitTarget = m_targets.getUnitTarget(); - Unit* originalCaster = GetOriginalCaster(); + Unit* originalCaster = GetAffectiveCaster(); if(!pUnitTarget || !originalCaster) break; @@ -1722,13 +1716,8 @@ void Spell::SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList& targetUni case TARGET_CASTER_COORDINATES: { // Check original caster is GO - set its coordinates as dst cast - WorldObject *caster = NULL; - if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) - caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); - if (!caster) - caster = m_caster; - // Set dest for targets - m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); + if (WorldObject *caster = GetCastingObject()) + m_targets.setDestination(caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ()); break; } case TARGET_ALL_HOSTILE_UNITS_AROUND_CASTER: @@ -2819,8 +2808,8 @@ void Spell::_handle_immediate_phase() m_needSpellLog = false; uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[j]; - if(m_originalCaster) - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + if (Unit* realCaster = GetAffectiveCaster()) + if(Player* modOwner = realCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); // initialize multipliers @@ -4511,9 +4500,8 @@ SpellCastResult Spell::CheckCast(bool strict) case SPELL_EFFECT_TAMECREATURE: { // Spell can be triggered, we need to check original caster prior to caster - Unit* caster = m_originalCaster ? m_originalCaster : m_caster; - - if (caster->GetTypeId() != TYPEID_PLAYER || + Unit* caster = GetAffectiveCaster(); + if (!caster || caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; @@ -5891,15 +5879,25 @@ void Spell::DelayedChannel() SendChannelUpdate(m_timer); } -void Spell::UpdatePointers() +void Spell::UpdateOriginalCasterPointer() { if(m_originalCasterGUID == m_caster->GetGUID()) m_originalCaster = m_caster; + else if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) + { + GameObject* go = m_caster->IsInWorld() ? m_caster->GetMap()->GetGameObject(m_originalCasterGUID) : NULL; + m_originalCaster = go ? go->GetOwner() : NULL; + } else { - m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID); - if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL; + Unit* unit = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID); + m_originalCaster = unit && unit->IsInWorld() ? unit : NULL; } +} + +void Spell::UpdatePointers() +{ + UpdateOriginalCasterPointer(); m_targets.Update(m_caster); } @@ -6023,13 +6021,10 @@ bool Spell::CheckTarget( Unit* target, uint32 eff ) break; default: // normal case // Get GO cast coordinates if original caster -> GO - WorldObject *caster = NULL; - if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) - caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID); - if (!caster) - caster = m_caster; - if(target != m_caster && !target->IsWithinLOSInMap(caster)) - return false; + if (target != m_caster) + if (WorldObject *caster = GetCastingObject()) + if (!target->IsWithinLOSInMap(caster)) + return false; break; } @@ -6336,3 +6331,11 @@ void Spell::FillRaidOrPartyHealthPriorityTargets(UnitList &targetUnitMap, Unit* healthQueue.pop(); } } + +WorldObject* Spell::GetCastingObject() const +{ + if (IS_GAMEOBJECT_GUID(m_originalCasterGUID)) + return m_caster->IsInWorld() ? m_caster->GetMap()->GetGameObject(m_originalCasterGUID) : NULL; + else + return m_caster; +} \ No newline at end of file diff --git a/src/game/Spell.h b/src/game/Spell.h index 088034e9a..c754d2a74 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -436,8 +436,14 @@ class Spell CurrentSpellTypes GetCurrentContainer(); + // caster types: + // formal spell caster, in game source of spell affects cast Unit* GetCaster() const { return m_caster; } - Unit* GetOriginalCaster() const { return m_originalCaster; } + // real source of cast affects, explcit caster, or DoT/HoT applier, or GO owner, etc. Can be NULL + Unit* GetAffectiveCaster() const { return m_originalCasterGUID ? m_originalCaster : m_caster; } + // m_originalCasterGUID can store GO guid, and in this case this is visual caster + WorldObject* GetCastingObject() const; + int32 GetPowerCost() const { return m_powerCost; } void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc) @@ -458,6 +464,7 @@ class Spell void SendLoot(uint64 guid, LootType loottype); bool IgnoreItemRequirements() const; // some item use spells have unexpected reagent data + void UpdateOriginalCasterPointer(); Unit* m_caster; @@ -611,7 +618,7 @@ namespace MaNGOS SpellNotifierPlayer(Spell &spell, std::list &data, const uint32 &i, float radius) : i_data(data), i_spell(spell), i_index(i), i_radius(radius) { - i_originalCaster = i_spell.GetOriginalCaster(); + i_originalCaster = i_spell.GetAffectiveCaster(); } void Visit(PlayerMapType &m) @@ -648,7 +655,7 @@ namespace MaNGOS SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY) : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType) { - i_originalCaster = spell.GetOriginalCaster(); + i_originalCaster = spell.GetAffectiveCaster(); } template inline void Visit(GridRefManager &m) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 285d0bd15..ab12b4de7 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -841,14 +841,16 @@ void Spell::EffectDummy(uint32 i) } case 17251: // Spirit Healer Res { - if (!unitTarget || !m_originalCaster) + if (!unitTarget) return; - if (m_originalCaster->GetTypeId() == TYPEID_PLAYER) + Unit* caster = GetAffectiveCaster(); + + if (caster && caster->GetTypeId() == TYPEID_PLAYER) { WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); data << uint64(unitTarget->GetGUID()); - ((Player*)m_originalCaster)->GetSession()->SendPacket( &data ); + ((Player*)caster)->GetSession()->SendPacket( &data ); } return; } @@ -2518,7 +2520,7 @@ void Spell::EffectApplyAura(uint32 i) (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; - Unit* caster = m_originalCaster ? m_originalCaster : m_caster; + Unit* caster = GetAffectiveCaster(); if(!caster) return; @@ -2668,9 +2670,7 @@ void Spell::EffectHeal( uint32 /*i*/ ) if (unitTarget && unitTarget->isAlive() && damage >= 0) { // Try to get original caster - Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; - - // Skip if m_originalCaster not available + Unit *caster = GetAffectiveCaster(); if (!caster) return; @@ -2752,9 +2752,7 @@ void Spell::EffectHealPct( uint32 /*i*/ ) if (unitTarget && unitTarget->isAlive() && damage >= 0) { // Try to get original caster - Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; - - // Skip if m_originalCaster not available + Unit *caster = GetAffectiveCaster(); if (!caster) return; @@ -2773,9 +2771,7 @@ void Spell::EffectHealMechanical( uint32 /*i*/ ) if (unitTarget && unitTarget->isAlive() && damage >= 0) { // Try to get original caster - Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; - - // Skip if m_originalCaster not available + Unit *caster = GetAffectiveCaster(); if (!caster) return; @@ -4265,7 +4261,7 @@ void Spell::EffectTameCreature(uint32 /*i*/) { // Caster must be player, checked in Spell::CheckCast // Spell can be triggered, we need to check original caster prior to caster - Player* plr = (Player*)(m_originalCaster ? m_originalCaster : m_caster); + Player* plr = (Player*)GetAffectiveCaster(); Creature* creatureTarget = (Creature*)unitTarget; @@ -5162,10 +5158,11 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Emblazon Runeblade case 51770: { - if(!m_originalCaster) + Unit* caster = GetAffectiveCaster(); + if(!caster) return; - m_originalCaster->CastSpell(m_originalCaster, damage, false); + caster->CastSpell(caster, damage, false); break; } // Death Gate diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9d24690f0..5e5598199 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9322" + #define REVISION_NR "9323" #endif // __REVISION_NR_H__