diff options
author | QAston <qaston@gmail.com> | 2011-08-26 12:05:47 +0200 |
---|---|---|
committer | QAston <qaston@gmail.com> | 2011-08-26 12:06:13 +0200 |
commit | 5c48d9ec8ab587f6d26b04b6b2becb340a9804a8 (patch) | |
tree | 87bd738171d5af8ea7e3e19341e82b2cdd7462ca /src | |
parent | e41774750f58c64a87f511dff4aeeda506ea7b48 (diff) |
Core/Spells: Store explicit unit, corpse and GO targets in one variable, because both client and server can't handle more than one explicit object target; Add spell explicit target validation.
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Entities/Object/Object.h | 3 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 280 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.h | 30 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 38 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 1 |
5 files changed, 174 insertions, 178 deletions
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index a0433f8f475..de2184eaaa6 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -328,6 +328,9 @@ class Object const Unit* ToUnit() const {if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) return (const Unit*)((Unit*)this); else return NULL; } GameObject* ToGameObject(){ if (GetTypeId() == TYPEID_GAMEOBJECT) return reinterpret_cast<GameObject*>(this); else return NULL; } const GameObject* ToGameObject() const {if (GetTypeId() == TYPEID_GAMEOBJECT) return (const GameObject*)((GameObject*)this); else return NULL; } + + Corpse* ToCorpse(){ if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse*>(this); else return NULL; } + const Corpse* ToCorpse() const {if (GetTypeId() == TYPEID_CORPSE) return (const Corpse*)((Corpse*)this); else return NULL; } protected: Object (); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index af8e1b2c1a9..a7370c3f74f 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -58,13 +58,10 @@ extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0) { - m_unitTarget = NULL; + m_objectTarget = NULL; m_itemTarget = NULL; - m_GOTarget = NULL; - m_unitTargetGUID = 0; - m_GOTargetGUID = 0; - m_CorpseTargetGUID = 0; + m_objectTargetGUID = 0; m_itemTargetGUID = 0; m_itemTargetEntry = 0; @@ -89,18 +86,12 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster) if (m_targetMask == TARGET_FLAG_NONE) return; - if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET)) - data.readPackGUID(m_unitTargetGUID); - - if (m_targetMask & (TARGET_FLAG_GAMEOBJECT)) - data.readPackGUID(m_GOTargetGUID); + if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY)) + data.readPackGUID(m_objectTargetGUID); if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) data.readPackGUID(m_itemTargetGUID); - if (m_targetMask & (TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY)) - data.readPackGUID(m_CorpseTargetGUID); - if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION) { data.readPackGUID(m_srcTransGUID); @@ -146,26 +137,7 @@ void SpellCastTargets::Write(ByteBuffer& data) data << uint32(m_targetMask); if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET)) - { - if (m_targetMask & TARGET_FLAG_UNIT) - { - if (m_unitTarget) - data.append(m_unitTarget->GetPackGUID()); - else - data << uint8(0); - } - else if (m_targetMask & TARGET_FLAG_GAMEOBJECT) - { - if (m_GOTarget) - data.append(m_GOTarget->GetPackGUID()); - else - data << uint8(0); - } - else if (m_targetMask & (TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_CORPSE_ENEMY)) - data.appendPackGUID(m_CorpseTargetGUID); - else - data << uint8(0); - } + data.appendPackGUID(m_objectTargetGUID); if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) { @@ -197,44 +169,101 @@ void SpellCastTargets::Write(ByteBuffer& data) data << m_strTarget; } +uint64 SpellCastTargets::GetUnitTargetGUID() const +{ + switch (GUID_HIPART(m_objectTargetGUID)) + { + case HIGHGUID_PLAYER: + case HIGHGUID_VEHICLE: + case HIGHGUID_UNIT: + case HIGHGUID_PET: + return m_objectTargetGUID; + default: + return 0LL; + } +} + +Unit* SpellCastTargets::GetUnitTarget() const +{ + if (m_objectTarget) + return m_objectTarget->ToUnit(); + return NULL; +} + void SpellCastTargets::SetUnitTarget(Unit* target) { if (!target) return; - m_unitTarget = target; - m_unitTargetGUID = target->GetGUID(); + m_objectTarget = target; + m_objectTargetGUID = target->GetGUID(); m_targetMask |= TARGET_FLAG_UNIT; } -void SpellCastTargets::RemoveUnitTarget() +uint64 SpellCastTargets::GetGOTargetGUID() const +{ + switch (GUID_HIPART(m_objectTargetGUID)) + { + case HIGHGUID_TRANSPORT: + case HIGHGUID_MO_TRANSPORT: + case HIGHGUID_GAMEOBJECT: + return m_objectTargetGUID; + default: + return 0LL; + } +} + +GameObject* SpellCastTargets::GetGOTarget() const { - m_unitTarget = NULL; - m_unitTargetGUID = 0LL; - m_targetMask &= ~(TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET); + if (m_objectTarget) + return m_objectTarget->ToGameObject(); + return NULL; } + void SpellCastTargets::SetGOTarget(GameObject* target) { if (!target) return; - m_GOTarget = target; - m_GOTargetGUID = target->GetGUID(); + m_objectTarget = target; + m_objectTargetGUID = target->GetGUID(); m_targetMask |= TARGET_FLAG_GAMEOBJECT; } -void SpellCastTargets::RemoveGOTarget() +uint64 SpellCastTargets::GetCorpseTargetGUID() const +{ + switch (GUID_HIPART(m_objectTargetGUID)) + { + case HIGHGUID_CORPSE: + return m_objectTargetGUID; + default: + return 0LL; + } +} + +Corpse* SpellCastTargets::GetCorpseTarget() const +{ + if (m_objectTarget) + return m_objectTarget->ToCorpse(); + return NULL; +} + +WorldObject* SpellCastTargets::GetObjectTarget() const +{ + return m_objectTarget; +} + +uint64 SpellCastTargets::GetObjectTargetGUID() const { - m_GOTarget = NULL; - m_GOTargetGUID = 0LL; - m_targetMask &= ~(TARGET_FLAG_GAMEOBJECT); + return m_objectTargetGUID; } -void SpellCastTargets::RemoveCorpseTarget() +void SpellCastTargets::RemoveObjectTarget() { - m_CorpseTargetGUID = 0; - m_targetMask &= ~(TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY); + m_objectTarget = NULL; + m_objectTargetGUID = 0LL; + m_targetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK); } void SpellCastTargets::SetItemTarget(Item* item) @@ -370,8 +399,7 @@ void SpellCastTargets::RemoveDst() void SpellCastTargets::Update(Unit* caster) { - m_GOTarget = m_GOTargetGUID ? caster->GetMap()->GetGameObject(m_GOTargetGUID) : NULL; - m_unitTarget = m_unitTargetGUID ? (m_unitTargetGUID == caster->GetGUID() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID)) : NULL; + m_objectTarget = m_objectTargetGUID ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : NULL; m_itemTarget = NULL; if (caster->GetTypeId() == TYPEID_PLAYER) @@ -411,28 +439,21 @@ void SpellCastTargets::Update(Unit* caster) void SpellCastTargets::OutDebug() const { if (!m_targetMask) - sLog->outString("TARGET_FLAG_NONE"); - - if (m_targetMask & TARGET_FLAG_UNIT) - sLog->outString("TARGET_FLAG_UNIT: " UI64FMTD, m_unitTargetGUID); - if (m_targetMask & TARGET_FLAG_UNIT_MINIPET) - sLog->outString("TARGET_FLAG_UNIT_MINIPET: " UI64FMTD, m_unitTargetGUID); - if (m_targetMask & TARGET_FLAG_GAMEOBJECT) - sLog->outString("TARGET_FLAG_GAMEOBJECT: " UI64FMTD, m_GOTargetGUID); - if (m_targetMask & TARGET_FLAG_CORPSE_ENEMY) - sLog->outString("TARGET_FLAG_CORPSE_ENEMY: " UI64FMTD, m_CorpseTargetGUID); - if (m_targetMask & TARGET_FLAG_CORPSE_ALLY) - sLog->outString("TARGET_FLAG_CORPSE_ALLY: " UI64FMTD, m_CorpseTargetGUID); + sLog->outString("No targets"); + + sLog->outString("target mask: %u", m_targetMask); + if (m_targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK)) + sLog->outString("Object target: " UI64FMTD, m_objectTargetGUID); if (m_targetMask & TARGET_FLAG_ITEM) - sLog->outString("TARGET_FLAG_ITEM: " UI64FMTD, m_itemTargetGUID); + sLog->outString("Item target: " UI64FMTD, m_itemTargetGUID); if (m_targetMask & TARGET_FLAG_TRADE_ITEM) - sLog->outString("TARGET_FLAG_TRADE_ITEM: " UI64FMTD, m_itemTargetGUID); + sLog->outString("Trade item target: " UI64FMTD, m_itemTargetGUID); if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION) - sLog->outString("TARGET_FLAG_SOURCE_LOCATION: transport guid:" UI64FMTD " trans offset: %s position: %s", m_srcTransGUID, m_srcTransOffset.ToString().c_str(), m_srcPos.ToString().c_str()); + sLog->outString("Source location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_srcTransGUID, m_srcTransOffset.ToString().c_str(), m_srcPos.ToString().c_str()); if (m_targetMask & TARGET_FLAG_DEST_LOCATION) - sLog->outString("TARGET_FLAG_DEST_LOCATION: transport guid:" UI64FMTD " trans offset: %s position: %s", m_dstTransGUID, m_dstTransOffset.ToString().c_str(), m_dstPos.ToString().c_str()); + sLog->outString("Destination location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_dstTransGUID, m_dstTransOffset.ToString().c_str(), m_dstPos.ToString().c_str()); if (m_targetMask & TARGET_FLAG_STRING) - sLog->outString("TARGET_FLAG_STRING: %s", m_strTarget.c_str()); + sLog->outString("String: %s", m_strTarget.c_str()); sLog->outString("speed: %f", m_speed); sLog->outString("elevation: %f", m_elevation); } @@ -608,19 +629,27 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) // this also makes sure that we correctly send explicit targets to client (removes redundant data) uint32 neededTargets = m_spellInfo->GetExplicitTargetMask(); - // check if spell needs unit target (allow spells with corpse flag to accept unit targets - unit target is sent by client when corpse not yet released) - if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)) + if (WorldObject* target = m_targets.GetObjectTarget()) { - Unit* target = targets.GetUnitTarget(); - - if (!target) + // check if object target is valid with needed target flags + // for unit case allow corpse target mask because player with not released corpse is a unit target + if ((target->ToUnit() && !(neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK))) + || (target->ToGameObject() && !(neededTargets & TARGET_FLAG_GAMEOBJECT_MASK)) + || (target->ToCorpse() && !(neededTargets & TARGET_FLAG_CORPSE_MASK))) + m_targets.RemoveObjectTarget(); + } + else + { + // try to select correct unit target if not provided by client or by serverside cast + if (neededTargets & (TARGET_FLAG_UNIT_MASK)) { + Unit* target = NULL; // try to use player selection as a target if (Player* playerCaster = m_caster->ToPlayer()) { // selection has to be found and to be valid target for the spell if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetSelection())) - if (IsValidSingleTargetSpell(selectedUnit)) + if (m_spellInfo->CheckExplicitTarget(m_caster, selectedUnit) == SPELL_CAST_OK) target = selectedUnit; } // try to use attacked unit as a target @@ -629,17 +658,10 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets) // didn't find anything - let's use self as target if (!target && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT)) target = m_caster; + + m_targets.SetUnitTarget(target); } - m_targets.SetUnitTarget(target); } - else - m_targets.RemoveUnitTarget(); - - if (!(neededTargets & TARGET_FLAG_GAMEOBJECT_MASK)) - m_targets.RemoveGOTarget(); - - if (!(neededTargets & TARGET_FLAG_CORPSE_MASK)) - m_targets.RemoveCorpseTarget(); // check if spell needs dst target if (neededTargets & TARGET_FLAG_DEST_LOCATION) @@ -746,15 +768,15 @@ void Spell::SelectSpellTargets() AddUnitTarget(target, i, false); } break; + case SPELL_EFFECT_SKIN_PLAYER_CORPSE: case SPELL_EFFECT_RESURRECT_NEW: - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); - if (m_targets.GetCorpseTargetGUID()) + if (WorldObject* target = m_targets.GetObjectTarget()) { - Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster, m_targets.GetCorpseTargetGUID()); - if (corpse) + if (Unit* unitTarget = target->ToUnit()) + AddUnitTarget(unitTarget, i, false); + else if (Corpse* corpseTarget = target->ToCorpse()) { - Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); + Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()); if (owner) AddUnitTarget(owner, i, false); } @@ -786,20 +808,6 @@ void Spell::SelectSpellTargets() break; } break; - case SPELL_EFFECT_SKIN_PLAYER_CORPSE: - if (m_targets.GetUnitTarget()) - AddUnitTarget(m_targets.GetUnitTarget(), i, false); - else if (m_targets.GetCorpseTargetGUID()) - { - Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster, m_targets.GetCorpseTargetGUID()); - if (corpse) - { - Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); - if (owner) - AddUnitTarget(owner, i, false); - } - } - break; default: AddUnitTarget(m_caster, i, false); break; @@ -2095,12 +2103,10 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_TARGET_MINIPET: - if (IsValidSingleTargetSpell(target)) - AddUnitTarget(target, i, false); + AddUnitTarget(target, i, false); break; case TARGET_UNIT_TARGET_PASSENGER: - if (target->IsOnVehicle(m_caster)) - AddUnitTarget(target, i, false); + AddUnitTarget(target, i, false); break; case TARGET_UNIT_LASTTARGET_AREA_PARTY: case TARGET_UNIT_TARGET_AREA_RAID_CLASS: @@ -4166,13 +4172,7 @@ void Spell::SendChannelUpdate(uint32 time) void Spell::SendChannelStart(uint32 duration) { - uint64 channelTarget = 0; - if (m_targets.GetUnitTargetGUID()) - channelTarget = m_targets.GetUnitTargetGUID(); - else if (m_targets.GetGOTargetGUID()) - channelTarget = m_targets.GetGOTargetGUID(); - else if (m_targets.GetCorpseTargetGUID()) - channelTarget = m_targets.GetCorpseTargetGUID(); + uint64 channelTarget = m_targets.GetObjectTargetGUID(); WorldPacket data(MSG_CHANNEL_START, (8+4+4)); data.append(m_caster->GetPackGUID()); @@ -4708,6 +4708,12 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_DONT_REPORT; } + { + SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_caster, m_targets.GetObjectTarget()); + if (castResult != SPELL_CAST_OK) + return castResult; + } + if (Unit* target = m_targets.GetUnitTarget()) { SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, false); @@ -5447,15 +5453,6 @@ SpellCastResult Spell::CheckPetCast(Unit* target) } } - Unit* _target = m_targets.GetUnitTarget(); - - // for target dead/target not valid - if (_target) - { - if (!IsValidSingleTargetSpell(_target)) - return SPELL_FAILED_BAD_TARGETS; - } - // cooldown if (Creature const* creatureCaster = m_caster->ToCreature()) if (creatureCaster->HasSpellCooldown(m_spellInfo->Id)) @@ -6564,45 +6561,6 @@ bool SpellEvent::IsDeletable() const return m_Spell->IsDeletable(); } -bool Spell::IsValidSingleTargetEffect(Unit const* target, Targets type) const -{ - switch (type) - { - case TARGET_UNIT_TARGET_ENEMY: - return !m_caster->IsFriendlyTo(target); - case TARGET_UNIT_TARGET_ALLY: - case TARGET_UNIT_LASTTARGET_AREA_PARTY: - return m_caster->IsFriendlyTo(target); - case TARGET_UNIT_TARGET_PARTY: - return m_caster != target && m_caster->IsInPartyWith(target); - case TARGET_UNIT_TARGET_RAID: - return m_caster->IsInRaidWith(target); - case TARGET_UNIT_TARGET_MINIPET: - return target->GetGUID() == m_caster->GetCritterGUID(); - default: - break; - } - return true; -} - -bool Spell::IsValidSingleTargetSpell(Unit const* target) const -{ - if (target->GetMapId() == MAPID_INVALID) - { - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell::IsValidSingleTargetSpell - a spell was cast on '%s' (GUIDLow: %u), but they have an invalid map id!", target->GetName(), target->GetGUIDLow()); - return false; - } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (!IsValidSingleTargetEffect(target, m_spellInfo->Effects[i].TargetA.GetTarget())) - return false; - // Need to check B? - //if (!IsValidSingleTargetEffect(m_spellInfo->Effects[i].TargetB, target) - // return false; - } - return true; -} - bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const { if (target->isAlive()) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index c0f3daf0664..2b0dd569e48 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -104,18 +104,20 @@ class SpellCastTargets uint32 GetTargetMask() const { return m_targetMask; } void SetTargetMask(uint32 newMask) { m_targetMask = newMask; } - uint64 GetUnitTargetGUID() const { return m_unitTargetGUID; } - Unit* GetUnitTarget() const { return m_unitTarget; } + uint64 GetUnitTargetGUID() const; + Unit* GetUnitTarget() const; void SetUnitTarget(Unit* target); - void RemoveUnitTarget(); - uint64 GetGOTargetGUID() const { return m_GOTargetGUID; } - GameObject* GetGOTarget() const { return m_GOTarget; } + uint64 GetGOTargetGUID() const; + GameObject* GetGOTarget() const; void SetGOTarget(GameObject* target); - void RemoveGOTarget(); - uint64 GetCorpseTargetGUID() const { return m_CorpseTargetGUID; } - void RemoveCorpseTarget(); + uint64 GetCorpseTargetGUID() const; + Corpse* GetCorpseTarget() const; + + WorldObject* GetObjectTarget() const; + uint64 GetObjectTargetGUID() const; + void RemoveObjectTarget(); uint64 GetItemTargetGUID() const { return m_itemTargetGUID; } Item* GetItemTarget() const { return m_itemTarget; } @@ -139,7 +141,6 @@ class SpellCastTargets void ModDst(Position const& pos); void RemoveDst(); - bool IsEmpty() const { return m_GOTargetGUID == 0 && m_unitTargetGUID == 0 && m_itemTarget == 0 && m_CorpseTargetGUID == 0; } bool HasSrc() const { return GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION; } bool HasDst() const { return GetTargetMask() & TARGET_FLAG_DEST_LOCATION; } bool HasTraj() const { return m_speed != 0; } @@ -159,15 +160,12 @@ class SpellCastTargets private: uint32 m_targetMask; - // objects (can be used at spell creating and after Update at casting - Unit* m_unitTarget; - GameObject* m_GOTarget; + // objects (can be used at spell creating and after Update at casting) + WorldObject* m_objectTarget; Item* m_itemTarget; // object GUID/etc, can be used always - uint64 m_unitTargetGUID; - uint64 m_GOTargetGUID; - uint64 m_CorpseTargetGUID; + uint64 m_objectTargetGUID; uint64 m_itemTargetGUID; uint32 m_itemTargetEntry; @@ -602,8 +600,6 @@ class Spell void SearchGOAreaTarget(std::list<GameObject*> &gobjectList, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry = 0); void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType); WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex); - bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; - bool IsValidSingleTargetSpell(Unit const* target) const; bool IsValidDeadOrAliveTarget(Unit const* target) const; void CalculateDamageDoneForAllTargets(); int32 CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index c798eefd98f..d09dce0566d 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1705,6 +1705,44 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b return SPELL_CAST_OK; } +SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target) const +{ + uint32 neededTargets = GetExplicitTargetMask(); + if (!target) + { + if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK | TARGET_FLAG_CORPSE_MASK)) + return SPELL_FAILED_BAD_TARGETS; + return SPELL_CAST_OK; + } + + if (Unit const* unitTarget = target->ToUnit()) + { + if (neededTargets & (TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_UNIT_PASSENGER)) + { + if (neededTargets & TARGET_FLAG_UNIT_ENEMY) + if (!caster->IsFriendlyTo(unitTarget)) + return SPELL_CAST_OK; + if (neededTargets & TARGET_FLAG_UNIT_ALLY) + if (caster->IsFriendlyTo(unitTarget)) + return SPELL_CAST_OK; + if (neededTargets & TARGET_FLAG_UNIT_PARTY) + if (caster->IsInPartyWith(unitTarget)) + return SPELL_CAST_OK; + if (neededTargets & TARGET_FLAG_UNIT_RAID) + if (caster->IsInRaidWith(unitTarget)) + return SPELL_CAST_OK; + if (neededTargets & TARGET_FLAG_UNIT_MINIPET) + if (unitTarget->GetGUID() == caster->GetCritterGUID()) + return SPELL_CAST_OK; + if (neededTargets & TARGET_FLAG_UNIT_PASSENGER) + if (unitTarget->IsOnVehicle(caster)) + return SPELL_CAST_OK; + return SPELL_FAILED_BAD_TARGETS; + } + } + return SPELL_CAST_OK; +} + bool SpellInfo::CheckTargetCreatureType(Unit const* target) const { // Curse of Doom & Exorcism: not find another way to fix spell target check :/ diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 3d94a376822..aa003641846 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -441,6 +441,7 @@ public: SpellCastResult CheckShapeshift(uint32 form) const; SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const; + SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target) const; bool CheckTargetCreatureType(Unit const* target) const; SpellSchoolMask GetSchoolMask() const; |