diff options
| author | QAston <qaston@gmail.com> | 2011-08-24 08:07:59 +0200 |
|---|---|---|
| committer | QAston <qaston@gmail.com> | 2011-08-24 08:08:33 +0200 |
| commit | 7f30ac5a9549746d19af9ca4cfc1ad7b8d2f1f4c (patch) | |
| tree | 50ab82a86ca92b300cee7408f97db514af722147 /src/server/game/Spells/SpellInfo.cpp | |
| parent | 9f7a557c05f4bb631c5f358093f2379ac01590a7 (diff) | |
Core/Spells: Add a generic way of selecting spell explicit targets. Make explicit targets independant of calling convention in core - this makes targets sent to client to be much more blizzlike than before (for example CastSpell(Unit*) won't set TARGET_FLAG_UNIT for spells which are not using explicit unit target) for SMSG_SPELL_START packets. Also remove hacks, which became obsolete with this commit.
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
| -rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 177 |
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 |
