diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/scripts/Northrend/Ulduar/ulduar/boss_kologarn.cpp | 303 | ||||
| -rw-r--r-- | src/server/scripts/Northrend/Ulduar/ulduar/ulduar.h | 17 |
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, |
