diff options
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp | 6 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 1 |
5 files changed, 31 insertions, 18 deletions
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 1f085b56dd6..928ad8a7d60 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -957,7 +957,7 @@ enum SpellAttr13 : uint32 SPELL_ATTR13_UNK12 = 0x00001000, // TITLE Unknown attribute 12@Attr13 SPELL_ATTR13_UNK13 = 0x00002000, // TITLE Unknown attribute 13@Attr13 SPELL_ATTR13_UNK14 = 0x00004000, // TITLE Unknown attribute 14@Attr13 - SPELL_ATTR13_UNK15 = 0x00008000, // TITLE Unknown attribute 15@Attr13 + SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET = 0x00008000, // TITLE Do Not Fail if No Target SPELL_ATTR13_UNK16 = 0x00010000, // TITLE Unknown attribute 16@Attr13 SPELL_ATTR13_UNK17 = 0x00020000, // TITLE Unknown attribute 17@Attr13 SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT = 0x00040000, // TITLE Do Not Enforce Shapeshift Requirements diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp index 1ec8bd8aea6..536974f3245 100644 --- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp +++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp @@ -1972,7 +1972,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr13>::ToString(SpellAttr13 value) case SPELL_ATTR13_UNK12: return { "SPELL_ATTR13_UNK12", "Unknown attribute 12@Attr13", "" }; case SPELL_ATTR13_UNK13: return { "SPELL_ATTR13_UNK13", "Unknown attribute 13@Attr13", "" }; case SPELL_ATTR13_UNK14: return { "SPELL_ATTR13_UNK14", "Unknown attribute 14@Attr13", "" }; - case SPELL_ATTR13_UNK15: return { "SPELL_ATTR13_UNK15", "Unknown attribute 15@Attr13", "" }; + case SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET: return { "SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET", "Do Not Fail if No Target", "" }; case SPELL_ATTR13_UNK16: return { "SPELL_ATTR13_UNK16", "Unknown attribute 16@Attr13", "" }; case SPELL_ATTR13_UNK17: return { "SPELL_ATTR13_UNK17", "Unknown attribute 17@Attr13", "" }; case SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT: return { "SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT", "Do Not Enforce Shapeshift Requirements", "" }; @@ -2016,7 +2016,7 @@ TC_API_EXPORT SpellAttr13 EnumUtils<SpellAttr13>::FromIndex(size_t index) case 12: return SPELL_ATTR13_UNK12; case 13: return SPELL_ATTR13_UNK13; case 14: return SPELL_ATTR13_UNK14; - case 15: return SPELL_ATTR13_UNK15; + case 15: return SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET; case 16: return SPELL_ATTR13_UNK16; case 17: return SPELL_ATTR13_UNK17; case 18: return SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT; @@ -2057,7 +2057,7 @@ TC_API_EXPORT size_t EnumUtils<SpellAttr13>::ToIndex(SpellAttr13 value) case SPELL_ATTR13_UNK12: return 12; case SPELL_ATTR13_UNK13: return 13; case SPELL_ATTR13_UNK14: return 14; - case SPELL_ATTR13_UNK15: return 15; + case SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET: return 15; case SPELL_ATTR13_UNK16: return 16; case SPELL_ATTR13_UNK17: return 17; case SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT: return 18; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6f6f23e618c..9559d37ccec 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1638,8 +1638,12 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectIn void Spell::SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType, SpellTargetIndex targetIndex) { - ASSERT(m_targets.GetObjectTarget() && "Spell::SelectImplicitTargetDestTargets - no explicit object target available!"); + ASSERT(m_targets.GetObjectTarget() || spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::DontFailSpellOnTargetingFailure), + "Spell::SelectImplicitTargetDestTargets - no explicit object target available!"); + WorldObject* target = m_targets.GetObjectTarget(); + if (!target) + return; SpellDestination dest(*target); @@ -1788,7 +1792,8 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffectInfo const& spellEffect void Spell::SelectImplicitTargetObjectTargets(SpellEffectInfo const& spellEffectInfo, SpellImplicitTargetInfo const& targetType) { - ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); + ASSERT(m_targets.GetObjectTarget() || m_targets.GetItemTarget() || spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::DontFailSpellOnTargetingFailure), + "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); WorldObject* target = m_targets.GetObjectTarget(); @@ -7106,7 +7111,7 @@ bool Spell::CanAutoCast(Unit* target) if (result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT) { // do not check targets for ground-targeted spells (we target them on top of the intended target anyway) - if (GetSpellInfo()->ExplicitTargetMask & TARGET_FLAG_DEST_LOCATION) + if (GetSpellInfo()->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) return true; SelectSpellTargets(); //check if among target units, our WANTED target is as well (->only self cast spells return false) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 74981277a3b..467c6fae06f 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -2362,7 +2362,7 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co SpellCastResult SpellInfo::CheckExplicitTarget(WorldObject const* caster, WorldObject const* target, Item const* itemTarget /*= nullptr*/) const { - uint32 neededTargets = GetExplicitTargetMask(); + uint32 neededTargets = RequiredExplicitTargetMask; if (!target) { if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK | TARGET_FLAG_CORPSE_MASK)) @@ -4424,31 +4424,38 @@ void SpellInfo::_InitializeExplicitTargetMask() { bool srcSet = false; bool dstSet = false; - uint32 targetMask = Targets; // prepare target mask using effect target entries for (SpellEffectInfo const& effect : GetEffects()) { if (!effect.IsEffect()) continue; + uint32 targetMask = 0; targetMask |= effect.TargetA.GetExplicitTargetMask(srcSet, dstSet); targetMask |= effect.TargetB.GetExplicitTargetMask(srcSet, dstSet); // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided - if (effect.GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) - continue; + if (effect.GetImplicitTargetType() == EFFECT_IMPLICIT_TARGET_EXPLICIT) + { - // extend explicit target mask only if valid targets for effect could not be provided by target types - uint32 effectTargetMask = effect.GetMissingTargetMask(srcSet, dstSet, targetMask); + // extend explicit target mask only if valid targets for effect could not be provided by target types + uint32 effectTargetMask = effect.GetMissingTargetMask(srcSet, dstSet, targetMask); - // don't add explicit object/dest flags when spell has no max range - if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) - effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); + // don't add explicit object/dest flags when spell has no max range + if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) + effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); + + targetMask |= effectTargetMask; + } - targetMask |= effectTargetMask; + ExplicitTargetMask |= targetMask; + if (!effect.EffectAttributes.HasFlag(SpellEffectAttributes::DontFailSpellOnTargetingFailure)) + RequiredExplicitTargetMask |= targetMask; } - ExplicitTargetMask = targetMask; + ExplicitTargetMask |= Targets; + if (!HasAttribute(SPELL_ATTR13_DO_NOT_FAIL_IF_NO_TARGET)) + RequiredExplicitTargetMask |= Targets; } inline bool _isPositiveTarget(SpellEffectInfo const& effect) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 5b62fa383a3..6eab18b0633 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -424,6 +424,7 @@ class TC_GAME_API SpellInfo } Scaling; uint32 ExplicitTargetMask = 0; + uint32 RequiredExplicitTargetMask = 0; SpellChainNode const* ChainEntry = nullptr; struct { |