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.

This commit is contained in:
QAston
2011-08-26 12:06:13 +02:00
parent e41774750f
commit 5c48d9ec8a
5 changed files with 173 additions and 177 deletions
+3
View File
@@ -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 ();
+118 -160
View File
@@ -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
{
m_unitTarget = NULL;
m_unitTargetGUID = 0LL;
m_targetMask &= ~(TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET);
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
{
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
{
m_GOTarget = NULL;
m_GOTargetGUID = 0LL;
m_targetMask &= ~(TARGET_FLAG_GAMEOBJECT);
switch (GUID_HIPART(m_objectTargetGUID))
{
case HIGHGUID_CORPSE:
return m_objectTargetGUID;
default:
return 0LL;
}
}
void SpellCastTargets::RemoveCorpseTarget()
Corpse* SpellCastTargets::GetCorpseTarget() const
{
m_CorpseTargetGUID = 0;
m_targetMask &= ~(TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY);
if (m_objectTarget)
return m_objectTarget->ToCorpse();
return NULL;
}
WorldObject* SpellCastTargets::GetObjectTarget() const
{
return m_objectTarget;
}
uint64 SpellCastTargets::GetObjectTargetGUID() const
{
return m_objectTargetGUID;
}
void SpellCastTargets::RemoveObjectTarget()
{
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");
sLog->outString("No targets");
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("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())
+13 -17
View File
@@ -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);
+38
View File
@@ -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 :/
+1
View File
@@ -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;