aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2021-05-13 00:38:09 +0200
committerShauren <shauren.trinity@gmail.com>2025-11-17 18:22:43 +0100
commit4997e316d9e4bf529e131d45528fff404d99b836 (patch)
tree633bf20758ce902a91b4000f8694e7f271c85cd6 /src
parent5e691c0d5f5fdc9f45d5c06525f6c0334ff0818e (diff)
Core/Spells: Expose number of targets selected for each spell effect to scripts to allow implementing spells that do something depending on number of targets hit
(cherry picked from commit 1a7779a6e6464d9bc5b367e02820213edd60f704)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Spells/Spell.cpp26
-rw-r--r--src/server/game/Spells/Spell.h4
-rw-r--r--src/server/game/Spells/SpellEffects.cpp12
-rw-r--r--src/server/game/Spells/SpellScript.cpp41
-rw-r--r--src/server/game/Spells/SpellScript.h9
5 files changed, 77 insertions, 15 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 5f024a813ea..e523ce7c111 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2362,6 +2362,30 @@ void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex)
m_destTargets[effIndex] = dest;
}
+int64 Spell::GetUnitTargetCountForEffect(SpellEffIndex effect) const
+{
+ return std::count_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [effect](TargetInfo const& targetInfo)
+ {
+ return targetInfo.EffectMask & (1 << effect);
+ });
+}
+
+int64 Spell::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
+{
+ return std::count_if(m_UniqueGOTargetInfo.begin(), m_UniqueGOTargetInfo.end(), [effect](GOTargetInfo const& targetInfo)
+ {
+ return targetInfo.EffectMask & (1 << effect);
+ });
+}
+
+int64 Spell::GetItemTargetCountForEffect(SpellEffIndex effect) const
+{
+ return std::count_if(m_UniqueItemInfo.begin(), m_UniqueItemInfo.end(), [effect](ItemTargetInfo const& targetInfo)
+ {
+ return targetInfo.EffectMask & (1 << effect);
+ });
+}
+
void Spell::TargetInfo::PreprocessTarget(Spell* spell)
{
Unit* unit = spell->m_caster->GetGUID() == TargetGUID ? spell->m_caster->ToUnit() : ObjectAccessor::GetUnit(*spell->m_caster, TargetGUID);
@@ -7784,7 +7808,7 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe
if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
{
// cap damage of player AOE
- uint32 targetAmount = m_UniqueTargetInfo.size();
+ int64 targetAmount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex);
if (targetAmount > 10)
m_damage = m_damage * 10 / targetAmount;
}
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index fe8b1a54670..f14e83c1677 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -466,6 +466,10 @@ class TC_GAME_API Spell
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
+ int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
+ int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
+ int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
+
protected:
bool HasGlobalCooldown() const;
void TriggerGlobalCooldown();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 6b4192efaef..77387b17798 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -332,18 +332,8 @@ void Spell::EffectSchoolDMG()
// Meteor like spells (divided damage to targets)
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
{
- uint32 count = 0;
- for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
- {
- if (ihit->MissCondition != SPELL_MISS_NONE)
- continue;
-
- if (ihit->EffectMask & (1 << effectInfo->EffectIndex))
- ++count;
- }
-
// divide to all targets
- if (count)
+ if (int64 count = GetUnitTargetCountForEffect(SpellEffIndex(effectInfo->EffectIndex)))
damage /= count;
}
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 66d02bb104e..874427e77ff 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -408,6 +408,14 @@ bool SpellScript::IsInCheckCastHook() const
{
return m_currentScriptState == SPELL_SCRIPT_HOOK_CHECK_CAST;
}
+
+bool SpellScript::IsAfterTargetSelectionPhase() const
+{
+ return IsInHitPhase()
+ || m_currentScriptState == SPELL_SCRIPT_HOOK_ON_CAST
+ || m_currentScriptState == SPELL_SCRIPT_HOOK_AFTER_CAST;
+}
+
bool SpellScript::IsInTargetHook() const
{
switch (m_currentScriptState)
@@ -509,6 +517,39 @@ Item* SpellScript::GetExplTargetItem() const
return m_spell->m_targets.GetItemTarget();
}
+int64 SpellScript::GetUnitTargetCountForEffect(SpellEffIndex effect) const
+{
+ if (!IsAfterTargetSelectionPhase())
+ {
+ TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetUnitTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)",
+ m_scriptName->c_str(), m_scriptSpellId);
+ return 0;
+ }
+ return m_spell->GetUnitTargetCountForEffect(effect);
+}
+
+int64 SpellScript::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
+{
+ if (!IsAfterTargetSelectionPhase())
+ {
+ TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetGameObjectTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)",
+ m_scriptName->c_str(), m_scriptSpellId);
+ return 0;
+ }
+ return m_spell->GetGameObjectTargetCountForEffect(effect);
+}
+
+int64 SpellScript::GetItemTargetCountForEffect(SpellEffIndex effect) const
+{
+ if (!IsAfterTargetSelectionPhase())
+ {
+ TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetItemTargetCountForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)",
+ m_scriptName->c_str(), m_scriptSpellId);
+ return 0;
+ }
+ return m_spell->GetItemTargetCountForEffect(effect);
+}
+
Unit* SpellScript::GetHitUnit() const
{
if (!IsInTargetHook())
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 6b399c3a59e..9c8e61a9b00 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -194,9 +194,6 @@ enum SpellScriptHookType
#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT_HIT
#define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1
-#define HOOK_SPELL_START SPELL_SCRIPT_HOOK_EFFECT
-#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1
-#define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START
class TC_GAME_API SpellScript : public _SpellScript
{
@@ -343,6 +340,7 @@ class TC_GAME_API SpellScript : public _SpellScript
void _PrepareScriptCall(SpellScriptHookType hookType);
void _FinishScriptCall();
bool IsInCheckCastHook() const;
+ bool IsAfterTargetSelectionPhase() const;
bool IsInTargetHook() const;
bool IsInModifiableHook() const;
bool IsInHitPhase() const;
@@ -469,6 +467,11 @@ class TC_GAME_API SpellScript : public _SpellScript
// returns: Item which was selected as an explicit spell target or NULL if there's no target
Item* GetExplTargetItem() const;
+ // methods usable only after spell targets have been fully selected
+ int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
+ int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
+ int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
+
// methods useable only during spell hit on target, or during spell launch on target:
// returns: target of current effect if it was Unit otherwise NULL
Unit* GetHitUnit() const;