Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_scourgelord_tyrannus.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 "SpellAuraEffects.h"
10#include "pit_of_saron.h"
11#include "Vehicle.h"
12#include "Player.h"
13
44
61
79
87
95
96#define GUID_HOARFROST 1
97
98static const Position rimefangPos[10] =
99{
100 {1017.299f, 168.9740f, 642.9259f, 0.000000f},
101 {1047.868f, 126.4931f, 665.0453f, 0.000000f},
102 {1069.828f, 138.3837f, 665.0453f, 0.000000f},
103 {1063.042f, 164.5174f, 665.0453f, 0.000000f},
104 {1031.158f, 195.1441f, 665.0453f, 0.000000f},
105 {1019.087f, 197.8038f, 665.0453f, 0.000000f},
106 {967.6233f, 168.9670f, 665.0453f, 0.000000f},
107 {969.1198f, 140.4722f, 665.0453f, 0.000000f},
108 {986.7153f, 141.6424f, 665.0453f, 0.000000f},
109 {1012.601f, 142.4965f, 665.0453f, 0.000000f},
110};
111
112static const Position miscPos = {1018.376f, 167.2495f, 628.2811f, 0.000000f}; //tyrannus combat start position
113
115{
116 public:
117 boss_tyrannus() : CreatureScript("boss_tyrannus") { }
118
119 struct boss_tyrannusAI : public BossAI
120 {
122 {
123 }
124
126 {
127 if (instance->GetBossState(DATA_TYRANNUS) != DONE)
128 Reset();
129 else
130 me->DespawnOrUnsummon();
131 }
132
134 {
135 events.Reset();
136 events.SetPhase(PHASE_NONE);
137 me->SetReactState(REACT_PASSIVE);
139 instance->SetBossState(DATA_TYRANNUS, NOT_STARTED);
140 }
141
143 {
145 }
146
147 void EnterCombat(Unit* /*who*/) OVERRIDE
148 {
150 }
151
153 {
155 return;
156
157 if (victim && me->Attack(victim, true) && !events.IsInPhase(PHASE_INTRO))
158 me->GetMotionMaster()->MoveChase(victim);
159 }
160
162 {
163 instance->SetBossState(DATA_TYRANNUS, FAIL);
164 if (Creature* rimefang = GetRimefang())
165 rimefang->AI()->EnterEvadeMode();
166
167 me->DespawnOrUnsummon();
168 }
169
171 {
172 if (victim->GetTypeId() == TypeID::TYPEID_PLAYER)
173 Talk(SAY_SLAY);
174 }
175
176 void JustDied(Unit* /*killer*/) OVERRIDE
177 {
179 instance->SetBossState(DATA_TYRANNUS, DONE);
180
181 // Prevent corpse despawning
182 if (TempSummon* summ = me->ToTempSummon())
183 summ->SetTempSummonType(TempSummonType::TEMPSUMMON_DEAD_DESPAWN);
184
185 // Stop combat for Rimefang
186 if (Creature* rimefang = GetRimefang())
187 rimefang->AI()->DoAction(ACTION_END_COMBAT);
188 }
189
190 void DoAction(int32 actionId) OVERRIDE
191 {
192 if (actionId == ACTION_START_INTRO)
193 {
195 events.SetPhase(PHASE_INTRO);
196 events.ScheduleEvent(EVENT_INTRO_1, 14000, 0, PHASE_INTRO);
197 events.ScheduleEvent(EVENT_INTRO_2, 22000, 0, PHASE_INTRO);
198 events.ScheduleEvent(EVENT_INTRO_3, 34000, 0, PHASE_INTRO);
199 events.ScheduleEvent(EVENT_COMBAT_START, 36000, 0, PHASE_INTRO);
200 instance->SetBossState(DATA_TYRANNUS, IN_PROGRESS);
201 }
202 }
203
205 {
206 if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
207 return;
208
209 events.Update(diff);
210
211 while (uint32 eventId = events.ExecuteEvent())
212 {
213 switch (eventId)
214 {
215 case EVENT_INTRO_1:
216 //Talk(SAY_GORKUN_INTRO_2, pGorkunOrVictus);
217 break;
218 case EVENT_INTRO_2:
220 break;
221 case EVENT_INTRO_3:
222 me->ExitVehicle();
223 me->GetMotionMaster()->MovePoint(0, miscPos);
224 break;
226 if (Creature* rimefang = me->GetCreature(*me, instance->GetData64(DATA_RIMEFANG)))
227 rimefang->AI()->DoAction(ACTION_START_RIMEFANG); //set rimefang also infight
228 events.SetPhase(PHASE_COMBAT);
230 me->SetReactState(REACT_AGGRESSIVE);
233 events.ScheduleEvent(EVENT_OVERLORD_BRAND, std::rand() % 7000 + 5000);
234 events.ScheduleEvent(EVENT_FORCEFUL_SMASH, std::rand() % 16000 + 14000);
235 events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, std::rand() % 27000 + 25000);
236 break;
238 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
240 events.ScheduleEvent(EVENT_OVERLORD_BRAND, std::rand() % 12000 + 11000);
241 break;
244 events.ScheduleEvent(EVENT_UNHOLY_POWER, 1000);
245 break;
250 events.ScheduleEvent(EVENT_FORCEFUL_SMASH, std::rand() % 48000 + 40000);
251 break;
254 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
255 {
256 Talk(SAY_MARK_RIMEFANG_2, target);
258 }
259 events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, std::rand() % 26000 + 24000);
260 break;
261 }
262 }
263
265 }
266 };
267
269 {
270 return GetPitOfSaronAI<boss_tyrannusAI>(creature);
271 }
272};
273
275{
276 public:
277 boss_rimefang() : CreatureScript("boss_rimefang") { }
278
280 {
281 boss_rimefangAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit())
282 {
284 }
285
287 {
288 _events.Reset();
289 _events.SetPhase(PHASE_NONE);
292 me->SetCanFly(true);
293 me->SetReactState(REACT_PASSIVE);
295 }
296
298 {
299 _vehicle->InstallAllAccessories(false);
300 }
301
302 void DoAction(int32 actionId) OVERRIDE
303 {
304 if (actionId == ACTION_START_RIMEFANG)
305 {
306 _events.SetPhase(PHASE_COMBAT);
308 _events.ScheduleEvent(EVENT_MOVE_NEXT, 500, 0, PHASE_COMBAT);
309 _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT);
310 }
311 else if (actionId == ACTION_END_COMBAT)
313 }
314
315 void SetGUID(uint64 guid, int32 type) OVERRIDE
316 {
317 if (type == GUID_HOARFROST)
318 {
320 _events.ScheduleEvent(EVENT_HOARFROST, 1000);
321 }
322 }
323
325 {
326 if (!UpdateVictim() && !_events.IsInPhase(PHASE_COMBAT))
327 return;
328
329 _events.Update(diff);
330
331 while (uint32 eventId = _events.ExecuteEvent())
332 {
333 switch (eventId)
334 {
335 case EVENT_MOVE_NEXT:
336 if (_currentWaypoint >= 10 || _currentWaypoint == 0)
338 me->GetMotionMaster()->MovePoint(0, rimefangPos[_currentWaypoint]);
340 _events.ScheduleEvent(EVENT_MOVE_NEXT, 2000, 0, PHASE_COMBAT);
341 break;
342 case EVENT_ICY_BLAST:
343 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
344 DoCast(target, SPELL_ICY_BLAST);
345 _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT);
346 break;
347 case EVENT_HOARFROST:
348 if (Unit* target = me->GetUnit(*me, _hoarfrostTargetGUID))
349 {
350 DoCast(target, SPELL_HOARFROST);
352 }
353 break;
354 default:
355 break;
356 }
357 }
358 }
359
360 private:
365 };
366
368 {
369 return new boss_rimefangAI(creature);
370 }
371};
372
374{
375 public:
377 {
378 }
379
380 void SetGUID(uint64 guid, int32 /*type*/) OVERRIDE
381 {
382 _tyrannus = guid;
383 }
384
385 void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) OVERRIDE
386 {
388 if (tyrannus->GetVictim())
389 me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->GetVictim(), true, NULL, NULL, tyrannus->GetGUID());
390 }
391
392 void HealDone(Unit* /*target*/, uint32& addHealth) OVERRIDE
393 {
395 me->CastCustomSpell(SPELL_OVERLORD_BRAND_HEAL, SPELLVALUE_BASE_POINT0, int32(addHealth*5.5f), tyrannus, true, NULL, NULL, tyrannus->GetGUID());
396 }
397
398 void UpdateAI(uint32 /*diff*/) OVERRIDE { }
399
400 private:
402};
403
405{
406 public:
407 spell_tyrannus_overlord_brand() : SpellScriptLoader("spell_tyrannus_overlord_brand") { }
408
449
454};
455
457{
458 public:
459 spell_tyrannus_mark_of_rimefang() : SpellScriptLoader("spell_tyrannus_mark_of_rimefang") { }
460
462 {
464
465 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
466 {
467 Unit* caster = GetCaster();
468 if (!caster || caster->GetTypeId() != TypeID::TYPEID_UNIT)
469 return;
470
471 if (InstanceScript* instance = caster->GetInstanceScript())
472 if (Creature* rimefang = ObjectAccessor::GetCreature(*caster, instance->GetData64(DATA_RIMEFANG)))
473 rimefang->AI()->SetGUID(GetTarget()->GetGUID(), GUID_HOARFROST);
474 }
475
480 };
481
486};
487
489{
490 public:
491 at_tyrannus_event_starter() : AreaTriggerScript("at_tyrannus_event_starter") { }
492
493 bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) OVERRIDE
494 {
495 InstanceScript* instance = player->GetInstanceScript();
496 if (player->IsGameMaster() || !instance)
497 return false;
498
499 if (instance->GetBossState(DATA_TYRANNUS) != IN_PROGRESS && instance->GetBossState(DATA_TYRANNUS) != DONE)
500 if (Creature* tyrannus = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_TYRANNUS)))
501 {
502 tyrannus->AI()->DoAction(ACTION_START_INTRO);
503 return true;
504 }
505
506 return false;
507 }
508};
509
Actions
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
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
@ IN_PROGRESS
@ FAIL
@ DONE
@ NOT_STARTED
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ TEMPSUMMON_DEAD_DESPAWN
Definition Object.h:74
@ EFFECT_0
@ SPELL_AURA_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
#define AuraEffectApplyFn(F, I, N, M)
#define AuraEffectRemoveFn(F, I, N, M)
@ SPELLVALUE_BASE_POINT0
Definition Unit.h:114
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
DamageEffectType
Definition Unit.h:613
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_FLAGS
@ SAY_SLAY
@ PHASE_INTRO
@ PHASE_COMBAT
#define SAY_DEATH
#define SAY_AGGRO
@ PHASE_NONE
@ SAY_JAYNA_OUTRO_4
@ SAY_SYLVANAS_OUTRO_4
@ PHASE_OUTRO
@ EVENT_INTRO_1
@ EVENT_INTRO_2
@ EVENT_INTRO_3
static const Position miscPos
#define GUID_HOARFROST
static const Position rimefangPos[10]
@ SPELL_OVERLORD_BRAND_HEAL
@ SPELL_OVERLORD_BRAND_DAMAGE
@ SPELL_EJECT_ALL_PASSENGERS
void AddSC_boss_tyrannus()
AreaTriggerScript(const char *name)
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectApplyHandler > AfterEffectApply
uint64 GetCasterGUID() const
Unit * GetCaster() const
Unit * GetTarget() const
InstanceScript *const instance
EventMap events
BossAI(Creature *creature, uint32 bossId)
void DoZoneInCombat(Creature *creature=NULL, float maxRangeToNearestTarget=50.0f)
bool _EnterEvadeMode()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
EncounterState GetBossState(uint32 id) const
static Creature * GetCreature(WorldObject const &u, uint64 guid)
TypeID GetTypeId() const
Definition Object.h:131
uint32 GetEntry() const
Definition Object.h:125
Player *const me
Definition UnitAI.h:263
PlayerAI(Player *player)
Definition UnitAI.h:265
SpellScriptLoader(const char *name)
virtual void SetGUID(uint64, int32=0)
Definition UnitAI.h:129
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
void SetAI(UnitAI *newAI)
Definition Unit.h:1397
bool IsAIEnabled
Definition Unit.h:2735
UnitAI * GetAI()
Definition Unit.h:1393
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
virtual uint64 GetData64(uint32) const
Definition ZoneScript.h:32
bool OnTrigger(Player *player, const AreaTriggerEntry *) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
void DamageDealt(Unit *, uint32 &damage, DamageEffectType) OVERRIDE
void HealDone(Unit *, uint32 &addHealth) OVERRIDE
void SetGUID(uint64 guid, int32) OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
@ ACTION_START_INTRO
@ NPC_TYRANNUS
AI * GetPitOfSaronAI(Creature *creature)
@ DATA_RIMEFANG
@ DATA_TYRANNUS
Creature * me
ScriptedAI(Creature *creature)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DoAction(int32 actionId) OVERRIDE
void SetGUID(uint64 guid, int32 type) OVERRIDE
void DoAction(int32 actionId) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================