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; } 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; } 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; } 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: protected:
Object (); Object ();
+118 -160
View File
@@ -58,13 +58,10 @@ extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];
SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0) SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0)
{ {
m_unitTarget = NULL; m_objectTarget = NULL;
m_itemTarget = NULL; m_itemTarget = NULL;
m_GOTarget = NULL;
m_unitTargetGUID = 0; m_objectTargetGUID = 0;
m_GOTargetGUID = 0;
m_CorpseTargetGUID = 0;
m_itemTargetGUID = 0; m_itemTargetGUID = 0;
m_itemTargetEntry = 0; m_itemTargetEntry = 0;
@@ -89,18 +86,12 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster)
if (m_targetMask == TARGET_FLAG_NONE) if (m_targetMask == TARGET_FLAG_NONE)
return; return;
if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET)) if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY))
data.readPackGUID(m_unitTargetGUID); data.readPackGUID(m_objectTargetGUID);
if (m_targetMask & (TARGET_FLAG_GAMEOBJECT))
data.readPackGUID(m_GOTargetGUID);
if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
data.readPackGUID(m_itemTargetGUID); 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) if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
{ {
data.readPackGUID(m_srcTransGUID); data.readPackGUID(m_srcTransGUID);
@@ -146,26 +137,7 @@ void SpellCastTargets::Write(ByteBuffer& data)
data << uint32(m_targetMask); 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 | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET))
{ data.appendPackGUID(m_objectTargetGUID);
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);
}
if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
{ {
@@ -197,44 +169,101 @@ void SpellCastTargets::Write(ByteBuffer& data)
data << m_strTarget; 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) void SpellCastTargets::SetUnitTarget(Unit* target)
{ {
if (!target) if (!target)
return; return;
m_unitTarget = target; m_objectTarget = target;
m_unitTargetGUID = target->GetGUID(); m_objectTargetGUID = target->GetGUID();
m_targetMask |= TARGET_FLAG_UNIT; m_targetMask |= TARGET_FLAG_UNIT;
} }
void SpellCastTargets::RemoveUnitTarget() uint64 SpellCastTargets::GetGOTargetGUID() const
{ {
m_unitTarget = NULL; switch (GUID_HIPART(m_objectTargetGUID))
m_unitTargetGUID = 0LL; {
m_targetMask &= ~(TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_MINIPET); 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) void SpellCastTargets::SetGOTarget(GameObject* target)
{ {
if (!target) if (!target)
return; return;
m_GOTarget = target; m_objectTarget = target;
m_GOTargetGUID = target->GetGUID(); m_objectTargetGUID = target->GetGUID();
m_targetMask |= TARGET_FLAG_GAMEOBJECT; m_targetMask |= TARGET_FLAG_GAMEOBJECT;
} }
void SpellCastTargets::RemoveGOTarget() uint64 SpellCastTargets::GetCorpseTargetGUID() const
{ {
m_GOTarget = NULL; switch (GUID_HIPART(m_objectTargetGUID))
m_GOTargetGUID = 0LL; {
m_targetMask &= ~(TARGET_FLAG_GAMEOBJECT); case HIGHGUID_CORPSE:
return m_objectTargetGUID;
default:
return 0LL;
}
} }
void SpellCastTargets::RemoveCorpseTarget() Corpse* SpellCastTargets::GetCorpseTarget() const
{ {
m_CorpseTargetGUID = 0; if (m_objectTarget)
m_targetMask &= ~(TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_CORPSE_ALLY); 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) void SpellCastTargets::SetItemTarget(Item* item)
@@ -370,8 +399,7 @@ void SpellCastTargets::RemoveDst()
void SpellCastTargets::Update(Unit* caster) void SpellCastTargets::Update(Unit* caster)
{ {
m_GOTarget = m_GOTargetGUID ? caster->GetMap()->GetGameObject(m_GOTargetGUID) : NULL; m_objectTarget = m_objectTargetGUID ? ((m_objectTargetGUID == caster->GetGUID()) ? caster : ObjectAccessor::GetWorldObject(*caster, m_objectTargetGUID)) : NULL;
m_unitTarget = m_unitTargetGUID ? (m_unitTargetGUID == caster->GetGUID() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID)) : NULL;
m_itemTarget = NULL; m_itemTarget = NULL;
if (caster->GetTypeId() == TYPEID_PLAYER) if (caster->GetTypeId() == TYPEID_PLAYER)
@@ -411,28 +439,21 @@ void SpellCastTargets::Update(Unit* caster)
void SpellCastTargets::OutDebug() const void SpellCastTargets::OutDebug() const
{ {
if (!m_targetMask) if (!m_targetMask)
sLog->outString("TARGET_FLAG_NONE"); sLog->outString("No targets");
if (m_targetMask & TARGET_FLAG_UNIT) sLog->outString("target mask: %u", m_targetMask);
sLog->outString("TARGET_FLAG_UNIT: " UI64FMTD, m_unitTargetGUID); if (m_targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
if (m_targetMask & TARGET_FLAG_UNIT_MINIPET) sLog->outString("Object target: " UI64FMTD, m_objectTargetGUID);
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);
if (m_targetMask & TARGET_FLAG_ITEM) 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) 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) 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) 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) 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("speed: %f", m_speed);
sLog->outString("elevation: %f", m_elevation); 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) // this also makes sure that we correctly send explicit targets to client (removes redundant data)
uint32 neededTargets = m_spellInfo->GetExplicitTargetMask(); 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 (WorldObject* target = m_targets.GetObjectTarget())
if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK))
{ {
Unit* target = targets.GetUnitTarget(); // 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) 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 // try to use player selection as a target
if (Player* playerCaster = m_caster->ToPlayer()) if (Player* playerCaster = m_caster->ToPlayer())
{ {
// selection has to be found and to be valid target for the spell // selection has to be found and to be valid target for the spell
if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetSelection())) if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetSelection()))
if (IsValidSingleTargetSpell(selectedUnit)) if (m_spellInfo->CheckExplicitTarget(m_caster, selectedUnit) == SPELL_CAST_OK)
target = selectedUnit; target = selectedUnit;
} }
// try to use attacked unit as a target // 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 // 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)) if (!target && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT))
target = m_caster; 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 // check if spell needs dst target
if (neededTargets & TARGET_FLAG_DEST_LOCATION) if (neededTargets & TARGET_FLAG_DEST_LOCATION)
@@ -746,15 +768,15 @@ void Spell::SelectSpellTargets()
AddUnitTarget(target, i, false); AddUnitTarget(target, i, false);
} }
break; break;
case SPELL_EFFECT_SKIN_PLAYER_CORPSE:
case SPELL_EFFECT_RESURRECT_NEW: case SPELL_EFFECT_RESURRECT_NEW:
if (m_targets.GetUnitTarget()) if (WorldObject* target = m_targets.GetObjectTarget())
AddUnitTarget(m_targets.GetUnitTarget(), i, false);
if (m_targets.GetCorpseTargetGUID())
{ {
Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster, m_targets.GetCorpseTargetGUID()); if (Unit* unitTarget = target->ToUnit())
if (corpse) AddUnitTarget(unitTarget, i, false);
else if (Corpse* corpseTarget = target->ToCorpse())
{ {
Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID());
if (owner) if (owner)
AddUnitTarget(owner, i, false); AddUnitTarget(owner, i, false);
} }
@@ -786,20 +808,6 @@ void Spell::SelectSpellTargets()
break; break;
} }
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: default:
AddUnitTarget(m_caster, i, false); AddUnitTarget(m_caster, i, false);
break; break;
@@ -2095,12 +2103,10 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_RAID:
case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_TARGET_PARTY:
case TARGET_UNIT_TARGET_MINIPET: case TARGET_UNIT_TARGET_MINIPET:
if (IsValidSingleTargetSpell(target)) AddUnitTarget(target, i, false);
AddUnitTarget(target, i, false);
break; break;
case TARGET_UNIT_TARGET_PASSENGER: case TARGET_UNIT_TARGET_PASSENGER:
if (target->IsOnVehicle(m_caster)) AddUnitTarget(target, i, false);
AddUnitTarget(target, i, false);
break; break;
case TARGET_UNIT_LASTTARGET_AREA_PARTY: case TARGET_UNIT_LASTTARGET_AREA_PARTY:
case TARGET_UNIT_TARGET_AREA_RAID_CLASS: case TARGET_UNIT_TARGET_AREA_RAID_CLASS:
@@ -4166,13 +4172,7 @@ void Spell::SendChannelUpdate(uint32 time)
void Spell::SendChannelStart(uint32 duration) void Spell::SendChannelStart(uint32 duration)
{ {
uint64 channelTarget = 0; uint64 channelTarget = m_targets.GetObjectTargetGUID();
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();
WorldPacket data(MSG_CHANNEL_START, (8+4+4)); WorldPacket data(MSG_CHANNEL_START, (8+4+4));
data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID());
@@ -4708,6 +4708,12 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_DONT_REPORT; 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()) if (Unit* target = m_targets.GetUnitTarget())
{ {
SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, false); 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 // cooldown
if (Creature const* creatureCaster = m_caster->ToCreature()) if (Creature const* creatureCaster = m_caster->ToCreature())
if (creatureCaster->HasSpellCooldown(m_spellInfo->Id)) if (creatureCaster->HasSpellCooldown(m_spellInfo->Id))
@@ -6564,45 +6561,6 @@ bool SpellEvent::IsDeletable() const
return m_Spell->IsDeletable(); 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 bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const
{ {
if (target->isAlive()) if (target->isAlive())
+13 -17
View File
@@ -104,18 +104,20 @@ class SpellCastTargets
uint32 GetTargetMask() const { return m_targetMask; } uint32 GetTargetMask() const { return m_targetMask; }
void SetTargetMask(uint32 newMask) { m_targetMask = newMask; } void SetTargetMask(uint32 newMask) { m_targetMask = newMask; }
uint64 GetUnitTargetGUID() const { return m_unitTargetGUID; } uint64 GetUnitTargetGUID() const;
Unit* GetUnitTarget() const { return m_unitTarget; } Unit* GetUnitTarget() const;
void SetUnitTarget(Unit* target); void SetUnitTarget(Unit* target);
void RemoveUnitTarget();
uint64 GetGOTargetGUID() const { return m_GOTargetGUID; } uint64 GetGOTargetGUID() const;
GameObject* GetGOTarget() const { return m_GOTarget; } GameObject* GetGOTarget() const;
void SetGOTarget(GameObject* target); void SetGOTarget(GameObject* target);
void RemoveGOTarget();
uint64 GetCorpseTargetGUID() const { return m_CorpseTargetGUID; } uint64 GetCorpseTargetGUID() const;
void RemoveCorpseTarget(); Corpse* GetCorpseTarget() const;
WorldObject* GetObjectTarget() const;
uint64 GetObjectTargetGUID() const;
void RemoveObjectTarget();
uint64 GetItemTargetGUID() const { return m_itemTargetGUID; } uint64 GetItemTargetGUID() const { return m_itemTargetGUID; }
Item* GetItemTarget() const { return m_itemTarget; } Item* GetItemTarget() const { return m_itemTarget; }
@@ -139,7 +141,6 @@ class SpellCastTargets
void ModDst(Position const& pos); void ModDst(Position const& pos);
void RemoveDst(); 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 HasSrc() const { return GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION; }
bool HasDst() const { return GetTargetMask() & TARGET_FLAG_DEST_LOCATION; } bool HasDst() const { return GetTargetMask() & TARGET_FLAG_DEST_LOCATION; }
bool HasTraj() const { return m_speed != 0; } bool HasTraj() const { return m_speed != 0; }
@@ -159,15 +160,12 @@ class SpellCastTargets
private: private:
uint32 m_targetMask; uint32 m_targetMask;
// objects (can be used at spell creating and after Update at casting // objects (can be used at spell creating and after Update at casting)
Unit* m_unitTarget; WorldObject* m_objectTarget;
GameObject* m_GOTarget;
Item* m_itemTarget; Item* m_itemTarget;
// object GUID/etc, can be used always // object GUID/etc, can be used always
uint64 m_unitTargetGUID; uint64 m_objectTargetGUID;
uint64 m_GOTargetGUID;
uint64 m_CorpseTargetGUID;
uint64 m_itemTargetGUID; uint64 m_itemTargetGUID;
uint32 m_itemTargetEntry; 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 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); void SearchChainTarget(std::list<Unit*> &unitList, float radius, uint32 unMaxTargets, SpellTargets TargetType);
WorldObject* SearchNearbyTarget(float range, SpellTargets TargetType, SpellEffIndex effIndex); 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; bool IsValidDeadOrAliveTarget(Unit const* target) const;
void CalculateDamageDoneForAllTargets(); void CalculateDamageDoneForAllTargets();
int32 CalculateDamageDone(Unit *unit, const uint32 effectMask, float *multiplier); 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; 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 bool SpellInfo::CheckTargetCreatureType(Unit const* target) const
{ {
// Curse of Doom & Exorcism: not find another way to fix spell target check :/ // 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 CheckShapeshift(uint32 form) const;
SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) 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 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; bool CheckTargetCreatureType(Unit const* target) const;
SpellSchoolMask GetSchoolMask() const; SpellSchoolMask GetSchoolMask() const;