Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_thaddius.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "ScriptMgr.h"
7#include "ScriptedCreature.h"
8#include "SpellScript.h"
9#include "Player.h"
10#include "naxxramas.h"
11
12//Stalagg
19
27
28//Feugen
35
42
43// Thaddius DoAction
51
52//generic
53#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!")
54
55//Thaddius
65
80
88
90{
92};
93
95{
96public:
97 boss_thaddius() : CreatureScript("boss_thaddius") { }
98
100 {
101 return new boss_thaddiusAI(creature);
102 }
103
104 struct boss_thaddiusAI : public BossAI
105 {
107 {
108 // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe
109 // and, in particular, if there was a crash after both adds were killed (should not respawn)
110
111 // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn
112 // and each mob will send its status at reset (meaning that it is alive)
113 checkFeugenAlive = false;
114 if (Creature* pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
115 checkFeugenAlive = pFeugen->IsAlive();
116
117 checkStalaggAlive = false;
118 if (Creature* pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
119 checkStalaggAlive = pStalagg->IsAlive();
120
122 {
124 me->SetReactState(REACT_AGGRESSIVE);
125 }
126 else
127 {
129 me->SetReactState(REACT_PASSIVE);
130 }
131 }
132
137
138 void KilledUnit(Unit* /*victim*/) OVERRIDE
139 {
140 if (!(rand()%5))
141 Talk(SAY_SLAY);
142 }
143
144 void JustDied(Unit* /*killer*/) OVERRIDE
145 {
146 _JustDied();
148 }
149
151 {
152 switch (action)
153 {
155 checkFeugenAlive = true;
156 break;
158 checkFeugenAlive = false;
159 break;
161 checkStalaggAlive = true;
162 break;
164 checkStalaggAlive = false;
165 break;
166 }
167
169 {
171 // REACT_AGGRESSIVE only reset when he takes damage.
173 }
174 else
175 {
177 me->SetReactState(REACT_PASSIVE);
178 }
179 }
180
181 void EnterCombat(Unit* /*who*/) OVERRIDE
182 {
183 _EnterCombat();
185 events.ScheduleEvent(EVENT_SHIFT, 30000);
186 events.ScheduleEvent(EVENT_CHAIN, std::rand() % 20000 + 10000);
187 events.ScheduleEvent(EVENT_BERSERK, 360000);
188 }
189
190 void DamageTaken(Unit* /*pDoneBy*/, uint32 & /*uiDamage*/) OVERRIDE
191 {
192 me->SetReactState(REACT_AGGRESSIVE);
193 }
194
196 {
197 if (id == DATA_POLARITY_SWITCH)
198 polaritySwitch = data ? true : false;
199 }
200
202 {
203 if (id != DATA_POLARITY_SWITCH)
204 return 0;
205
206 return uint32(polaritySwitch);
207 }
208
210 {
212 uiAddsTimer = 0;
213
215 {
216 uiAddsTimer += diff;
217 if (uiAddsTimer > 5000)
218 {
220 {
221 if (instance)
222 if (Creature* pStalagg = me->GetCreature(*me, instance->GetData64(DATA_STALAGG)))
223 pStalagg->Respawn();
224 }
225 else
226 {
227 if (instance)
228 if (Creature* pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
229 pFeugen->Respawn();
230 }
231 }
232 }
233
234 if (!UpdateVictim())
235 return;
236
237 events.Update(diff);
238
239 if (me->HasUnitState(UNIT_STATE_CASTING))
240 return;
241
242 while (uint32 eventId = events.ExecuteEvent())
243 {
244 switch (eventId)
245 {
246 case EVENT_SHIFT:
248 events.ScheduleEvent(EVENT_SHIFT, 30000);
249 return;
250 case EVENT_CHAIN:
252 events.ScheduleEvent(EVENT_CHAIN, std::rand() % 20000 + 10000);
253 return;
254 case EVENT_BERSERK:
256 return;
257 }
258 }
259
260 if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->GetVictim()))
262 else
264 }
265 };
266};
267
269{
270public:
271 npc_stalagg() : CreatureScript("npc_stalagg") { }
272
274 {
275 return new npc_stalaggAI(creature);
276 }
277
278 struct npc_stalaggAI : public ScriptedAI
279 {
280 npc_stalaggAI(Creature* creature) : ScriptedAI(creature)
281 {
282 instance = creature->GetInstanceScript();
283 }
284
286
289
291 {
292 if (instance)
293 if (Creature* pThaddius = me->GetCreature(*me, instance->GetData64(DATA_THADDIUS)))
294 if (pThaddius->AI())
295 pThaddius->AI()->DoAction(ACTION_STALAGG_RESET);
296 powerSurgeTimer = std::rand() % 25000 + 20000;
297 magneticPullTimer = 20000;
298 }
299
300 void KilledUnit(Unit* /*victim*/) OVERRIDE
301 {
302 if (!(rand()%5))
304 }
305
306 void EnterCombat(Unit* /*who*/) OVERRIDE
307 {
310 }
311
312 void JustDied(Unit* /*killer*/) OVERRIDE
313 {
315 if (instance)
316 if (Creature* pThaddius = me->GetCreature(*me, instance->GetData64(DATA_THADDIUS)))
317 if (pThaddius->AI())
318 pThaddius->AI()->DoAction(ACTION_STALAGG_DIED);
319 }
320
322 {
323 if (!UpdateVictim())
324 return;
325
326 if (magneticPullTimer <= uiDiff)
327 {
328 if (Creature* pFeugen = me->GetCreature(*me, instance->GetData64(DATA_FEUGEN)))
329 {
330 Unit* pStalaggVictim = me->GetVictim();
331 Unit* pFeugenVictim = pFeugen->GetVictim();
332
333 if (pFeugenVictim && pStalaggVictim)
334 {
335 // magnetic pull is not working. So just jump.
336
337 // reset aggro to be sure that feugen will not follow the jump
338 pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100);
339 pFeugenVictim->JumpTo(me, 0.3f);
340
341 me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100);
342 pStalaggVictim->JumpTo(pFeugen, 0.3f);
343 }
344 }
345
346 magneticPullTimer = 20000;
347 }
348 else magneticPullTimer -= uiDiff;
349
350 if (powerSurgeTimer <= uiDiff)
351 {
353 powerSurgeTimer = std::rand() % 20000 + 15000;
354 } else powerSurgeTimer -= uiDiff;
355
357 }
358 };
359};
360
362{
363public:
364 npc_feugen() : CreatureScript("npc_feugen") { }
365
367 {
368 return new npc_feugenAI(creature);
369 }
370
371 struct npc_feugenAI : public ScriptedAI
372 {
373 npc_feugenAI(Creature* creature) : ScriptedAI(creature)
374 {
375 instance = creature->GetInstanceScript();
376 }
377
379
381
383 {
384 if (instance)
385 if (Creature* pThaddius = me->GetCreature(*me, instance->GetData64(DATA_THADDIUS)))
386 if (pThaddius->AI())
387 pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET);
388 staticFieldTimer = 5000;
389 }
390
391 void KilledUnit(Unit* /*victim*/) OVERRIDE
392 {
393 if (!(rand()%5))
395 }
396
397 void EnterCombat(Unit* /*who*/) OVERRIDE
398 {
401 }
402
403 void JustDied(Unit* /*killer*/) OVERRIDE
404 {
406 if (instance)
407 if (Creature* pThaddius = me->GetCreature(*me, instance->GetData64(DATA_THADDIUS)))
408 if (pThaddius->AI())
409 pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED);
410 }
411
413 {
414 if (!UpdateVictim())
415 return;
416
417 if (staticFieldTimer <= uiDiff)
418 {
420 staticFieldTimer = 5000;
421 } else staticFieldTimer -= uiDiff;
422
424 }
425 };
426};
427
429{
430 public:
431 spell_thaddius_pos_neg_charge() : SpellScriptLoader("spell_thaddius_pos_neg_charge") { }
432
434 {
436
437 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
438 {
439 if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE))
440 return false;
441 if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_STACK))
442 return false;
443 if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE))
444 return false;
445 if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_STACK))
446 return false;
447 return true;
448 }
449
451 {
453 }
454
455 void HandleTargets(std::list<WorldObject*>& targets)
456 {
457 uint8 count = 0;
458 for (std::list<WorldObject*>::iterator ihit = targets.begin(); ihit != targets.end(); ++ihit)
459 if ((*ihit)->GetGUID() != GetCaster()->GetGUID())
460 if (Player* target = (*ihit)->ToPlayer())
461 if (target->HasAura(GetTriggeringSpell()->Id))
462 ++count;
463
464 if (count)
465 {
466 uint32 spellId = 0;
467
470 else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE)
472
473 GetCaster()->SetAuraStack(spellId, GetCaster(), count);
474 }
475 }
476
477 void HandleDamage(SpellEffIndex /*effIndex*/)
478 {
479 if (!GetTriggeringSpell())
480 return;
481
482 Unit* target = GetHitUnit();
483 Unit* caster = GetCaster();
484
485 if (target->HasAura(GetTriggeringSpell()->Id))
486 SetHitDamage(0);
487 else
488 {
489 if (target->GetTypeId() == TypeID::TYPEID_PLAYER && caster->IsAIEnabled)
490 caster->ToCreature()->AI()->SetData(DATA_POLARITY_SWITCH, 1);
491 }
492 }
493
499 };
500
505};
506
508{
509 public:
510 spell_thaddius_polarity_shift() : SpellScriptLoader("spell_thaddius_polarity_shift") { }
511
513 {
515
516 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
517 {
518 if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_POLARITY) || !sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_POLARITY))
519 return false;
520 return true;
521 }
522
523 void HandleDummy(SpellEffIndex /* effIndex */)
524 {
525 Unit* caster = GetCaster();
526 if (Unit* target = GetHitUnit())
527 target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, NULL, NULL, caster->GetGUID());
528 }
529
534 };
535
540};
541
543{
544 public:
545 achievement_polarity_switch() : AchievementCriteriaScript("achievement_polarity_switch") { }
546
547 bool OnCheck(Player* /*source*/, Unit* target) OVERRIDE
548 {
549 return target && target->GetAI()->GetData(DATA_POLARITY_SWITCH);
550 }
551};
552
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ TARGET_UNIT_SRC_AREA_ALLY
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_STUNNED
Definition Unit.h:643
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ UNIT_FIELD_FLAGS
bool roll_chance_i(int chance)
Definition Util.h:89
@ SAY_SLAY
@ SAY_GREET
#define SAY_DEATH
#define SAY_AGGRO
@ EVENT_NONE
#define SPELL_BERSERK
@ EVENT_CHAIN
Achievement
@ EVENT_BERSERK
@ DATA_POLARITY_SWITCH
void AddSC_boss_thaddius()
StalagSpells
@ SPELL_POWERSURGE
@ SPELL_MAGNETIC_PULL
@ SPELL_STALAGG_TESLA
@ H_SPELL_POWERSURGE
FeugenSpells
@ SPELL_FEUGEN_TESLA
@ H_SPELL_STATICFIELD
@ SPELL_STATICFIELD
StalaggYells
@ SAY_STAL_AGGRO
@ SAY_STAL_DEATH
@ SAY_STAL_SLAY
ThaddiusYells
@ SAY_DEATH
@ SAY_ELECT
@ SAY_SCREAM
@ SAY_AGGRO
@ SAY_SLAY
ThaddiusSpells
@ SPELL_NEGATIVE_CHARGE
@ SPELL_POLARITY_SHIFT
@ SPELL_BALL_LIGHTNING
@ H_SPELL_CHAIN_LIGHTNING
@ SPELL_POSITIVE_CHARGE
@ SPELL_POSITIVE_POLARITY
@ SPELL_POSITIVE_CHARGE_STACK
@ SPELL_NEGATIVE_CHARGE_STACK
@ SPELL_NEGATIVE_POLARITY
@ SPELL_CHAIN_LIGHTNING
@ SPELL_BERSERK
@ EVENT_SHIFT
@ EVENT_BERSERK
@ EVENT_CHAIN
ThaddiusActions
@ ACTION_STALAGG_DIED
@ ACTION_FEUGEN_RESET
@ ACTION_FEUGEN_DIED
@ ACTION_STALAGG_RESET
FeugenYells
@ SAY_FEUG_AGGRO
@ SAY_FEUG_SLAY
@ SAY_FEUG_DEATH
@ SPELL_CHAIN_LIGHTNING
AchievementCriteriaScript(const char *name)
InstanceScript *const instance
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
Creature * ToCreature()
Definition Object.h:207
SpellInfo const * GetSpellInfo()
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
SpellInfo const * GetTriggeringSpell()
void SetHitDamage(int32 damage)
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
virtual void SetData(uint32, uint32)
Definition UnitAI.h:128
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
Definition Unit.h:1367
void SetAuraStack(uint32 spellId, Unit *target, uint32 stack)
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
void JumpTo(float speedXY, float speedZ, bool forward=true)
Definition Unit.cpp:8139
Unit * GetVictim() const
Definition Unit.h:1468
bool IsAIEnabled
Definition Unit.h:2735
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
bool OnCheck(Player *, Unit *target) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ DATA_THADDIUS
Definition naxxramas.h:50
@ DATA_FEUGEN
Definition naxxramas.h:52
@ DATA_STALAGG
Definition naxxramas.h:53
@ BOSS_THADDIUS
Definition naxxramas.h:22
Creature * me
const T & RAID_MODE(const T &normal10, const T &normal25) const
ScriptedAI(Creature *creature)
void DamageTaken(Unit *, uint32 &) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
boss_thaddiusAI(Creature *creature)
void DoAction(int32 action) OVERRIDE
void SetData(uint32 id, uint32 data) OVERRIDE
uint32 GetData(uint32 id) const OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void JustDied(Unit *) OVERRIDE
void KilledUnit(Unit *) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
npc_feugenAI(Creature *creature)
void EnterCombat(Unit *) OVERRIDE
void KilledUnit(Unit *) OVERRIDE
void JustDied(Unit *) OVERRIDE
npc_stalaggAI(Creature *creature)
void KilledUnit(Unit *) OVERRIDE
void JustDied(Unit *) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void EnterCombat(Unit *) OVERRIDE