Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_kologarn.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 "ulduar.h"
11#include "Vehicle.h"
12#include "Player.h"
13
14/* ScriptData
15SDName: boss_kologarn
16SD%Complete: 90
17SDComment: @todo Achievements
18SDCategory: Ulduar
19EndScriptData */
20
49
55
70
83
85{
86 public:
87 boss_kologarn() : CreatureScript("boss_kologarn") { }
88
89 struct boss_kologarnAI : public BossAI
90 {
91 boss_kologarnAI(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), vehicle(creature->GetVehicleKit()),
92 left(false), right(false)
93 {
95
98
100 SetCombatMovement(false);
101 Reset();
102 }
103
105 bool left, right;
107
108 void EnterCombat(Unit* /*who*/) OVERRIDE
109 {
111
112 events.ScheduleEvent(EVENT_MELEE_CHECK, 6000);
113 events.ScheduleEvent(EVENT_SMASH, 5000);
114 events.ScheduleEvent(EVENT_SWEEP, 19000);
115 events.ScheduleEvent(EVENT_STONE_GRIP, 25000);
116 events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 21000);
117 events.ScheduleEvent(EVENT_ENRAGE, 600000);
118
119 for (uint8 i = 0; i < 2; ++i)
120 if (Unit* arm = vehicle->GetPassenger(i))
121 arm->ToCreature()->SetInCombatWithZone();
122
123 _EnterCombat();
124 }
125
127 {
128 _Reset();
130 eyebeamTarget = 0;
131 }
132
133 void JustDied(Unit* /*killer*/) OVERRIDE
134 {
137 me->GetMotionMaster()->MoveTargetedHome();
139 me->SetCorpseDelay(604800); // Prevent corpse from despawning.
140 _JustDied();
141 }
142
144 {
145 if (who->GetTypeId() == TypeID::TYPEID_PLAYER)
146 Talk(SAY_SLAY);
147 }
148
149 void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) OVERRIDE
150 {
151 bool isEncounterInProgress = instance->GetBossState(BOSS_KOLOGARN) == IN_PROGRESS;
152 if (who->GetEntry() == NPC_LEFT_ARM)
153 {
154 left = apply;
155 if (!apply && isEncounterInProgress)
156 {
157 who->ToCreature()->DespawnOrUnsummon();
159 events.ScheduleEvent(EVENT_RESPAWN_LEFT_ARM, 40000);
160 }
161 }
162
163 else if (who->GetEntry() == NPC_RIGHT_ARM)
164 {
165 right = apply;
166 if (!apply && isEncounterInProgress)
167 {
168 who->ToCreature()->DespawnOrUnsummon();
170 events.ScheduleEvent(EVENT_RESPAWN_RIGHT_ARM, 40000);
171 }
172 }
173
174 if (!isEncounterInProgress)
175 return;
176
177 if (!apply)
178 {
179 who->CastSpell(me, SPELL_ARM_DEAD_DAMAGE, true);
180
181 if (Creature* rubbleStalker = who->FindNearestCreature(NPC_RUBBLE_STALKER, 70.0f))
182 {
183 rubbleStalker->CastSpell(rubbleStalker, SPELL_FALLING_RUBBLE, true);
184 rubbleStalker->CastSpell(rubbleStalker, SPELL_SUMMON_RUBBLE, true);
185 }
186
187 if (!right && !left)
188 events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
189
191 }
192 else
193 {
194 events.CancelEvent(EVENT_STONE_SHOUT);
195 who->ToCreature()->SetInCombatWithZone();
196 }
197 }
198
200 {
201 switch (summon->GetEntry())
202 {
204 summon->CastSpell(me, SPELL_FOCUSED_EYEBEAM_VISUAL_LEFT, true);
205 break;
207 summon->CastSpell(me, SPELL_FOCUSED_EYEBEAM_VISUAL_RIGHT, true);
208 break;
209 case NPC_RUBBLE:
210 summons.Summon(summon);
211 // absence of break intended
212 default:
213 return;
214 }
215
216 summon->CastSpell(summon, SPELL_FOCUSED_EYEBEAM_PERIODIC, true);
217 summon->CastSpell(summon, SPELL_FOCUSED_EYEBEAM_VISUAL, true);
218 summon->SetReactState(REACT_PASSIVE);
219 // One of the above spells is a channeled spell, we need to clear this unit state for MoveChase to work
220 summon->ClearUnitState(UNIT_STATE_CASTING);
221
222 // Victim gets 67351
223 if (eyebeamTarget)
224 {
225 if (Unit* target = Unit::GetUnit(*summon, eyebeamTarget))
226 {
227 summon->Attack(target, false);
228 summon->GetMotionMaster()->MoveChase(target);
229 }
230 }
231 }
232
234 {
235 if (!UpdateVictim())
236 return;
237
238 events.Update(diff);
239
240 if (me->HasUnitState(UNIT_STATE_CASTING))
241 return;
242
243 while (uint32 eventId = events.ExecuteEvent())
244 {
245 switch (eventId)
246 {
248 if (!me->IsWithinMeleeRange(me->GetVictim()))
250 events.ScheduleEvent(EVENT_MELEE_CHECK, 1 * IN_MILLISECONDS);
251 break;
252 case EVENT_SWEEP:
253 if (left)
254 DoCast(me->FindNearestCreature(NPC_ARM_SWEEP_STALKER, 500.0f, true), SPELL_ARM_SWEEP, true);
255 events.ScheduleEvent(EVENT_SWEEP, 25 * IN_MILLISECONDS);
256 break;
257 case EVENT_SMASH:
258 if (left && right)
260 else if (left || right)
262 events.ScheduleEvent(EVENT_SMASH, 15 * IN_MILLISECONDS);
263 break;
266 events.ScheduleEvent(EVENT_STONE_SHOUT, 2 * IN_MILLISECONDS);
267 break;
268 case EVENT_ENRAGE:
271 break;
274 {
275 if (vehicle)
276 {
277 int8 seat = eventId == EVENT_RESPAWN_LEFT_ARM ? 0 : 1;
279 vehicle->InstallAccessory(entry, seat, true, TempSummonType::TEMPSUMMON_MANUAL_DESPAWN, 0);
280 }
281 break;
282 }
283 case EVENT_STONE_GRIP:
284 {
285 if (right)
286 {
290 }
291 events.ScheduleEvent(EVENT_STONE_GRIP, 25 * IN_MILLISECONDS);
292 break;
293 }
295 if (Unit* eyebeamTargetUnit = SelectTarget(SELECT_TARGET_FARTHEST, 0, 0, true))
296 {
297 eyebeamTarget = eyebeamTargetUnit->GetGUID();
299 }
300 events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, std::rand() % (35 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS));
301 break;
302 }
303 }
304
306 }
307 };
308
310 {
311 return GetUlduarAI<boss_kologarnAI>(creature);
312 }
313};
314
316{
317 public:
318 spell_ulduar_rubble_summon() : SpellScriptLoader("spell_ulduar_rubble_summon") { }
319
321 {
323
324 void HandleScript(SpellEffIndex /*effIndex*/)
325 {
326 Unit* caster = GetCaster();
327 if (!caster)
328 return;
329
330 uint64 originalCaster = caster->GetInstanceScript() ? caster->GetInstanceScript()->GetData64(BOSS_KOLOGARN) : 0;
331 uint32 spellId = GetEffectValue();
332 for (uint8 i = 0; i < 5; ++i)
333 caster->CastSpell(caster, spellId, true, NULL, NULL, originalCaster);
334 }
335
340 };
341
346};
347
348// predicate function to select non main tank target
350{
351 public:
352 StoneGripTargetSelector(Creature* me, Unit const* victim) : _me(me), _victim(victim) { }
353
355 {
356 if (target == _victim && _me->getThreatManager().getThreatList().size() > 1)
357 return true;
358
359 if (target->GetTypeId() != TypeID::TYPEID_PLAYER)
360 return true;
361
362 return false;
363 }
364
366 Unit const* _victim;
367};
368
370{
371 public:
372 spell_ulduar_stone_grip_cast_target() : SpellScriptLoader("spell_ulduar_stone_grip_cast_target") { }
373
375 {
377
379 {
380 if (GetCaster()->GetTypeId() != TypeID::TYPEID_UNIT)
381 return false;
382 return true;
383 }
384
385 void FilterTargetsInitial(std::list<WorldObject*>& unitList)
386 {
387 // Remove "main tank" and non-player targets
388 unitList.remove_if(StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
389 // Maximum affected targets per difficulty mode
390 uint32 maxTargets = 1;
391 if (GetSpellInfo()->Id == 63981)
392 maxTargets = 3;
393
394 // Return a random amount of targets based on maxTargets
395 while (maxTargets < unitList.size())
396 {
397 std::list<WorldObject*>::iterator itr = unitList.begin();
398 advance(itr, std::rand() % (unitList.size() - 1));
399 unitList.erase(itr);
400 }
401
402 // For subsequent effects
403 _unitList = unitList;
404 }
405
406 void FillTargetsSubsequential(std::list<WorldObject*>& unitList)
407 {
408 unitList = _unitList;
409 }
410
417
418 private:
419 // Shared between effects
420 std::list<WorldObject*> _unitList;
421 };
422
427};
428
430{
431 public:
432 spell_ulduar_cancel_stone_grip() : SpellScriptLoader("spell_ulduar_cancel_stone_grip") { }
433
435 {
437
438 void HandleScript(SpellEffIndex /*effIndex*/)
439 {
440 Unit* target = GetHitUnit();
441 if (!target || !target->GetVehicle())
442 return;
443
444 switch (target->GetMap()->GetDifficulty())
445 {
447 target->RemoveAura(GetSpellInfo()->Effects[EFFECT_0].CalcValue());
448 break;
450 target->RemoveAura(GetSpellInfo()->Effects[EFFECT_1].CalcValue());
451 break;
452 default:
453 break;
454 }
455 }
456
461 };
462
467};
468
470{
471 public:
472 spell_ulduar_squeezed_lifeless() : SpellScriptLoader("spell_ulduar_squeezed_lifeless") { }
473
475 {
477
479 {
480 if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle())
481 return;
482
485 Position pos;
486 pos.m_positionX = 1756.25f + float(std::rand() % 3 + -3);
487 pos.m_positionY = -8.3f + float(std::rand() % 3 + -3);
488 pos.m_positionZ = 448.8f;
489 pos.SetOrientation(M_PI);
491 GetHitPlayer()->ExitVehicle(&pos);
493 }
494
499 };
500
505};
506
508{
509 public:
510 spell_ulduar_stone_grip_absorb() : SpellScriptLoader("spell_ulduar_stone_grip_absorb") { }
511
513 {
515
518 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
519 {
520 if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
521 return;
522
523 if (!GetOwner()->ToCreature())
524 return;
525
526 uint32 rubbleStalkerEntry = (GetOwner()->GetMap()->GetDifficulty() == DIFFICULTY_NORMAL ? 33809 : 33942);
527 Creature* rubbleStalker = GetOwner()->FindNearestCreature(rubbleStalkerEntry, 200.0f, true);
528 if (rubbleStalker)
529 rubbleStalker->CastSpell(rubbleStalker, SPELL_STONE_GRIP_CANCEL, true);
530 }
531
536 };
537
542};
543
545{
546 public:
547 spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { }
548
550 {
552
553 void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
554 {
555 if (Player* owner = GetOwner()->ToPlayer())
556 owner->RemoveAurasDueToSpell(aurEff->GetAmount());
557 }
558
559 void OnRemoveVehicle(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
560 {
562 Unit* caster = GetCaster();
563 if (!caster)
564 return;
565
566 Position exitPosition;
567 exitPosition.m_positionX = 1750.0f;
568 exitPosition.m_positionY = -7.5f + frand(-3.0f, 3.0f);
569 exitPosition.m_positionZ = 457.9322f;
570
571 // Remove pending passengers before exiting vehicle - might cause an Uninstall
573 caster->_ExitVehicle(&exitPosition);
574 caster->RemoveAurasDueToSpell(GetId());
575
576 // Temporarily relocate player to vehicle exit dest serverside to send proper fall movement
577 // beats me why blizzard sends these 2 spline packets one after another instantly
578 Position oldPos;
579 caster->GetPosition(&oldPos);
580 caster->Relocate(exitPosition);
581 caster->GetMotionMaster()->MoveFall();
582 caster->Relocate(oldPos);
583 }
584
590 };
591
596};
597
623
651
@ IN_MILLISECONDS
Definition Common.h:125
#define M_PI
Definition Common.h:192
@ ACHIEVEMENT_TIMED_TYPE_EVENT
Definition DBCEnums.h:158
@ DIFFICULTY_25MAN_NORMAL
Definition DBCEnums.h:335
@ DIFFICULTY_NORMAL
Definition DBCEnums.h:332
@ DIFFICULTY_10MAN_NORMAL
Definition DBCEnums.h:334
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
@ IN_PROGRESS
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ TEMPSUMMON_MANUAL_DESPAWN
Definition Object.h:75
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_INSTAKILL
@ SPELL_EFFECT_FORCE_CAST
@ TARGET_UNIT_SRC_AREA_ENEMY
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_SCHOOL_ABSORB
@ SPELL_AURA_MOD_STUN
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectRemoveFn(F, I, N, M)
#define SF_UNARY_FUNCTION
@ AURA_REMOVE_BY_ENEMY_SPELL
Definition Unit.h:409
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ REACT_PASSIVE
Definition Unit.h:1156
@ UNIT_FLAG_DISABLE_MOVE
Definition Unit.h:627
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ SELECT_TARGET_FARTHEST
Definition UnitAI.h:27
@ UNIT_FIELD_FLAGS
float frand(float min, float max)
Definition Util.cpp:39
@ EVENT_ENRAGE
@ SAY_BERSERK
@ SAY_SLAY
#define SAY_DEATH
#define SAY_AGGRO
@ EVENT_NONE
#define SPELL_BERSERK
@ SAY_DEATH
@ SAY_AGGRO
@ SAY_GRAB_PLAYER
@ SAY_SHOCKWAVE
@ SAY_RIGHT_ARM_GONE
@ SAY_LEFT_ARM_GONE
@ EMOTE_STONE_GRIP
@ SAY_SLAY
@ SAY_BERSERK
@ SPELL_FOCUSED_EYEBEAM_VISUAL
@ SPELL_ARM_SWEEP
@ SPELL_ONE_ARM_SMASH
@ SPELL_PETRIFY_BREATH
@ SPELL_KOLOGARN_UNK_0
@ SPELL_FALLING_RUBBLE
@ SPELL_SUMMON_FOCUSED_EYEBEAM
@ SPELL_ARM_ENTER_VEHICLE
@ SPELL_STONE_GRIP
@ SPELL_STONE_GRIP_CANCEL
@ SPELL_TWO_ARM_SMASH
@ SPELL_ARM_ENTER_VISUAL
@ SPELL_ARM_DEAD_DAMAGE
@ SPELL_STONE_SHOUT
@ SPELL_FOCUSED_EYEBEAM_VISUAL_LEFT
@ SPELL_FOCUSED_EYEBEAM_PERIODIC
@ SPELL_KOLOGARN_REDUCE_PARRY
@ SPELL_BERSERK
@ SPELL_FOCUSED_EYEBEAM_VISUAL_RIGHT
@ SPELL_KOLOGARN_PACIFY
@ SPELL_SUMMON_RUBBLE
@ NPC_ARM_SWEEP_STALKER
@ NPC_RUBBLE_STALKER
void AddSC_boss_kologarn()
@ EVENT_RESPAWN_RIGHT_ARM
@ EVENT_ENRAGE
@ EVENT_INSTALL_ACCESSORIES
@ EVENT_STONE_GRIP
@ EVENT_SMASH
@ EVENT_RESPAWN_LEFT_ARM
@ EVENT_MELEE_CHECK
@ EVENT_FOCUSED_EYEBEAM
@ EVENT_SWEEP
@ EVENT_STONE_SHOUT
int32 GetAmount() const
void PreventDefaultAction()
AuraApplication const * GetTargetApplication() const
HookList< EffectApplyHandler > AfterEffectRemove
WorldObject * GetOwner() const
Unit * GetCaster() const
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectRemove
uint32 GetId() const
InstanceScript *const instance
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void _EnterCombat()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
CreatureScript(const char *name)
DifficultyID GetDifficulty() const
Definition Map.h:363
void MoveFall(uint32 id=0)
TypeID GetTypeId() const
Definition Object.h:131
void UpdateObjectVisibility(bool forced=true) override
Definition Player.cpp:18318
Player * GetHitPlayer()
SpellInfo const * GetSpellInfo()
void PreventHitDefaultEffect(SpellEffIndex effIndex)
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
int32 GetEffectValue()
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
StoneGripTargetSelector(Creature *me, Unit const *victim)
bool operator()(WorldObject *target)
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
Vehicle * GetVehicle() const
Definition Unit.h:2743
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
void _ExitVehicle(Position const *exitPosition=NULL)
Definition Unit.cpp:8325
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
Vehicle * GetVehicleKit() const
Definition Unit.h:2739
void ExitVehicle(Position const *exitPosition=NULL)
Definition Unit.cpp:8306
void RemovePendingEventsForPassenger(Unit *passenger)
Definition Vehicle.cpp:729
Map * GetMap() const
Definition Object.h:740
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
void DestroyForNearbyPlayers()
Definition Object.cpp:3453
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2801
virtual uint64 GetData64(uint32) const
Definition ZoneScript.h:32
CreatureAI * GetAI(Creature *creature) const OVERRIDE
PrepareSpellScript(spell_kologarn_stone_shout_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_ulduar_rubble_summonSpellScript)
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
PrepareAuraScript(spell_ulduar_stone_grip_AuraScript)
void OnRemoveStun(AuraEffect const *aurEff, AuraEffectHandleModes)
void OnRemoveVehicle(AuraEffect const *, AuraEffectHandleModes)
AuraScript * GetAuraScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
float m_positionZ
Definition Object.h:289
float m_positionX
Definition Object.h:287
float m_positionY
Definition Object.h:288
void SetOrientation(float orientation)
Definition Object.h:323
void GetPosition(float &x, float &y) const
Definition Object.h:333
void Relocate(float x, float y)
Definition Object.h:302
void SetCombatMovement(bool allowMovement)
Creature * me
void PassengerBoarded(Unit *who, int8, bool apply) OVERRIDE
== Fields =======================================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void KilledUnit(Unit *who) OVERRIDE
void JustSummoned(Creature *summon) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
boss_kologarnAI(Creature *creature)
void JustDied(Unit *) OVERRIDE
@ BOSS_KOLOGARN
Definition ulduar.h:25
AI * GetUlduarAI(T *obj)
Definition ulduar.h:336
@ NPC_RIGHT_ARM
Definition ulduar.h:59
@ NPC_FOCUSED_EYEBEAM_RIGHT
Definition ulduar.h:57
@ NPC_LEFT_ARM
Definition ulduar.h:58
@ NPC_FOCUSED_EYEBEAM
Definition ulduar.h:56
@ NPC_RUBBLE
Definition ulduar.h:60
@ CRITERIA_DISARMED
Definition ulduar.h:240