TrinityCore
Loading...
Searching...
No Matches
boss_sartharion.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ScriptMgr.h"
19#include "CellImpl.h"
20#include "Containers.h"
21#include "GridNotifiersImpl.h"
22#include "InstanceScript.h"
23#include "MotionMaster.h"
24#include "ObjectAccessor.h"
25#include "obsidian_sanctum.h"
26#include "ScriptedCreature.h"
27#include "TemporarySummon.h"
28
30{
31 //Sartharion Yell
42
43 //Sartharion Spells
44 SPELL_BERSERK = 61632, // Increases the caster's attack speed by 150% and all damage it deals by 500% for 5 min.
45 SPELL_CLEAVE = 56909, // Inflicts 35% weapon damage to an enemy and its nearest allies, affecting up to 10 targets.
46 SPELL_FLAME_BREATH = 56908, // Inflicts 8750 to 11250 Fire damage to enemies in a cone in front of the caster.
47 SPELL_TAIL_LASH = 56910, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec.
48 SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%.
49 SPELL_LAVA_STRIKE = 57571, // (Real spell cast should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572)
52
53 SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes
54 SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x Creature entry 30494)
55
56 //Vesperon
57 //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
58 NPC_ACOLYTE_OF_VESPERON = 31219, // Acolyte of Vesperon
59 SPELL_POWER_OF_VESPERON = 61251, // Vesperon's presence decreases the maximum health of all enemies by 25%.
60
61 //Shadron
62 //In portal is a disciple, when disciple killed remove Power_of_vesperon, portal open multiple times
63 NPC_ACOLYTE_OF_SHADRON = 31218, // Acolyte of Shadron
64 SPELL_POWER_OF_SHADRON = 58105, // Shadron's presence increases Fire damage taken by all enemies by 100%.
65
66 //Tenebron
67 //in the portal spawns 6 eggs, if not killed in time (approx. 20s) they will hatch, whelps can cast 60708
68 SPELL_POWER_OF_TENEBRON = 61248, // Tenebron's presence increases Shadow damage taken by all enemies by 100%.
69
70 NPC_FLAME_TSUNAMI = 30616, // for the flame waves
71
72 //using these custom points for dragons start and end
74 POINT_ID_LAND = 200
75};
76
77enum Misc
78{
80};
81
82Position const FlameRight1Spawn = { 3200.00f, 573.211f, 57.1551f, 0.0f };
83Position const FlameRight1Direction = { 3289.28f, 573.211f, 57.1551f, 0.0f };
84Position const FlameRight2Spawn = { 3200.00f, 532.211f, 57.1551f, 0.0f };
85Position const FlameRight2Direction = { 3289.28f, 532.211f, 57.1551f, 0.0f };
86Position const FlameRight3Spawn = { 3200.00f, 491.211f, 57.1551f, 0.0f };
87Position const FlameRight3Direction = { 3289.28f, 491.211f, 57.1551f, 0.0f };
88Position const FlameLeft1Spawn = { 3289.28f, 511.711f, 57.1551f, 0.0f };
89Position const FlameLeft1Direction = { 3200.00f, 511.711f, 57.1551f, 0.0f };
90Position const FlameLeft2Spawn = { 3289.28f, 552.711f, 57.1551f, 0.0f };
91Position const FlameLeft2Direction = { 3200.00f, 552.711f, 57.1551f, 0.0f };
92
93//each dragons special points. First where fly to before connect to connon, second where land point is.
95{
96 { 3212.854f, 575.597f, 109.856f, 0.0f }, // init
97 { 3246.425f, 565.367f, 61.249f, 0.0f } // end
98};
99
101{
102 { 3293.238f, 472.223f, 106.968f, 0.0f },
103 { 3271.669f, 526.907f, 61.931f, 0.0f }
104};
105
107{
108 { 3193.310f, 472.861f, 102.697f, 0.0f },
109 { 3227.268f, 533.238f, 59.995f, 0.0f }
110};
111
124
125/*######
126## Boss Sartharion
127######*/
128
129struct boss_sartharion : public BossAI
130{
132 {
133 Initialize();
134 }
135
137 {
138 _isBerserk = false;
139 _isSoftEnraged = false;
140 _isHardEnraged = false;
141 drakeCount = 0;
142 }
143
144 void Reset() override
145 {
146 Initialize();
147
150
151 me->SetHomePosition(3246.57f, 551.263f, 58.6164f, 4.66003f);
152
153 DrakeRespawn();
155 }
156
157 void JustReachedHome() override
158 {
159 _Reset();
160 }
161
179
180 void JustDied(Unit* /*killer*/) override
181 {
183 _JustDied();
184
186 if (tenebron->IsAlive())
187 tenebron->DisappearAndDie();
188
190 if (shadron->IsAlive())
191 shadron->DisappearAndDie();
192
194 if (vesperon->IsAlive())
195 vesperon->DisappearAndDie();
196 }
197
198 void KilledUnit(Unit* who) override
199 {
200 if (who->GetTypeId() == TYPEID_PLAYER)
202 }
203
204 // me->ResetLootMode() is called from Reset()
205 // AddDrakeLootMode() should only ever be called from FetchDragons(), which is called from Aggro()
207 {
208 if (me->HasLootMode(LOOT_MODE_HARD_MODE_2)) // Has two Drake loot modes
209 me->AddLootMode(LOOT_MODE_HARD_MODE_3); // Add 3rd Drake loot mode
210 else if (me->HasLootMode(LOOT_MODE_HARD_MODE_1)) // Has one Drake loot mode
211 me->AddLootMode(LOOT_MODE_HARD_MODE_2); // Add 2nd Drake loot mode
212 else // Has no Drake loot modes
213 me->AddLootMode(LOOT_MODE_HARD_MODE_1); // Add 1st Drake loot mode
214 }
215
216 void DrakeRespawn() // Drakes respawning system
217 {
219 {
220 tenebron->SetHomePosition(3239.07f, 657.235f, 86.8775f, 4.74729f);
221 if (tenebron->IsAlive())
222 {
223 if (tenebron->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
224 tenebron->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
225 tenebron->GetMotionMaster()->MoveTargetedHome();
226 }
227 else
228 {
230 {
231 tenebron->Respawn();
232 tenebron->GetMotionMaster()->MoveTargetedHome();
233 tenebron->AI()->SetData(DATA_CAN_LOOT, 0);
234 }
235 }
236 }
237
239 {
240 shadron->SetHomePosition(3363.06f, 525.28f, 98.362f, 4.76475f);
241 if (shadron->IsAlive())
242 {
243 if (shadron->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
244 shadron->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
245 shadron->GetMotionMaster()->MoveTargetedHome();
246 }
247 else
248 {
250 {
251 shadron->Respawn();
252 shadron->GetMotionMaster()->MoveTargetedHome();
253 shadron->AI()->SetData(DATA_CAN_LOOT, 0);
254 }
255 }
256 }
257
259 {
260 vesperon->SetHomePosition(3145.68f, 520.71f, 89.7f, 4.64258f);
261 if (vesperon->IsAlive())
262 {
263 if (vesperon->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
264 vesperon->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
265 vesperon->GetMotionMaster()->MoveTargetedHome();
266 }
267 else
268 {
270 {
271 vesperon->Respawn();
272 vesperon->GetMotionMaster()->MoveTargetedHome();
273 vesperon->AI()->SetData(DATA_CAN_LOOT, 0);
274 }
275 }
276 }
277 }
278
280 {
281 me->ResetLootMode();
282 drakeCount = 0;
283
284 //if at least one of the dragons are alive and are being called
285 bool _canUseWill = false;
286
288 {
289 if (fetchTene->IsAlive() && !fetchTene->GetVictim())
290 {
291 _canUseWill = true;
292 if (!fetchTene->IsInCombat())
293 {
296 ++drakeCount;
297 }
298 fetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, TenebronPositions[0]);
299
300 if (!fetchTene->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
301 fetchTene->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
302 }
303 }
304
306 {
307 if (fetchShad->IsAlive() && !fetchShad->GetVictim())
308 {
309 _canUseWill = true;
310 if (!fetchShad->IsInCombat())
311 {
314 ++drakeCount;
315 }
316 fetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, ShadronPositions[0]);
317
318 if (!fetchShad->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
319 fetchShad->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
320 }
321 }
322
324 {
325 if (fetchVesp->IsAlive() && !fetchVesp->GetVictim())
326 {
327 _canUseWill = true;
328 if (!fetchVesp->IsInCombat())
329 {
332 ++drakeCount;
333 }
334 fetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, VesperonPositions[0]);
335
336 if (!fetchVesp->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
337 fetchVesp->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
338 }
339 }
340
341 if (_canUseWill)
343 }
344
345 void CallDragon(uint32 dataId)
346 {
348 {
349 if (temp->IsAlive() && !temp->GetVictim())
350 {
351 temp->SetWalk(false);
352
353 if (temp->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
354 temp->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
355
356 uint8 textId = 0;
357
358 switch (temp->GetEntry())
359 {
360 case NPC_TENEBRON:
362 temp->AddAura(SPELL_POWER_OF_TENEBRON, temp);
363 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, TenebronPositions[1]);
364 break;
365 case NPC_SHADRON:
367 temp->AddAura(SPELL_POWER_OF_SHADRON, temp);
368 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, ShadronPositions[1]);
369 break;
370 case NPC_VESPERON:
372 temp->AddAura(SPELL_POWER_OF_VESPERON, temp);
373 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, VesperonPositions[1]);
374 break;
375 }
376
377 Talk(textId);
378 }
379 }
380 }
381
382 uint32 GetData(uint32 type) const override
383 {
384 if (type == TWILIGHT_ACHIEVEMENTS)
385 return drakeCount;
386
387 return 0;
388 }
389
390 // Selects a random Fire Cyclone and makes it cast Lava Strike.
391 // FIXME: Frequency of the casts reduced to compensate 100% chance of spawning a Lava Blaze add
393 {
394 std::list<Creature*> fireCyclonesList;
397 Cell::VisitAllObjects(me, searcher, 200.0f);
398
399 if (fireCyclonesList.empty())
400 return;
401
402 Trinity::Containers::SelectRandomContainerElement(fireCyclonesList)->CastSpell(target, SPELL_LAVA_STRIKE, true);
403 }
404
405 void UpdateAI(uint32 diff) override
406 {
407 if (!UpdateVictim())
408 return;
409
410 events.Update(diff);
411
412 while (uint32 eventId = events.ExecuteEvent())
413 {
414 switch (eventId)
415 {
417 if (!_isHardEnraged)
418 {
419 DoCast(me, SPELL_PYROBUFFET, true);
420 _isHardEnraged = true;
421 }
422 break;
425 switch (urand(0, 1))
426 {
427 case 0:
428 {
430 right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction);
432 right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction);
434 right3->GetMotionMaster()->MovePoint(0, FlameRight3Direction);
435 break;
436 }
437 case 1:
438 {
440 left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction);
442 left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction);
443 break;
444 }
445 }
447 break;
452 break;
453 case EVENT_TAIL_SWEEP:
456 break;
460 break;
463 {
465 if (urand(0, 5) == 0)
467 }
468 if (_isSoftEnraged)
470 else
472 break;
475 break;
478 break;
481 break;
482 default:
483 break;
484 }
485 }
486
487 // At 35% spell will target dragons, if they are still alive.
488 if (!_isBerserk && !HealthAbovePct(35))
489 {
491 {
494 _isBerserk = true;
495 }
496 }
497
498 // Soft Enrage used while determining Lava Strike cooldown.
499 if (!_isSoftEnraged && HealthBelowPct(10))
500 {
501 _isSoftEnraged = true;
502 }
503
505 }
506
507private:
512};
513
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ DONE
@ NOT_STARTED
@ TEMPSUMMON_TIMED_DESPAWN
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
@ LOOT_MODE_HARD_MODE_3
@ LOOT_MODE_HARD_MODE_1
@ LOOT_MODE_HARD_MODE_2
@ UNIT_FLAG_NON_ATTACKABLE
@ SPELL_TWILIGHT_REVENGE
@ SPELL_POWER_OF_VESPERON
@ SAY_SARTHARION_BERSERK
@ SPELL_POWER_OF_SHADRON
@ SPELL_CLEAVE
@ NPC_FLAME_TSUNAMI
@ SAY_SARTHARION_SLAY
@ POINT_ID_LAND
@ SPELL_LAVA_STRIKE
@ POINT_ID_INIT
@ SAY_SARTHARION_AGGRO
@ SAY_SARTHARION_CALL_TENEBRON
@ SAY_SARTHARION_DEATH
@ SPELL_FLAME_BREATH
@ WHISPER_LAVA_CHURN
@ SAY_SARTHARION_BREATH
@ SPELL_POWER_OF_TENEBRON
@ NPC_ACOLYTE_OF_VESPERON
@ SAY_SARTHARION_CALL_VESPERON
@ SPELL_WILL_OF_SARTHARION
@ SPELL_TAIL_LASH
@ SAY_SARTHARION_CALL_SHADRON
@ SAY_SARTHARION_SPECIAL
@ NPC_ACOLYTE_OF_SHADRON
@ SPELL_PYROBUFFET_RANGE
@ SPELL_PYROBUFFET
@ NPC_FIRE_CYCLONE
@ SPELL_BERSERK
Position const FlameLeft1Direction
@ DATA_CAN_LOOT
Position const FlameRight1Direction
Position const FlameRight1Spawn
Position const FlameLeft1Spawn
void AddSC_boss_sartharion()
Position const VesperonPositions[]
Position const FlameRight3Spawn
Position const TenebronPositions[]
SartharionEvents
@ EVENT_CLEAVE_ATTACK
@ EVENT_CALL_VESPERON
@ EVENT_FLAME_BREATH
@ EVENT_TAIL_SWEEP
@ EVENT_HARD_ENRAGE
@ EVENT_LAVA_STRIKE
@ EVENT_CALL_TENEBRON
@ EVENT_CALL_SHADRON
@ EVENT_FLAME_TSUNAMI
Position const FlameLeft2Spawn
Position const ShadronPositions[]
Position const FlameRight2Spawn
Position const FlameRight3Direction
Position const FlameRight2Direction
Position const FlameLeft2Direction
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
EventMap events
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
void ResetLootMode()
Definition Creature.h:227
void AddLootMode(uint16 lootMode)
Definition Creature.h:225
bool HasLootMode(uint16 lootMode)
Definition Creature.h:223
void Update(uint32 time)
Definition EventMap.h:67
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
virtual bool SetBossState(uint32 id, EncounterState state)
virtual ObjectGuid GetGuidData(uint32 type) const override
EncounterState GetBossState(uint32 id) const
TypeID GetTypeId() const
Definition Object.h:93
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
#define RegisterObsidianSanctumCreatureAI(ai_name)
@ DATA_VESPERON
@ DATA_TENEBRON
@ DATA_SARTHARION
@ DATA_PORTAL_OPEN
@ DATA_SHADRON
@ TWILIGHT_ACHIEVEMENTS
@ NPC_VESPERON
@ NPC_SHADRON
@ NPC_TENEBRON
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:192
bool HealthAbovePct(uint32 pct) const
bool HealthBelowPct(uint32 pct) const
void UpdateAI(uint32 diff) override
void JustDied(Unit *) override
void KilledUnit(Unit *who) override
void CallDragon(uint32 dataId)
void CastLavaStrikeOnTarget(Unit *target)
void JustReachedHome() override
boss_sartharion(Creature *creature)
uint32 GetData(uint32 type) const override
void Reset() override
void JustEngagedWith(Unit *who) override