TrinityCore
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
113{
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
162 void JustEngagedWith(Unit* who) override
163 {
167
168 FetchDragons();
169
178 }
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 tenebron->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
224 tenebron->GetMotionMaster()->MoveTargetedHome();
225 }
226 else
227 {
229 {
230 tenebron->Respawn();
231 tenebron->GetMotionMaster()->MoveTargetedHome();
232 tenebron->AI()->SetData(DATA_CAN_LOOT, 0);
233 }
234 }
235 }
236
238 {
239 shadron->SetHomePosition(3363.06f, 525.28f, 98.362f, 4.76475f);
240 if (shadron->IsAlive())
241 {
242 shadron->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
243 shadron->GetMotionMaster()->MoveTargetedHome();
244 }
245 else
246 {
248 {
249 shadron->Respawn();
250 shadron->GetMotionMaster()->MoveTargetedHome();
251 shadron->AI()->SetData(DATA_CAN_LOOT, 0);
252 }
253 }
254 }
255
257 {
258 vesperon->SetHomePosition(3145.68f, 520.71f, 89.7f, 4.64258f);
259 if (vesperon->IsAlive())
260 {
261 vesperon->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
262 vesperon->GetMotionMaster()->MoveTargetedHome();
263 }
264 else
265 {
267 {
268 vesperon->Respawn();
269 vesperon->GetMotionMaster()->MoveTargetedHome();
270 vesperon->AI()->SetData(DATA_CAN_LOOT, 0);
271 }
272 }
273 }
274 }
275
277 {
278 me->ResetLootMode();
279 drakeCount = 0;
280
281 //if at least one of the dragons are alive and are being called
282 bool _canUseWill = false;
283
285 {
286 if (fetchTene->IsAlive() && !fetchTene->GetVictim())
287 {
288 _canUseWill = true;
289 if (!fetchTene->IsInCombat())
290 {
293 ++drakeCount;
294 }
295 fetchTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, TenebronPositions[0]);
296
297 fetchTene->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
298 }
299 }
300
302 {
303 if (fetchShad->IsAlive() && !fetchShad->GetVictim())
304 {
305 _canUseWill = true;
306 if (!fetchShad->IsInCombat())
307 {
310 ++drakeCount;
311 }
312 fetchShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, ShadronPositions[0]);
313
314 fetchShad->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
315 }
316 }
317
319 {
320 if (fetchVesp->IsAlive() && !fetchVesp->GetVictim())
321 {
322 _canUseWill = true;
323 if (!fetchVesp->IsInCombat())
324 {
327 ++drakeCount;
328 }
329 fetchVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, VesperonPositions[0]);
330
331 fetchVesp->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
332 }
333 }
334
335 if (_canUseWill)
337 }
338
339 void CallDragon(uint32 dataId)
340 {
342 {
343 if (temp->IsAlive() && !temp->GetVictim())
344 {
345 temp->SetWalk(false);
346
347 temp->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
348
349 uint8 textId = 0;
350
351 switch (temp->GetEntry())
352 {
353 case NPC_TENEBRON:
355 temp->AddAura(SPELL_POWER_OF_TENEBRON, temp);
356 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, TenebronPositions[1]);
357 break;
358 case NPC_SHADRON:
360 temp->AddAura(SPELL_POWER_OF_SHADRON, temp);
361 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, ShadronPositions[1]);
362 break;
363 case NPC_VESPERON:
365 temp->AddAura(SPELL_POWER_OF_VESPERON, temp);
366 temp->GetMotionMaster()->MovePoint(POINT_ID_LAND, VesperonPositions[1]);
367 break;
368 }
369
370 Talk(textId);
371 }
372 }
373 }
374
375 uint32 GetData(uint32 type) const override
376 {
377 if (type == TWILIGHT_ACHIEVEMENTS)
378 return drakeCount;
379
380 return 0;
381 }
382
383 // Selects a random Fire Cyclone and makes it cast Lava Strike.
384 // FIXME: Frequency of the casts reduced to compensate 100% chance of spawning a Lava Blaze add
386 {
387 std::list<Creature*> fireCyclonesList;
390 Cell::VisitAllObjects(me, searcher, 200.0f);
391
392 if (fireCyclonesList.empty())
393 return;
394
395 Trinity::Containers::SelectRandomContainerElement(fireCyclonesList)->CastSpell(target, SPELL_LAVA_STRIKE, true);
396 }
397
398 void UpdateAI(uint32 diff) override
399 {
400 if (!UpdateVictim())
401 return;
402
403 events.Update(diff);
404
405 while (uint32 eventId = events.ExecuteEvent())
406 {
407 switch (eventId)
408 {
410 if (!_isHardEnraged)
411 {
412 DoCast(me, SPELL_PYROBUFFET, true);
413 _isHardEnraged = true;
414 }
415 break;
418 switch (urand(0, 1))
419 {
420 case 0:
421 {
423 right1->GetMotionMaster()->MovePoint(0, FlameRight1Direction);
425 right2->GetMotionMaster()->MovePoint(0, FlameRight2Direction);
427 right3->GetMotionMaster()->MovePoint(0, FlameRight3Direction);
428 break;
429 }
430 case 1:
431 {
433 left1->GetMotionMaster()->MovePoint(0, FlameLeft1Direction);
435 left2->GetMotionMaster()->MovePoint(0, FlameLeft2Direction);
436 break;
437 }
438 }
440 break;
445 break;
446 case EVENT_TAIL_SWEEP:
449 break;
453 break;
456 {
458 if (urand(0, 5) == 0)
460 }
461 if (_isSoftEnraged)
463 else
465 break;
468 break;
471 break;
474 break;
475 default:
476 break;
477 }
478 }
479
480 // At 35% spell will target dragons, if they are still alive.
481 if (!_isBerserk && !HealthAbovePct(35))
482 {
484 {
487 _isBerserk = true;
488 }
489 }
490
491 // Soft Enrage used while determining Lava Strike cooldown.
492 if (!_isSoftEnraged && HealthBelowPct(10))
493 {
494 _isSoftEnraged = true;
495 }
496 }
497
498private:
503};
504
506{
508}
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
@ DONE
@ NOT_STARTED
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
@ LOOT_MODE_HARD_MODE_3
Definition: SharedDefines.h:80
@ LOOT_MODE_HARD_MODE_1
Definition: SharedDefines.h:78
@ LOOT_MODE_HARD_MODE_2
Definition: SharedDefines.h:79
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:145
Enums
Definition: boss_aeonus.cpp:31
@ 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 _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:371
bool HasLootMode(uint16 lootMode) const
Definition: Creature.h:296
void ResetLootMode()
Definition: Creature.h:300
void AddLootMode(uint16 lootMode)
Definition: Creature.h:298
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
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:173
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
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:2025
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:109
#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:203
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