Skip to content

Commit 78d4064

Browse files
author
Github Actions
committed
Merge 3.3.5 to 3.3.5-base_patch
2 parents 7de0aa2 + bc47ca8 commit 78d4064

7 files changed

Lines changed: 108 additions & 52 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--
2+
UPDATE `page_text` SET `Text`='The corruption and evil that rumor says travels with the arcane is nothing compared to the pain we\'ve already felt. We are no longer victims, $N. We are the ones who control our fate. Sylvanas has paved the way for us--she has proven that our will is our own; that we are no longer thralls to that bastard Arthas.$B$BSeek me out in the church, I shall instruct you further... if that is your desire.$B$B- Isabella, Mage Trainer' WHERE `ID`=2447;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_patchwerk_hateful_strike_primer';
2+
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
3+
(28307, 'spell_patchwerk_hateful_strike_primer');

‎src/server/game/Spells/Spell.cpp‎

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2378,25 +2378,42 @@ void Spell::AddDestTarget(SpellDestination const& dest, uint32 effIndex)
23782378
m_destTargets[effIndex] = dest;
23792379
}
23802380

2381+
int32 Spell::GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const
2382+
{
2383+
int32 index = 0;
2384+
for (TargetInfo const& uniqueTargetInfo : m_UniqueTargetInfo)
2385+
{
2386+
if (uniqueTargetInfo.MissCondition == SPELL_MISS_NONE && uniqueTargetInfo.EffectMask & (1 << effect))
2387+
{
2388+
if (uniqueTargetInfo.TargetGUID == target)
2389+
return index;
2390+
2391+
++index;
2392+
}
2393+
}
2394+
2395+
return -1;
2396+
}
2397+
23812398
int64 Spell::GetUnitTargetCountForEffect(SpellEffIndex effect) const
23822399
{
2383-
return std::count_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [effect](TargetInfo const& targetInfo)
2400+
return std::ranges::count_if(m_UniqueTargetInfo, [effect](TargetInfo const& targetInfo)
23842401
{
23852402
return targetInfo.EffectMask & (1 << effect);
23862403
});
23872404
}
23882405

23892406
int64 Spell::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
23902407
{
2391-
return std::count_if(m_UniqueGOTargetInfo.begin(), m_UniqueGOTargetInfo.end(), [effect](GOTargetInfo const& targetInfo)
2408+
return std::ranges::count_if(m_UniqueGOTargetInfo, [effect](GOTargetInfo const& targetInfo)
23922409
{
23932410
return targetInfo.EffectMask & (1 << effect);
23942411
});
23952412
}
23962413

23972414
int64 Spell::GetItemTargetCountForEffect(SpellEffIndex effect) const
23982415
{
2399-
return std::count_if(m_UniqueItemInfo.begin(), m_UniqueItemInfo.end(), [effect](ItemTargetInfo const& targetInfo)
2416+
return std::ranges::count_if(m_UniqueItemInfo, [effect](ItemTargetInfo const& targetInfo)
24002417
{
24012418
return targetInfo.EffectMask & (1 << effect);
24022419
});
@@ -7777,16 +7794,18 @@ void Spell::DoEffectOnLaunchTarget(TargetInfo& targetInfo, float multiplier, Spe
77777794

77787795
if (m_originalCaster && m_damage > 0)
77797796
{
7780-
if (spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect() || spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
7797+
bool isAoeTarget = spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect() || spellEffectInfo.IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA);
7798+
if (isAoeTarget)
77817799
{
77827800
m_damage = unit->CalculateAOEAvoidance(m_damage, m_spellInfo->SchoolMask, m_originalCaster->GetGUID());
77837801

77847802
if (m_originalCaster->GetTypeId() == TYPEID_PLAYER)
77857803
{
7804+
int64 targetCount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex);
7805+
77867806
// cap damage of player AOE
7787-
int64 targetAmount = GetUnitTargetCountForEffect(spellEffectInfo.EffectIndex);
7788-
if (targetAmount > 10)
7789-
m_damage = m_damage * 10 / targetAmount;
7807+
if (targetCount > AOE_DAMAGE_TARGET_CAP)
7808+
m_damage = m_damage * AOE_DAMAGE_TARGET_CAP / targetCount;
77907809
}
77917810
}
77927811
}

‎src/server/game/Spells/Spell.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ enum WeaponAttackType : uint8;
7272
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS)
7373
#define MAX_SPELL_RANGE_TOLERANCE 3.0f
7474
#define TRAJECTORY_MISSILE_SIZE 3.0f
75+
#define AOE_DAMAGE_TARGET_CAP SI64LIT(10)
7576

7677
enum SpellCastFlags
7778
{
@@ -640,6 +641,8 @@ class TC_GAME_API Spell
640641

641642
SpellDestination m_destTargets[MAX_SPELL_EFFECTS];
642643

644+
int32 GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const;
645+
643646
void AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid = true, bool implicit = true, Position const* losPosition = nullptr);
644647
void AddGOTarget(GameObject* target, uint32 effectMask);
645648
void AddItemTarget(Item* item, uint32 effectMask);

‎src/server/game/Spells/SpellScript.cpp‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,17 @@ int64 SpellScript::GetUnitTargetCountForEffect(SpellEffIndex effect) const
524524
return m_spell->GetUnitTargetCountForEffect(effect);
525525
}
526526

527+
int32 SpellScript::GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const
528+
{
529+
if (!IsAfterTargetSelectionPhase())
530+
{
531+
TC_LOG_ERROR("scripts", "Script: `{}` Spell: `{}`: function SpellScript::GetUnitTargetIndexForEffect was called, but function has no effect in current hook! (spell has not selected targets yet)",
532+
m_scriptName->c_str(), m_scriptSpellId);
533+
return 0;
534+
}
535+
return m_spell->GetUnitTargetIndexForEffect(target, effect);
536+
}
537+
527538
int64 SpellScript::GetGameObjectTargetCountForEffect(SpellEffIndex effect) const
528539
{
529540
if (!IsAfterTargetSelectionPhase())

‎src/server/game/Spells/SpellScript.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ class TC_GAME_API SpellScript : public _SpellScript
469469

470470
// methods usable only after spell targets have been fully selected
471471
int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
472+
int32 GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const;
472473
int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
473474
int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
474475

‎src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp‎

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
#include "ScriptMgr.h"
2424
#include "InstanceScript.h"
25+
#include "Map.h"
2526
#include "naxxramas.h"
2627
#include "ScriptedCreature.h"
28+
#include "SpellScript.h"
2729

2830
enum PatchwerkTexts
2931
{
@@ -38,6 +40,7 @@ enum PatchwerkSpells
3840
{
3941
SPELL_HATEFUL_STRIKE_PRIMER = 28307,
4042
SPELL_HATEFUL_STRIKE = 28308,
43+
SPELL_HATEFUL_STRIKE_HEROIC = 59192,
4144
SPELL_FRENZY = 28131,
4245
SPELL_BERSERK = 26662,
4346
SPELL_SLIME_BOLT = 32309
@@ -106,54 +109,10 @@ struct boss_patchwerk : public BossAI
106109
{
107110
switch (eventId)
108111
{
109-
// Move everything to SPELL_HATEFUL_STRIKE_PRIMER spell script
110112
case EVENT_HATEFUL:
111-
{
112-
// Hateful Strike targets the highest non-MT threat in melee range on 10man
113-
// and the higher HP target out of the two highest non-MT threats in melee range on 25man
114-
ThreatReference* secondThreat = nullptr;
115-
ThreatReference* thirdThreat = nullptr;
116-
117-
ThreatManager& mgr = me->GetThreatManager();
118-
Unit* currentVictim = mgr.GetCurrentVictim();
119-
auto list = mgr.GetModifiableThreatList();
120-
auto it = list.begin(), end = list.end();
121-
if (it == end)
122-
{
123-
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
124-
return;
125-
}
126-
127-
if ((*it)->GetVictim() != currentVictim)
128-
secondThreat = *it;
129-
if ((!secondThreat || Is25ManRaid()) && (++it != end && (*it)->IsAvailable()))
130-
{
131-
if ((*it)->GetVictim() != currentVictim)
132-
(secondThreat ? thirdThreat : secondThreat) = *it;
133-
if (!thirdThreat && Is25ManRaid() && (++it != end && (*it)->IsAvailable()))
134-
thirdThreat = *it;
135-
}
136-
137-
Unit* pHatefulTarget = nullptr;
138-
if (!secondThreat)
139-
pHatefulTarget = currentVictim;
140-
else if (!thirdThreat)
141-
pHatefulTarget = secondThreat->GetVictim();
142-
else
143-
pHatefulTarget = (secondThreat->GetVictim()->GetHealth() < thirdThreat->GetVictim()->GetHealth()) ? thirdThreat->GetVictim() : secondThreat->GetVictim();
144-
145-
// add threat to highest threat targets
146-
AddThreat(currentVictim, HATEFUL_THREAT_AMT);
147-
if (secondThreat)
148-
secondThreat->AddThreat(HATEFUL_THREAT_AMT);
149-
if (thirdThreat)
150-
thirdThreat->AddThreat(HATEFUL_THREAT_AMT);
151-
152-
DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true);
153-
113+
DoCastSelf(SPELL_HATEFUL_STRIKE_PRIMER, true);
154114
events.Repeat(1200ms);
155115
break;
156-
}
157116
case EVENT_BERSERK:
158117
DoCastSelf(SPELL_BERSERK, true);
159118
Talk(EMOTE_BERSERK);
@@ -180,7 +139,65 @@ struct boss_patchwerk : public BossAI
180139
bool _enraged;
181140
};
182141

142+
// 28307 - Hateful Strike Primer
143+
class spell_patchwerk_hateful_strike_primer : public SpellScript
144+
{
145+
PrepareSpellScript(spell_patchwerk_hateful_strike_primer);
146+
147+
bool Validate(SpellInfo const* /*spellInfo*/) override
148+
{
149+
return ValidateSpellInfo({ SPELL_HATEFUL_STRIKE, SPELL_HATEFUL_STRIKE_HEROIC });
150+
}
151+
152+
void SelectTargets(std::list<WorldObject*>& targets)
153+
{
154+
Unit* caster = GetCaster();
155+
156+
uint32 targetLimit = caster->GetMap()->Is25ManRaid() ? 3 : 2;
157+
std::array<Unit*, 3> newTargets = { };
158+
auto newTargetsItr = newTargets.begin();
159+
auto newTargetsEnd = newTargetsItr + targetLimit;
160+
161+
for (ThreatReference const* threatRef : caster->GetThreatManager().GetSortedThreatList())
162+
{
163+
if (!threatRef->IsOnline() || !threatRef->GetVictim()->IsPlayer() || !caster->IsWithinMeleeRange(threatRef->GetVictim()))
164+
continue;
165+
166+
*newTargetsItr = threatRef->GetVictim();
167+
if (++newTargetsItr == newTargetsEnd)
168+
break;
169+
}
170+
171+
// Hateful Strike damages the higher HP target out of the two highest non-MT threats in melee range on 25man
172+
if (newTargets[1] && newTargets[2] && newTargets[1]->GetHealth() < newTargets[2]->GetHealth())
173+
std::swap(newTargets[1], newTargets[2]);
174+
175+
targets.assign(newTargets.begin(), newTargetsItr);
176+
}
177+
178+
void HandleEffect(SpellEffIndex effIndex)
179+
{
180+
Unit* caster = GetCaster();
181+
182+
// all targets get threat increase
183+
caster->GetThreatManager().AddThreat(GetHitUnit(), HATEFUL_THREAT_AMT, GetSpellInfo());
184+
185+
// Hateful Strike damages the second unit on target list (not the MT)
186+
// or MT if it is the only target
187+
if (GetUnitTargetIndexForEffect(GetHitUnit()->GetGUID(), effIndex) == 1
188+
|| GetUnitTargetCountForEffect(effIndex) == 1)
189+
caster->CastSpell(GetHitUnit(), caster->GetMap()->Is25ManRaid() ? SPELL_HATEFUL_STRIKE_HEROIC : SPELL_HATEFUL_STRIKE, true);
190+
}
191+
192+
void Register() override
193+
{
194+
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_patchwerk_hateful_strike_primer::SelectTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
195+
OnEffectHitTarget += SpellEffectFn(spell_patchwerk_hateful_strike_primer::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
196+
}
197+
};
198+
183199
void AddSC_boss_patchwerk()
184200
{
185201
RegisterNaxxramasCreatureAI(boss_patchwerk);
202+
RegisterSpellScript(spell_patchwerk_hateful_strike_primer);
186203
}

0 commit comments

Comments
 (0)