aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
-rw-r--r--src/server/game/Spells/SpellInfo.cpp177
1 files changed, 166 insertions, 11 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 8b660d36a8d..d84e32379a7 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -21,6 +21,30 @@
#include "Spell.h"
#include "DBCStores.h"
+uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
+{
+ switch (objType)
+ {
+ case TARGET_OBJECT_TYPE_DEST:
+ return TARGET_FLAG_DEST_LOCATION;
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ return TARGET_FLAG_DEST_LOCATION | TARGET_FLAG_UNIT;
+ case TARGET_OBJECT_TYPE_CORPSE:
+ case TARGET_OBJECT_TYPE_UNIT:
+ return TARGET_FLAG_UNIT;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ return TARGET_FLAG_GAMEOBJECT;
+ case TARGET_OBJECT_TYPE_GOBJ_ITEM:
+ return TARGET_FLAG_GAMEOBJECT_ITEM;
+ case TARGET_OBJECT_TYPE_ITEM:
+ return TARGET_FLAG_ITEM;
+ case TARGET_OBJECT_TYPE_SRC:
+ return TARGET_FLAG_SOURCE_LOCATION;
+ default:
+ return TARGET_FLAG_NONE;
+ }
+}
+
SpellImplicitTargetInfo::SpellImplicitTargetInfo(uint32 target)
{
_target = Targets(target);
@@ -93,6 +117,66 @@ Targets SpellImplicitTargetInfo::GetTarget() const
return _target;
}
+uint32 SpellImplicitTargetInfo::GetExplicitTargetMask(bool& srcSet, bool& dstSet) const
+{
+ switch (GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_SRC:
+ srcSet = true;
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ dstSet = true;
+ break;
+ default:
+ break;
+ }
+
+ switch (GetReferenceType())
+ {
+ case TARGET_REFERENCE_TYPE_SRC:
+ if (srcSet)
+ break;
+ return TARGET_FLAG_SOURCE_LOCATION;
+ case TARGET_REFERENCE_TYPE_DEST:
+ if (dstSet)
+ break;
+ return TARGET_FLAG_DEST_LOCATION;
+ case TARGET_REFERENCE_TYPE_TARGET:
+ switch (GetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_GOBJ:
+ return TARGET_FLAG_GAMEOBJECT;
+ case TARGET_OBJECT_TYPE_GOBJ_ITEM:
+ return TARGET_FLAG_GAMEOBJECT_ITEM;
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ case TARGET_OBJECT_TYPE_UNIT:
+ switch (GetSelectionCheckType())
+ {
+ case TARGET_SELECT_CHECK_ENEMY:
+ return TARGET_FLAG_UNIT_ENEMY;
+ case TARGET_SELECT_CHECK_ALLY:
+ return TARGET_FLAG_UNIT_ALLY;
+ case TARGET_SELECT_CHECK_PARTY:
+ return TARGET_FLAG_UNIT_PARTY;
+ case TARGET_SELECT_CHECK_RAID:
+ return TARGET_FLAG_UNIT_RAID;
+ case TARGET_SELECT_CHECK_PASSENGER:
+ return TARGET_FLAG_UNIT_PASSENGER;
+ default:
+ return TARGET_FLAG_UNIT;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return TARGET_FLAG_NONE;
+}
+
bool SpellImplicitTargetInfo::IsPosition(uint32 targetType)
{
switch (SpellImplicitTargetInfo::Type[targetType])
@@ -885,6 +969,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
SchoolMask = spellEntry->SchoolMask;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
Effects[i] = SpellEffectInfo(spellEntry, this, i);
+ ExplicitTargetMask = _GetExplicitTargetMask();
ChainEntry = NULL;
}
@@ -1021,17 +1106,7 @@ bool SpellInfo::IsAOE() const
bool SpellInfo::IsRequiringSelectedTarget() const
{
- for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS; ++i)
- {
- if (Effects[i].TargetA.GetType() == TARGET_TYPE_UNIT_TARGET
- || Effects[i].TargetB.GetType() == TARGET_TYPE_UNIT_TARGET
- || Effects[i].TargetA.GetType() == TARGET_TYPE_CHANNEL
- || Effects[i].TargetB.GetType() == TARGET_TYPE_CHANNEL
- || Effects[i].TargetA.GetType() == TARGET_TYPE_DEST_TARGET
- || Effects[i].TargetB.GetType() == TARGET_TYPE_DEST_TARGET)
- return true;
- }
- return false;
+ return (GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK) != 0;
}
bool SpellInfo::IsPassive() const
@@ -1672,6 +1747,11 @@ uint32 SpellInfo::GetDispelMask(DispelType type)
return uint32(1 << type);
}
+uint32 SpellInfo::GetExplicitTargetMask() const
+{
+ return ExplicitTargetMask;
+}
+
AuraStateType SpellInfo::GetAuraState() const
{
// Seals
@@ -2119,6 +2199,81 @@ bool SpellInfo::IsHighRankOf(SpellInfo const* spellInfo) const
return false;
}
+uint32 SpellInfo::_GetExplicitTargetMask() const
+{
+ bool srcSet = false;
+ bool dstSet = false;
+ uint32 targetMask = Targets;
+ // prepare target mask using effect target entries
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (!Effects[i].IsEffect())
+ continue;
+ targetMask |= Effects[i].TargetA.GetExplicitTargetMask(srcSet, dstSet);
+ targetMask |= Effects[i].TargetB.GetExplicitTargetMask(srcSet, dstSet);
+ }
+ // spells with range may need explicit targets, even if target entries not set
+ // for example many SPELL_EFFECT_LEARN_SPELL spells need to have unit target
+ if (GetMaxRange(true) > 0.0f || GetMaxRange(false) > 0.0f)
+ {
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (!Effects[i].IsEffect())
+ continue;
+
+ uint32 effImplicitTargetMask = GetTargetFlagMask(Effects[i].GetImplicitTargetObjectType());
+ uint32 providedTargetMask = GetTargetFlagMask(Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(Effects[i].TargetB.GetObjectType()) | targetMask;
+
+ // check if valid targets already present, prevent adding redundant flags
+ switch (Effects[i].GetImplicitTargetObjectType())
+ {
+ case TARGET_OBJECT_TYPE_UNIT_AND_DEST:
+ if (providedTargetMask & TARGET_FLAG_UNIT_MASK)
+ effImplicitTargetMask &= ~(TARGET_FLAG_UNIT_MASK);
+ if (dstSet || providedTargetMask & TARGET_FLAG_DEST_LOCATION)
+ effImplicitTargetMask &= ~(TARGET_FLAG_DEST_LOCATION);
+ if (!effImplicitTargetMask)
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_SRC:
+ if (srcSet || providedTargetMask & TARGET_FLAG_SOURCE_LOCATION)
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_DEST:
+ if (dstSet || providedTargetMask & TARGET_FLAG_DEST_LOCATION)
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_UNIT:
+ if (providedTargetMask & TARGET_FLAG_UNIT_MASK)
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_CORPSE:
+ if (providedTargetMask & (TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_UNIT_MASK))
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_ITEM:
+ if (providedTargetMask & (TARGET_FLAG_GAMEOBJECT_ITEM | TARGET_FLAG_ITEM))
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ:
+ if (providedTargetMask & TARGET_FLAG_GAMEOBJECT_MASK)
+ continue;
+ break;
+ case TARGET_OBJECT_TYPE_GOBJ_ITEM:
+ if (providedTargetMask & (TARGET_FLAG_GAMEOBJECT_ITEM | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_ITEM))
+ continue;
+ break;
+ default:
+ continue;
+ }
+
+ // extend explicit target mask only if valid targets for effect could not be provided by target types
+ targetMask |= effImplicitTargetMask &~(providedTargetMask);
+ }
+ }
+ return targetMask;
+}
+
bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
{
// not found a single positive spell with this attribute