aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-02-16 20:38:52 +0100
committerShauren <shauren.trinity@gmail.com>2025-02-16 20:38:52 +0100
commit195945742105fa8dbd061f3b62b755d722655931 (patch)
tree0aa1b74b7f01aec3f8e435354992a27f74316f6a /src
parented15c428058dc70adecbbe5ff0fbc28f6e17f63f (diff)
Core/Spells: Implemented SpellEffectAttributes::DontFailSpellOnTargetingFailure
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp6
-rw-r--r--src/server/game/Spells/Spell.cpp11
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
-rw-r--r--src/server/game/Spells/SpellInfo.h1
5 files changed, 31 insertions, 18 deletions
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 5f0c06c0dd2..98a24c4d9c1 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -925,7 +925,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 b6d72ce4795..e1816c62eba 100644
--- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
+++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp
@@ -1966,7 +1966,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", "" };
@@ -2010,7 +2010,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;
@@ -2051,7 +2051,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 3d99133087b..78060c919ea 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();
@@ -7323,7 +7328,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 a6d92d63716..26e0288f471 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -2419,7 +2419,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))
@@ -4461,31 +4461,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 1af55b90239..0b5b168a9d5 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -422,6 +422,7 @@ class TC_GAME_API SpellInfo
} Scaling;
uint32 ExplicitTargetMask = 0;
+ uint32 RequiredExplicitTargetMask = 0;
SpellChainNode const* ChainEntry = nullptr;
struct
{