aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp303
-rw-r--r--src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h17
2 files changed, 270 insertions, 50 deletions
diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp
index 5b00f2067ce..d8afa36fc4f 100644
--- a/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp
+++ b/src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp
@@ -26,14 +26,20 @@
#define SPELL_PETRIFY_BREATH RAID_MODE(62030,63980)
#define SPELL_STONE_GRIP RAID_MODE(62166,63981)
+#define SPELL_STONE_GRIP_CANCEL 65594
#define SPELL_ARM_SWEEP RAID_MODE(63766,63983)
+#define SPELL_ARM_VISUAL 64753
+
+#define SPELL_BERSERK 47008 // guess
enum Events
{
EVENT_NONE = 0,
+ EVENT_MELEE_CHECK,
EVENT_SMASH,
- EVENT_GRIP,
- EVENT_SWEEP,
+ EVENT_STONE_SHOUT,
+ EVENT_RESPAWN_ARM,
+ EVENT_ENRAGE,
};
enum Yells
@@ -54,6 +60,22 @@ enum
ACHIEV_DISARMED_START_EVENT = 21687,
};
+void EncounterInCombat(Creature* me, InstanceScript* pInstance)
+{
+ Creature* c;
+ c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0);
+ if (c && c != me && c->isAlive())
+ c->SetInCombatWithZone();
+
+ c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_RIGHT_ARM) : 0);
+ if (c && c != me && c->isAlive())
+ c->SetInCombatWithZone();
+
+ c = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_LEFT_ARM) : 0);
+ if (c && c != me && c->isAlive())
+ c->SetInCombatWithZone();
+}
+
class boss_kologarn : public CreatureScript
{
public:
@@ -67,19 +89,31 @@ public:
struct boss_kologarnAI : public BossAI
{
boss_kologarnAI(Creature *pCreature) : BossAI(pCreature, TYPE_KOLOGARN), vehicle(pCreature->GetVehicleKit()),
- left(false), right(false)
+ uiArmCount(0)
{
- assert(vehicle);
+ ASSERT(vehicle);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); // i think this is a hack, but there is no other way to disable his rotation
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ SetCombatMovement(false);
+ Reset();
}
Vehicle *vehicle;
- bool left, right;
+ uint8 uiArmCount;
+
+ void Reset()
+ {
+ _Reset();
+ }
- void AttackStart(Unit *who)
+ void EnterCombat(Unit * /*who*/)
{
- me->Attack(who, true);
+ DoScriptText(SAY_AGGRO, me);
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_MELEE_CHECK, 6000);
+ events.ScheduleEvent(EVENT_SMASH, 5000);
+ events.ScheduleEvent(EVENT_ENRAGE, 600000);
+ EncounterInCombat(me, instance);
}
void JustDied(Unit * /*victim*/)
@@ -93,35 +127,30 @@ public:
DoScriptText(RAND(SAY_SLAY_2,SAY_SLAY_2), me);
}
- void PassengerBoarded(Unit *who, int8 /*seatId*/, bool apply)
+ void PassengerBoarded(Unit *who, int8 seatId, bool apply)
{
if (who->GetTypeId() == TYPEID_UNIT)
{
- if (who->GetEntry() == 32933)
- left = apply;
- else if (who->GetEntry() == 32934)
- right = apply;
-
- if (!apply && instance)
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT);
+ if (apply)
+ {
+ ++uiArmCount;
+ events.CancelEvent(EVENT_STONE_SHOUT);
+ }
+ else
+ {
+ if (--uiArmCount == 0)
+ events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
- who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
- CAST_CRE(who)->SetReactState(REACT_PASSIVE);
+ events.ScheduleEvent(EVENT_RESPAWN_ARM, 40000);
+ if (instance)
+ instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_DISARMED_START_EVENT);
+ }
}
}
- void EnterCombat(Unit * /*who*/)
- {
- DoScriptText(SAY_AGGRO, me);
- _EnterCombat();
- events.ScheduleEvent(EVENT_SMASH, 5000);
- events.ScheduleEvent(EVENT_SWEEP, 10000);
- events.ScheduleEvent(EVENT_GRIP, 15000);
- }
-
void UpdateAI(const uint32 diff)
{
- if (!UpdateVictim())
+ if (!me->getVictim() && instance->GetBossState(TYPE_KOLOGARN) == NOT_STARTED)
return;
events.Update(diff);
@@ -129,41 +158,225 @@ public:
if (me->HasUnitState(UNIT_STAT_CASTING))
return;
- // TODO: because we are using hack, he is stunned and cannot cast, so we use triggered for every spell
- switch(events.GetEvent())
+ switch (events.GetEvent())
{
- case EVENT_NONE:
+ case EVENT_MELEE_CHECK:
+ if (!me->IsWithinMeleeRange(me->getVictim()))
+ DoCast(SPELL_PETRIFY_BREATH);
+ events.RepeatEvent(1000);
break;
case EVENT_SMASH:
- if (left && right)
- DoCastVictim(SPELL_TWO_ARM_SMASH, true);
- else if (left || right)
- DoCastVictim(SPELL_ONE_ARM_SMASH, true);
+ if (uiArmCount == 2)
+ DoCastVictim(SPELL_TWO_ARM_SMASH);
+ else if (uiArmCount == 1)
+ DoCastVictim(SPELL_ONE_ARM_SMASH);
events.RepeatEvent(15000);
break;
- case EVENT_SWEEP:
- if (left)
- DoCastAOE(SPELL_ARM_SWEEP, true);
- events.RepeatEvent(15000);
+ case EVENT_STONE_SHOUT:
+ DoCast(SPELL_STONE_SHOUT);
+ events.RepeatEvent(2000);
break;
- case EVENT_GRIP:
- if (right)
- DoCastAOE(SPELL_STONE_GRIP, true);
- events.RepeatEvent(15000);
+ case EVENT_ENRAGE:
+ DoCast(SPELL_BERSERK);
+ DoScriptText(SAY_BERSERK, me);
break;
- default:
- events.PopEvent();
+ case EVENT_RESPAWN_ARM:
+ {
+ Creature* curArm = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_RIGHT_ARM) : 0);
+ if (!(curArm && curArm->isAlive()))
+ curArm = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_LEFT_ARM) : 0);
+ if (!(curArm && curArm->isAlive()))
+ break;
+
+ curArm->Respawn();
+ curArm->SetInCombatWithZone();
+ curArm->EnterVehicle(me);
break;
+ }
}
DoMeleeAttackIfReady();
}
};
+};
+
+class npc_right_arm : public CreatureScript
+{
+public:
+ npc_right_arm() : CreatureScript("npc_right_arm") { }
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new npc_right_armAI(pCreature);
+ }
+
+ struct npc_right_armAI : public ScriptedAI
+ {
+ npc_right_armAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ pInstance = me->GetInstanceScript();
+ SetCombatMovement(false);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ Reset();
+ }
+
+ uint32 uiStoneGripTimer;
+ uint64 uiGrippedTargets[3];
+ uint32 uiPermittedDamage;
+ InstanceScript * pInstance;
+
+ void EnterCombat(Unit* who)
+ {
+ EncounterInCombat(me, pInstance);
+ uiStoneGripTimer = 30000;
+ }
+
+ void Reset()
+ {
+ memset(&uiGrippedTargets, 0, sizeof(uiGrippedTargets));
+ uiPermittedDamage = RAID_MODE(100000, 480000);
+ uiStoneGripTimer = 0;
+ DoCast(SPELL_ARM_VISUAL);
+ }
+
+ void DamageTaken(Unit* who, uint32& damage)
+ {
+ if (uiGrippedTargets[0] == 0)
+ return;
+
+ if (damage > uiPermittedDamage)
+ uiPermittedDamage = 0;
+ else
+ uiPermittedDamage -= damage;
+
+ if (!uiPermittedDamage)
+ ReleaseGrabbedPlayers();
+ }
+
+ void JustDied(Unit* /*who*/)
+ {
+ ReleaseGrabbedPlayers();
+
+ if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
+ {
+ if (Kologarn->isAlive())
+ {
+ Kologarn->CastSpell(Kologarn, SPELL_ARM_DEAD_DAMAGE, true);
+ DoScriptText(SAY_RIGHT_ARM_GONE, Kologarn);
+ }
+ }
+ }
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (uiStoneGripTimer <= diff)
+ {
+ GrabPlayers();
+ if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
+ DoScriptText(SAY_GRAB_PLAYER, Kologarn);
+
+ uiStoneGripTimer = urand(30000, 35000);
+ uiPermittedDamage = RAID_MODE(100000, 480000);
+ }
+ else
+ uiStoneGripTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void ReleaseGrabbedPlayers()
+ {
+ for (uint8 i = 0; i < RAID_MODE(1, 3); ++i)
+ if (Unit* grabbed = Unit::GetUnit(*me, uiGrippedTargets[i]))
+ me->CastSpell(grabbed, SPELL_STONE_GRIP_CANCEL, false);
+ }
+
+ void GrabPlayers()
+ {
+ for (uint8 i = 0; i < RAID_MODE(1, 3); ++i)
+ {
+ if (Unit* grabbed = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ {
+ DoCast(grabbed, SPELL_STONE_GRIP);
+ uiGrippedTargets[i] = grabbed->GetGUID();
+ }
+ }
+ }
+ };
};
+class npc_left_arm : public CreatureScript
+{
+public:
+ npc_left_arm() : CreatureScript("npc_left_arm") { }
+
+ CreatureAI* GetAI(Creature* pCreature) const
+ {
+ return new npc_left_armAI(pCreature);
+ }
+
+ struct npc_left_armAI : public ScriptedAI
+ {
+ npc_left_armAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ pInstance = me->GetInstanceScript();
+ SetCombatMovement(false);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ Reset();
+ }
+
+ uint32 uiSweepTimer;
+ InstanceScript * pInstance;
+
+ void EnterCombat(Unit* who)
+ {
+ EncounterInCombat(me, pInstance);
+ uiSweepTimer = 15000;
+ }
+
+ void Reset()
+ {
+ DoCast(SPELL_ARM_VISUAL);
+ EncounterInCombat(me, pInstance);
+ uiSweepTimer = 0;
+ }
+
+ void JustDied(Unit* /*who*/)
+ {
+ if (Creature* Kologarn = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(TYPE_KOLOGARN) : 0))
+ {
+ if (Kologarn->isAlive())
+ {
+ Kologarn->CastSpell(Kologarn, SPELL_ARM_DEAD_DAMAGE, true);
+ DoScriptText(SAY_LEFT_ARM_GONE, Kologarn);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (uiSweepTimer <= diff)
+ {
+ DoCast(SPELL_ARM_SWEEP);
+ uiSweepTimer = urand(15000, 25000);
+ }
+ else
+ uiSweepTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ };
+};
void AddSC_boss_kologarn()
{
new boss_kologarn();
+ new npc_right_arm();
+ new npc_left_arm();
}
diff --git a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h
index 714ca8ec7dc..3fafe76eea3 100644
--- a/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h
@@ -38,13 +38,17 @@ enum eTypes
TYPE_ALGALON = 13,
TYPE_COLOSSUS = 14,
- DATA_STEELBREAKER = 20,
- DATA_MOLGEIM = 21,
- DATA_BRUNDIR = 22,
-
- DATA_EXP_COMMANDER = 25,
+ DATA_STEELBREAKER,
+ DATA_MOLGEIM,
+ DATA_BRUNDIR,
+ DATA_EXP_COMMANDER,
+ DATA_RIGHT_ARM,
+ DATA_LEFT_ARM,
+};
+enum eBossNPCs
+{
NPC_LEVIATHAN = 33113,
NPC_IGNIS = 33118,
NPC_RAZORSCALE = 33186,
@@ -62,7 +66,10 @@ enum eTypes
NPC_VEZAX = 33271,
NPC_YOGGSARON = 33288,
NPC_ALGALON = 32871,
+};
+enum eTowerEvents
+{
EVENT_TOWER_OF_STORM_DESTROYED = 21031,
EVENT_TOWER_OF_FROST_DESTROYED = 21032,
EVENT_TOWER_OF_FLAMES_DESTROYED = 21033,