aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorQAston <qaston@gmail.com>2011-08-26 12:05:47 +0200
committerQAston <qaston@gmail.com>2011-08-26 12:06:13 +0200
commit5c48d9ec8ab587f6d26b04b6b2becb340a9804a8 (patch)
tree87bd738171d5af8ea7e3e19341e82b2cdd7462ca /src
parente41774750f58c64a87f511dff4aeeda506ea7b48 (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-xsrc/server/game/Entities/Object/Object.h3
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp280
-rwxr-xr-xsrc/server/game/Spells/Spell.h30
-rw-r--r--src/server/game/Spells/SpellInfo.cpp38
-rw-r--r--src/server/game/Spells/SpellInfo.h1
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;