Skip to content

Commit 4997e31

Browse files
committed
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 1a7779a)
1 parent 5e691c0 commit 4997e31

File tree

5 files changed

+77
-15
lines changed

5 files changed

+77
-15
lines changed

src/server/game/Spells/Spell.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2362,6 +2362,30 @@ void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex)
23622362
m_destTargets[effIndex] = dest;
23632363
}
23642364

2365+
int64 Spell::GetUnitTargetCountForEffect(SpellEffIndex effect) const
2366+
{
2367+
return std::count_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [effect](TargetInfo const& targetInfo)
2368+
{
2369+
return targetInfo.EffectMask & (1 << effect);
2370+
});
2371+
}
2372+
2373+
int64 Spell::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
2374+
{
2375+
return std::count_if(m_UniqueGOTargetInfo.begin(), m_UniqueGOTargetInfo.end(), [effect](GOTargetInfo const& targetInfo)
2376+
{
2377+
return targetInfo.EffectMask & (1 << effect);
2378+
});
2379+
}
2380+
2381+
int64 Spell::GetItemTargetCountForEffect(SpellEffIndex effect) const
2382+
{
2383+
return std::count_if(m_UniqueItemInfo.begin(), m_UniqueItemInfo.end(), [effect](ItemTargetInfo const& targetInfo)
2384+
{
2385+
return targetInfo.EffectMask & (1 << effect);
2386+
});
2387+
}
2388+
23652389
void Spell::TargetInfo::PreprocessTarget(Spell* spell)
23662390
{
23672391
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
77847808
if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
77857809
{
77867810
// cap damage of player AOE
7787-
uint32 targetAmount = m_UniqueTargetInfo.size();
7811+
int64 targetAmount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex);
77887812
if (targetAmount > 10)
77897813
m_damage = m_damage * 10 / targetAmount;
77907814
}

src/server/game/Spells/Spell.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ class TC_GAME_API Spell
466466

467467
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
468468

469+
int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
470+
int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
471+
int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
472+
469473
protected:
470474
bool HasGlobalCooldown() const;
471475
void TriggerGlobalCooldown();

src/server/game/Spells/SpellEffects.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -332,18 +332,8 @@ void Spell::EffectSchoolDMG()
332332
// Meteor like spells (divided damage to targets)
333333
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
334334
{
335-
uint32 count = 0;
336-
for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
337-
{
338-
if (ihit->MissCondition != SPELL_MISS_NONE)
339-
continue;
340-
341-
if (ihit->EffectMask & (1 << effectInfo->EffectIndex))
342-
++count;
343-
}
344-
345335
// divide to all targets
346-
if (count)
336+
if (int64 count = GetUnitTargetCountForEffect(SpellEffIndex(effectInfo->EffectIndex)))
347337
damage /= count;
348338
}
349339

src/server/game/Spells/SpellScript.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,14 @@ bool SpellScript::IsInCheckCastHook() const
408408
{
409409
return m_currentScriptState == SPELL_SCRIPT_HOOK_CHECK_CAST;
410410
}
411+
412+
bool SpellScript::IsAfterTargetSelectionPhase() const
413+
{
414+
return IsInHitPhase()
415+
|| m_currentScriptState == SPELL_SCRIPT_HOOK_ON_CAST
416+
|| m_currentScriptState == SPELL_SCRIPT_HOOK_AFTER_CAST;
417+
}
418+
411419
bool SpellScript::IsInTargetHook() const
412420
{
413421
switch (m_currentScriptState)
@@ -509,6 +517,39 @@ Item* SpellScript::GetExplTargetItem() const
509517
return m_spell->m_targets.GetItemTarget();
510518
}
511519

520+
int64 SpellScript::GetUnitTargetCountForEffect(SpellEffIndex effect) const
521+
{
522+
if (!IsAfterTargetSelectionPhase())
523+
{
524+
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)",
525+
m_scriptName->c_str(), m_scriptSpellId);
526+
return 0;
527+
}
528+
return m_spell->GetUnitTargetCountForEffect(effect);
529+
}
530+
531+
int64 SpellScript::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
532+
{
533+
if (!IsAfterTargetSelectionPhase())
534+
{
535+
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)",
536+
m_scriptName->c_str(), m_scriptSpellId);
537+
return 0;
538+
}
539+
return m_spell->GetGameObjectTargetCountForEffect(effect);
540+
}
541+
542+
int64 SpellScript::GetItemTargetCountForEffect(SpellEffIndex effect) const
543+
{
544+
if (!IsAfterTargetSelectionPhase())
545+
{
546+
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)",
547+
m_scriptName->c_str(), m_scriptSpellId);
548+
return 0;
549+
}
550+
return m_spell->GetItemTargetCountForEffect(effect);
551+
}
552+
512553
Unit* SpellScript::GetHitUnit() const
513554
{
514555
if (!IsInTargetHook())

src/server/game/Spells/SpellScript.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,6 @@ enum SpellScriptHookType
194194

195195
#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT_HIT
196196
#define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1
197-
#define HOOK_SPELL_START SPELL_SCRIPT_HOOK_EFFECT
198-
#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1
199-
#define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START
200197

201198
class TC_GAME_API SpellScript : public _SpellScript
202199
{
@@ -343,6 +340,7 @@ class TC_GAME_API SpellScript : public _SpellScript
343340
void _PrepareScriptCall(SpellScriptHookType hookType);
344341
void _FinishScriptCall();
345342
bool IsInCheckCastHook() const;
343+
bool IsAfterTargetSelectionPhase() const;
346344
bool IsInTargetHook() const;
347345
bool IsInModifiableHook() const;
348346
bool IsInHitPhase() const;
@@ -469,6 +467,11 @@ class TC_GAME_API SpellScript : public _SpellScript
469467
// returns: Item which was selected as an explicit spell target or NULL if there's no target
470468
Item* GetExplTargetItem() const;
471469

470+
// methods usable only after spell targets have been fully selected
471+
int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
472+
int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
473+
int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
474+
472475
// methods useable only during spell hit on target, or during spell launch on target:
473476
// returns: target of current effect if it was Unit otherwise NULL
474477
Unit* GetHitUnit() const;

0 commit comments

Comments
 (0)