diff options
| author | Shauren <shauren.trinity@gmail.com> | 2021-05-13 00:38:09 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2025-11-17 18:22:43 +0100 |
| commit | 4997e316d9e4bf529e131d45528fff404d99b836 (patch) | |
| tree | 633bf20758ce902a91b4000f8694e7f271c85cd6 | |
| parent | 5e691c0d5f5fdc9f45d5c06525f6c0334ff0818e (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)
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 26 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 12 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellScript.cpp | 41 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellScript.h | 9 |
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; |
