diff --git a/sql/updates/world/custom/custom_2018_08_22_04_world.sql b/sql/updates/world/custom/custom_2018_08_22_04_world.sql new file mode 100644 index 00000000000..daf0b933391 --- /dev/null +++ b/sql/updates/world/custom/custom_2018_08_22_04_world.sql @@ -0,0 +1,5 @@ +DELETE FROM `creature` WHERE `guid` IN (304363); +DELETE FROM `creature_addon` WHERE `guid` IN (304363); + +UPDATE `creature_template` SET `unit_flags`= 0x40 | 0x200 WHERE `entry` IN (39788, 48902); +UPDATE `creature_template` SET `speed_run`= 1.71429 WHERE `entry`= 48902; diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index 5f7c2e96fb2..25ede96bbb0 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -125,9 +125,6 @@ enum Points POINT_BRANN_TURN_BACK }; -// Anraphet's intro -Position const AnraphetActivatePos = { -193.656f, 366.689f, 75.91001f, 3.138207f }; - uint32 const AnraphetPathSize = 6; Position const AnraphetPath[AnraphetPathSize] = { @@ -171,348 +168,293 @@ Position const BrannFinalPath[BrannFinalPathSize] = { -35.04861f, 366.6563f, 89.77447f, 0.0f } }; -class boss_anraphet : public CreatureScript +struct boss_anraphet : public BossAI { -public: - boss_anraphet() : CreatureScript("boss_anraphet") { } + boss_anraphet(Creature* creature) : BossAI(creature, DATA_ANRAPHET) { } - struct boss_anraphetAI : public BossAI + void Reset() override { - boss_anraphetAI(Creature* creature) : BossAI(creature, DATA_ANRAPHET) { } - - void Reset() override - { - _Reset(); - - // Vault of Lights not yet done? - //if (instance->GetData(DATA_DEAD_ELEMENTALS) < 4) - if (instance->GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) - { - me->SetHomePosition(AnraphetActivatePos); - me->GetMotionMaster()->MoveTargetedHome(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.SetPhase(PHASE_COMBAT); - } - } - - void JustEngagedWith(Unit* /*who*/) override - { - // Prevents spam during intro (massive trogg kill) - if (events.IsInPhase(PHASE_INTRO)) - return; - - Talk(ANRAPHET_SAY_AGGRO); - _JustEngagedWith(); - - instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); - events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, Seconds(8), 0, PHASE_COMBAT); - events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, Seconds(10), 0, PHASE_COMBAT); - events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, Seconds(35), 0, PHASE_COMBAT); - } - - void EnterEvadeMode(EvadeReason /*why*/) override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - summons.DespawnAll(); - _EnterEvadeMode(); - _DespawnAtEvade(); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - Talk(ANRAPHET_SAY_DEATH); - _JustDied(); - - if (Creature* brann = instance->GetCreature(DATA_BRANN_0)) - brann->AI()->DoAction(ACTION_ANRAPHET_DIED); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(ANRAPHET_SAY_KILL); - } - - void DoAction(int32 action) override - { - if (action != ACTION_ANRAPHET_INTRO) - return; - - // Intro - events.SetPhase(PHASE_INTRO); - events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, Seconds(6), 0, PHASE_INTRO); // Note: 5800 ms - } - - void MovementInform(uint32 type, uint32 point) override - { - if (type != EFFECT_MOTION_TYPE || point != POINT_ANRAPHET_ACTIVATE) - return; - - // Activate point - me->SetHomePosition(AnraphetActivatePos); - events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, Seconds(1), 0, PHASE_INTRO); - } - - void UpdateAI(uint32 diff) override - { - if (!events.IsInPhase(PHASE_INTRO) && (!UpdateVictim() || !CheckInRoom())) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_ANRAPHET_APPEAR: - me->GetMotionMaster()->MoveSmoothPath(POINT_ANRAPHET_ACTIVATE, AnraphetPath, AnraphetPathSize); - break; - case EVENT_ANRAPHET_ACTIVATE: - Talk(ANRAPHET_SAY_INTRO); - events.ScheduleEvent(EVENT_ANRAPHET_DESTRUCTION, Seconds(10), 0, PHASE_INTRO); // Note: 10800 ms - break; - case EVENT_ANRAPHET_DESTRUCTION: - DoCastAOE(SPELL_DESTRUCTION_PROTOCOL); - events.ScheduleEvent(EVENT_ANRAPHET_READY, Seconds(6), 0, PHASE_INTRO); // Note: 6400 ms - break; - case EVENT_ANRAPHET_READY: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.SetPhase(PHASE_COMBAT); - break; - case EVENT_ANRAPHET_NEMESIS_STRIKE: - DoCastVictim(SPELL_NEMESIS_STRIKE); - events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, Seconds(21), 0, PHASE_COMBAT); - break; - case EVENT_ANRAPHET_ALPHA_BEAMS: - DoCastSelf(SPELL_ALPHA_BEAMS); - events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, Seconds(12), 0, PHASE_COMBAT); - events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, Seconds(40), Seconds(45), 0, PHASE_COMBAT); - break; - case EVENT_ANRAPHET_OMEGA_STANCE: - DoCastSelf(SPELL_OMEGA_STANCE); - Talk(ANRAPHET_SAY_OMEGA_STANCE); - events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, Seconds(45), Seconds(50), 0, PHASE_COMBAT); - events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, Seconds(13), 0, PHASE_COMBAT); - break; - case EVENT_ANRAPHET_CRUMBLING_RUIN: - DoCastSelf(SPELL_CRUMBLING_RUIN); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetHallsOfOriginationAI(creature); + _Reset(); } -}; -// 5811 Brann's AreaTrigger -class at_hoo_brann_idle_emote : public AreaTriggerScript -{ -public: - at_hoo_brann_idle_emote() : AreaTriggerScript("at_hoo_brann_idle_emote") { } - - bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + void JustEngagedWith(Unit* /*who*/) override { - if (InstanceScript* instance = player->GetInstanceScript()) - if (Creature* brann = instance->GetCreature(DATA_BRANN_0)) - brann->AI()->DoAction(ACTION_BRANN_IDLE_EMOTE); - return true; + Talk(ANRAPHET_SAY_AGGRO); + _JustEngagedWith(); + instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me); + events.SetPhase(PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, Seconds(8), 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, Seconds(10), 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, Seconds(35), 0, PHASE_COMBAT); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + instance->SetBossState(DATA_ANRAPHET, FAIL); + summons.DespawnAll(); + _EnterEvadeMode(); + me->DespawnOrUnsummon(); + } + + void JustDied(Unit* /*killer*/) override + { + instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); + Talk(ANRAPHET_SAY_DEATH); + _JustDied(); + + if (Creature* brann = instance->GetCreature(DATA_BRANN_0)) + brann->AI()->DoAction(ACTION_ANRAPHET_DIED); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(ANRAPHET_SAY_KILL); + } + + void DoAction(int32 action) override + { + if (action != ACTION_ANRAPHET_INTRO) + return; + + // Intro + events.SetPhase(PHASE_INTRO); + events.ScheduleEvent(EVENT_ANRAPHET_APPEAR, Seconds(6), 0, PHASE_INTRO); + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != EFFECT_MOTION_TYPE || point != POINT_ANRAPHET_ACTIVATE) + return; + + events.ScheduleEvent(EVENT_ANRAPHET_ACTIVATE, Seconds(1), 0, PHASE_INTRO); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ANRAPHET_APPEAR: + me->GetMotionMaster()->MoveSmoothPath(POINT_ANRAPHET_ACTIVATE, AnraphetPath, AnraphetPathSize); + break; + case EVENT_ANRAPHET_ACTIVATE: + Talk(ANRAPHET_SAY_INTRO); + events.ScheduleEvent(EVENT_ANRAPHET_DESTRUCTION, Seconds(10), 0, PHASE_INTRO); + break; + case EVENT_ANRAPHET_DESTRUCTION: + DoCastAOE(SPELL_DESTRUCTION_PROTOCOL); + events.ScheduleEvent(EVENT_ANRAPHET_READY, Seconds(6), 0, PHASE_INTRO); + break; + case EVENT_ANRAPHET_READY: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + break; + case EVENT_ANRAPHET_NEMESIS_STRIKE: + DoCastVictim(SPELL_NEMESIS_STRIKE); + events.ScheduleEvent(EVENT_ANRAPHET_NEMESIS_STRIKE, Seconds(21), 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_ALPHA_BEAMS: + DoCastSelf(SPELL_ALPHA_BEAMS); + events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, Seconds(12), 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_ALPHA_BEAMS, Seconds(40), Seconds(45), 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_OMEGA_STANCE: + DoCastSelf(SPELL_OMEGA_STANCE); + Talk(ANRAPHET_SAY_OMEGA_STANCE); + events.ScheduleEvent(EVENT_ANRAPHET_OMEGA_STANCE, Seconds(45), Seconds(50), 0, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ANRAPHET_CRUMBLING_RUIN, Seconds(13), 0, PHASE_COMBAT); + break; + case EVENT_ANRAPHET_CRUMBLING_RUIN: + DoCastSelf(SPELL_CRUMBLING_RUIN); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); } }; // 39908 Brann Bronzebeard -class npc_brann_bronzebeard_anraphet : public CreatureScript +struct npc_brann_bronzebeard_anraphet : public CreatureAI { -public: - npc_brann_bronzebeard_anraphet() : CreatureScript("npc_brann_bronzebeard_anraphet") { } + npc_brann_bronzebeard_anraphet(Creature* creature) : CreatureAI(creature), _instance(creature->GetInstanceScript()) { } - - struct npc_brann_bronzebeard_anraphetAI : public CreatureAI + bool GossipHello(Player* player) override { - npc_brann_bronzebeard_anraphetAI(Creature* creature) : CreatureAI(creature), _instance(creature->GetInstanceScript()) { } - - bool GossipHello(Player* player) override - { - if (!_instance) - return true; - - // What gossip menu shall we send? - uint32 gossipMenuId = GOSSIP_MENU_NO_TIME_TO_WASTE; - - if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == NOT_STARTED) // gossipMenuId already set, only add gossip option - AddGossipItemFor(player, gossipMenuId, GOSSIP_OPTION_WE_ARE_READY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - else if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) != DONE) - gossipMenuId = GOSSIP_MENU_DESTROY_ELEMENTAL; - else // To-do: There might be another gossip text before and while fighting Anraphet. Check retail. - gossipMenuId = GOSSIP_MENU_OCH_ITS_NOT_EASY; - - SendGossipMenuFor(player, player->GetGossipTextId(gossipMenuId, me), me->GetGUID()); + if (!_instance) return true; - } - void Reset() override + uint32 gossipMenuId = GOSSIP_MENU_NO_TIME_TO_WASTE; + + if (_instance->GetData(DATA_VAULT_OF_LIGHTS) == NOT_STARTED) + AddGossipItemFor(player, gossipMenuId, GOSSIP_OPTION_WE_ARE_READY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + else if (_instance->GetData(DATA_VAULT_OF_LIGHTS) != DONE) + gossipMenuId = GOSSIP_MENU_DESTROY_ELEMENTAL; + else + gossipMenuId = GOSSIP_MENU_OCH_ITS_NOT_EASY; + + SendGossipMenuFor(player, player->GetGossipTextId(gossipMenuId, me), me->GetGUID()); + return true; + } + + void Reset() override + { + canSayIdleEmote = _instance->GetData(DATA_VAULT_OF_LIGHTS) == NOT_STARTED; + + if (_instance->GetBossState(DATA_ANRAPHET) == DONE) + me->SetHomePosition(BrannFinalHomePos); + else if (_instance->GetData(DATA_VAULT_OF_LIGHTS) != NOT_STARTED) + me->SetHomePosition(BrannBossHomePos); + + me->GetMotionMaster()->MoveTargetedHome(); + } + + bool GossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override + { + if (_instance->GetData(DATA_VAULT_OF_LIGHTS) != NOT_STARTED) + return false; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.RescheduleEvent(EVENT_BRANN_START_INTRO, Seconds(1)); + + return true; + } + + void DoAction(int32 action) override + { + switch (action) { - // DATA_VAULT_OF_LIGHTS is not a boss/creature, so we need to initialize it manually. - if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == TO_BE_DECIDED) - _instance->SetBossState(DATA_VAULT_OF_LIGHTS, NOT_STARTED); - - // We are ready for idle emote only if intro not started yet. - canSayIdleEmote = _instance->GetBossState(DATA_VAULT_OF_LIGHTS) == NOT_STARTED; - - // Different home positions after intro is started. - if (_instance->GetBossState(DATA_ANRAPHET) == DONE) - me->SetHomePosition(BrannFinalHomePos); - else if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) != NOT_STARTED) - me->SetHomePosition(BrannBossHomePos); - - me->GetMotionMaster()->MoveTargetedHome(); - } - - bool GossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override - { - if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) != NOT_STARTED) - return false; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); // Removes EVENT_BRANN_IDLE_EMOTE. - events.RescheduleEvent(EVENT_BRANN_START_INTRO, Seconds(1)); - - return true; - } - - void DoAction(int32 action) override - { - switch (action) + case ACTION_BRANN_IDLE_EMOTE: + if (canSayIdleEmote) + { + canSayIdleEmote = false; + Talk(urand(0, 1) ? BRANN_SAY_BLASTED_TITANS : BRANN_SAY_THIS_SYMBOL); + events.ScheduleEvent(EVENT_BRANN_IDLE_EMOTE_COOLDOWN, Seconds(45)); // Cooldown for AreaTrigger + } + break; + case ACTION_ELEMENTAL_DIED: { - case ACTION_BRANN_IDLE_EMOTE: - if (canSayIdleEmote) + + uint32 deadElementals = _instance->GetData(DATA_DEAD_ELEMENTALS); + if (deadElementals < 4) + Talk(BRANN_1_ELEMENTAL_DEAD + deadElementals - 1); + else + _instance->SetData(DATA_VAULT_OF_LIGHTS, DONE); + events.RescheduleEvent(EVENT_BRANN_ACTIVATE_LASERBEAMS, Seconds(9)); + break; + } + case ACTION_ANRAPHET_DIED: + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.ScheduleEvent(EVENT_BRANN_MOVE_OUTRO, Seconds(5)); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BRANN_IDLE_EMOTE_COOLDOWN: + canSayIdleEmote = true; + break; + case EVENT_BRANN_START_INTRO: + Talk(BRANN_SAY_DOOR_INTRO); + events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, Seconds(7)); + break; + case EVENT_BRANN_UNLOCK_DOOR: + Talk(BRANN_SAY_UNLOCK_DOOR); + _instance->SetBossState(DATA_VAULT_OF_LIGHTS, IN_PROGRESS); + events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, Seconds(3)); + break; + case EVENT_BRANN_MOVE_INTRO: + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(POINT_BRANN_SAY_TROGGS, BrannBossHomePos, true); + break; + case EVENT_BRANN_THINK: + Talk(BRANN_SAY_THINK); + events.ScheduleEvent(EVENT_BRANN_LOOK_RIGHT, Seconds(6)); + break; + case EVENT_BRANN_LOOK_RIGHT: + me->SetFacingTo(DegToRad(312.0f)); // Sniff: o = 5.445427f + Talk(BRANN_SAY_MIRRORS); + events.ScheduleEvent(EVENT_BRANN_LOOK_LEFT, Seconds(1)); + break; + case EVENT_BRANN_LOOK_LEFT: + me->SetFacingTo(DegToRad(36.0f)); // Sniff: o = 0.6283185f + events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, Seconds(3)); + break; + case EVENT_BRANN_SAY_ELEMENTALS: + me->SetFacingTo(DegToRad(1.0f)); // Sniff: o = 0.01745329f + Talk(BRANN_SAY_ELEMENTALS); + events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, Seconds(4)); + break; + case EVENT_BRANN_SAY_GET_IT: + Talk(BRANN_SAY_GET_IT); + events.ScheduleEvent(EVENT_BRANN_SET_FLAG_GOSSIP, Seconds(16)); + break; + case EVENT_BRANN_SET_FLAG_GOSSIP: + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case EVENT_BRANN_ACTIVATE_LASERBEAMS: + { + _instance->SetData(DATA_UPDATE_LASERBEAMS, 0); + + if (_instance->GetData(DATA_VAULT_OF_LIGHTS) == DONE) { - canSayIdleEmote = false; - Talk(urand(0, 1) ? BRANN_SAY_BLASTED_TITANS : BRANN_SAY_THIS_SYMBOL); - events.ScheduleEvent(EVENT_BRANN_IDLE_EMOTE_COOLDOWN, Seconds(45)); // Cooldown for AreaTrigger + if (GameObject* mirror = _instance->GetGameObject(DATA_ANRAPHET_SUN_MIRROR)) + mirror->SetGoState(GO_STATE_ACTIVE); + if (GameObject* door = _instance->GetGameObject(DATA_ANRAPHET_DOOR)) + door->SetGoState(GO_STATE_ACTIVE); + events.ScheduleEvent(EVENT_BRANN_SAY_ALL_ELEMENTAL_DEAD, Seconds(4)); } break; - case ACTION_ELEMENTAL_DIED: - { - uint32 dead = _instance->GetData(DATA_DEAD_ELEMENTALS); - if (dead < 4) // Say that an elemental has died. - Talk(BRANN_1_ELEMENTAL_DEAD + dead - 1); - else // Last one died! Continue script when laser beam activates (9-second animation of light machine behind the warden). - _instance->SetBossState(DATA_VAULT_OF_LIGHTS, DONE); - events.RescheduleEvent(EVENT_BRANN_ACTIVATE_LASERBEAMS, Seconds(9)); - break; } - case ACTION_ANRAPHET_DIED: - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.ScheduleEvent(EVENT_BRANN_MOVE_OUTRO, Seconds(5)); + case EVENT_BRANN_SAY_ALL_ELEMENTAL_DEAD: + Talk(BRANN_4_ELEMENTAL_DEAD); + if (Creature* anraphet = _instance->GetCreature(DATA_ANRAPHET)) + anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO); + break; + case EVENT_BRANN_MOVE_OUTRO: + Talk(BRANN_SAY_ANRAPHET_DIED); + me->GetMotionMaster()->MoveSmoothPath(POINT_BRANN_SAY_MOMENT, BrannOutroPath, BrannOutroPathSize, false); + break; + case EVENT_BRANN_MOVE_FINAL: + me->GetMotionMaster()->MoveSmoothPath(POINT_BRANN_TURN_BACK, BrannFinalPath, BrannFinalPathSize, false); + break; + case EVENT_BRANN_TURN_BACK: + me->SetFacingTo(DegToRad(180.0f)); // Sniff: 3.141593f + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); break; } } + } - void UpdateAI(uint32 diff) override + void MovementInform(uint32 movementType, uint32 pointId) override + { + if (movementType != POINT_MOTION_TYPE && movementType != EFFECT_MOTION_TYPE) + return; + + switch (pointId) { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_BRANN_IDLE_EMOTE_COOLDOWN: - canSayIdleEmote = true; - break; - case EVENT_BRANN_START_INTRO: - Talk(BRANN_SAY_DOOR_INTRO); - events.ScheduleEvent(EVENT_BRANN_UNLOCK_DOOR, Seconds(7)); - break; - case EVENT_BRANN_UNLOCK_DOOR: - Talk(BRANN_SAY_UNLOCK_DOOR); - _instance->SetBossState(DATA_VAULT_OF_LIGHTS, IN_PROGRESS); - events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, Seconds(3)); - break; - case EVENT_BRANN_MOVE_INTRO: - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(POINT_BRANN_SAY_TROGGS, BrannBossHomePos, true); - break; - case EVENT_BRANN_THINK: - Talk(BRANN_SAY_THINK); - events.ScheduleEvent(EVENT_BRANN_LOOK_RIGHT, Seconds(6)); - break; - case EVENT_BRANN_LOOK_RIGHT: - me->SetFacingTo(DegToRad(312.0f)); // Sniff: o = 5.445427f - Talk(BRANN_SAY_MIRRORS); - events.ScheduleEvent(EVENT_BRANN_LOOK_LEFT, Seconds(1)); - break; - case EVENT_BRANN_LOOK_LEFT: - me->SetFacingTo(DegToRad(36.0f)); // Sniff: o = 0.6283185f - events.ScheduleEvent(EVENT_BRANN_SAY_ELEMENTALS, Seconds(3)); - break; - case EVENT_BRANN_SAY_ELEMENTALS: - me->SetFacingTo(DegToRad(1.0f)); // Sniff: o = 0.01745329f - Talk(BRANN_SAY_ELEMENTALS); - events.ScheduleEvent(EVENT_BRANN_SAY_GET_IT, Seconds(4)); - break; - case EVENT_BRANN_SAY_GET_IT: - Talk(BRANN_SAY_GET_IT); - events.ScheduleEvent(EVENT_BRANN_SET_FLAG_GOSSIP, Seconds(16)); - break; - case EVENT_BRANN_SET_FLAG_GOSSIP: - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case EVENT_BRANN_ACTIVATE_LASERBEAMS: - { - // Update laserbeams - _instance->SetData(DATA_UPDATE_LASERBEAMS, 0); - - if (_instance->GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) - { - // Note: In some old sniff file Sun Mirror gets activated every time an elemental dies (for 10 seconds). - // Needs to be checked on live. It makes sense that it is only activated after all four beams are active. - if (GameObject* mirror = _instance->GetGameObject(DATA_ANRAPHET_SUN_MIRROR)) - mirror->SetGoState(GO_STATE_ACTIVE); - if (GameObject* door = _instance->GetGameObject(DATA_ANRAPHET_DOOR)) - door->SetGoState(GO_STATE_ACTIVE); - events.ScheduleEvent(EVENT_BRANN_SAY_ALL_ELEMENTAL_DEAD, Seconds(4)); // Note: 4600 ms - } - break; - } - case EVENT_BRANN_SAY_ALL_ELEMENTAL_DEAD: - Talk(BRANN_4_ELEMENTAL_DEAD); - if (Creature* anraphet = _instance->GetCreature(DATA_ANRAPHET)) - anraphet->AI()->DoAction(ACTION_ANRAPHET_INTRO); - break; - case EVENT_BRANN_MOVE_OUTRO: - Talk(BRANN_SAY_ANRAPHET_DIED); - me->GetMotionMaster()->MoveSmoothPath(POINT_BRANN_SAY_MOMENT, BrannOutroPath, BrannOutroPathSize, false); - break; - case EVENT_BRANN_MOVE_FINAL: - me->GetMotionMaster()->MoveSmoothPath(POINT_BRANN_TURN_BACK, BrannFinalPath, BrannFinalPathSize, false); - break; - case EVENT_BRANN_TURN_BACK: - me->SetFacingTo(DegToRad(180.0f)); // Sniff: 3.141593f - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - } - } - } - - void MovementInform(uint32 movementType, uint32 pointId) override - { - if (movementType != POINT_MOTION_TYPE && movementType != EFFECT_MOTION_TYPE) - return; - - switch (pointId) - { case POINT_BRANN_SAY_TROGGS: me->SetWalk(false); Talk(BRANN_SAY_TROGGS); @@ -527,144 +469,40 @@ public: break; default: break; - } } - - private: - InstanceScript* _instance; - EventMap events; - bool canSayIdleEmote; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetHallsOfOriginationAI(creature); } +private: + InstanceScript * _instance; + EventMap events; + bool canSayIdleEmote; }; -class npc_alpha_beam : public CreatureScript +struct npc_alpha_beam : public ScriptedAI { -public: - npc_alpha_beam() : CreatureScript("npc_alpha_beam") { } + npc_alpha_beam(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - struct npc_alpha_beamAI : public ScriptedAI + void IsSummonedBy(Unit* /*summoner*/) override { - npc_alpha_beamAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } - - void IsSummonedBy(Unit* /*summoner*/) override - { - if (Creature* anraphet = _instance->GetCreature(DATA_ANRAPHET)) - anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST); - } - - void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade - - private: - InstanceScript* _instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetHallsOfOriginationAI(creature); + if (Creature* anraphet = _instance->GetCreature(DATA_ANRAPHET)) + anraphet->CastSpell(me, SPELL_ALPHA_BEAMS_BACK_CAST); } + + void EnterEvadeMode(EvadeReason /*why*/) override { } // Never evade + +private: + InstanceScript * _instance; }; -class npc_omega_stance : public CreatureScript +struct npc_omega_stance : public ScriptedAI { -public: - npc_omega_stance() : CreatureScript("npc_omega_stance") { } + npc_omega_stance(Creature* creature) : ScriptedAI(creature) { } - struct npc_omega_stanceAI : public ScriptedAI + void IsSummonedBy(Unit* /*who*/) override { - npc_omega_stanceAI(Creature* creature) : ScriptedAI(creature) { } - - void IsSummonedBy(Unit* /*who*/) override - { - DoCastSelf(SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true); - } - - void EnterEvadeMode(EvadeReason /*why*/) override { } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetHallsOfOriginationAI(creature); + DoCastSelf(SPELL_OMEGA_STANCE_SPIDER_TRIGGER, true); } -}; -// 77333 Whirling Winds: This script handles Whirling Wind's movement. -class spell_whirling_winds_movement : public SpellScriptLoader -{ -public: - spell_whirling_winds_movement() : SpellScriptLoader("spell_whirling_winds_movement") { } - - class spell_whirling_winds_movement_SpellScript : public SpellScript - { - PrepareSpellScript(spell_whirling_winds_movement_SpellScript); - - void StartMovement(SpellEffIndex /*effIndex*/) - { - Player* target = GetRandomPlayer(false); - if (!target) // Try to get tank. - target = GetRandomPlayer(true); - - if (target) - { - GetCaster()->SetWalk(true); - GetCaster()->GetMotionMaster()->MoveChase(target); - } - } - - void StopMovement(SpellEffIndex /*effIndex*/) - { - // Stop moving when we hit someone and chase another target on next cast. - GetCaster()->StopMoving(); - GetCaster()->GetMotionMaster()->Clear(); - } - - void Register() override - { - OnEffectHit += SpellEffectFn(spell_whirling_winds_movement_SpellScript::StartMovement, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget += SpellEffectFn(spell_whirling_winds_movement_SpellScript::StopMovement, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - - private: - Player* GetRandomPlayer(bool includingTank) - { - Creature* whirlwind = GetCaster()->ToCreature(); - if (!whirlwind || whirlwind->isMoving()) - return NULL; - - // Use Air Warden's threatlist, we don't have one. - Creature* warden = nullptr; - if (InstanceScript* instance = whirlwind->GetInstanceScript()) - warden = instance->GetCreature(DATA_AIR_WARDEN); - if (!warden) - return NULL; - - std::list const& threatlist = warden->getThreatManager().getThreatList(); - std::list targets; - - if (threatlist.empty()) - return NULL; - - // Target must be a player that is not tanking Air Warden and has not been recently hit by this spell. - for (std::list::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if (Unit* refTarget = (*itr)->getTarget()) - if (refTarget->GetTypeId() == TYPEID_PLAYER && (includingTank || refTarget != warden->GetVictim()) && !refTarget->HasAura(m_scriptSpellId)) - targets.push_back(refTarget->ToPlayer()); - - if (targets.empty()) - return NULL; - - return Trinity::Containers::SelectRandomContainerElement(targets); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_whirling_winds_movement_SpellScript(); - } + void EnterEvadeMode(EvadeReason /*why*/) override { } }; class PlayerCheck @@ -679,195 +517,152 @@ class PlayerCheck }; // 77437 - Destruction Protocol -class spell_anraphet_destruction_protocol : public SpellScriptLoader +class spell_anraphet_destruction_protocol : public SpellScript { -public: - spell_anraphet_destruction_protocol() : SpellScriptLoader("spell_anraphet_destruction_protocol") { } + PrepareSpellScript(spell_anraphet_destruction_protocol); - class spell_anraphet_destruction_protocol_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_anraphet_destruction_protocol_SpellScript); + if (targets.empty()) + return; - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; + targets.remove_if(PlayerCheck()); + } - targets.remove_if(PlayerCheck()); - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - if (Creature* trogg = GetHitUnit()->ToCreature()) - trogg->SetRespawnTime(DAY); - } - - void HandlePlayerDamage(SpellEffIndex /*effIndex*/) - { - if (Player* player = GetHitPlayer()) - SetHitDamage(CalculatePct(player->GetHealth(), 90)); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_destruction_protocol_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnEffectHitTarget += SpellEffectFn(spell_anraphet_destruction_protocol_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - OnEffectHitTarget += SpellEffectFn(spell_anraphet_destruction_protocol_SpellScript::HandlePlayerDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - } - }; - - SpellScript* GetSpellScript() const override + void HandleDummy(SpellEffIndex /*effIndex*/) { - return new spell_anraphet_destruction_protocol_SpellScript(); + if (Creature* trogg = GetHitUnit()->ToCreature()) + trogg->SetRespawnTime(DAY); + } + + void HandlePlayerDamage(SpellEffIndex /*effIndex*/) + { + if (Player* player = GetHitPlayer()) + SetHitDamage(CalculatePct(player->GetHealth(), 90)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_destruction_protocol::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_anraphet_destruction_protocol::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_anraphet_destruction_protocol::HandlePlayerDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; -class spell_anraphet_alpha_beams : public SpellScriptLoader +class spell_anraphet_alpha_beams : public SpellScript { -public: - spell_anraphet_alpha_beams() : SpellScriptLoader("spell_anraphet_alpha_beams") { } + PrepareSpellScript(spell_anraphet_alpha_beams); - class spell_anraphet_alpha_beams_SpellScript : public SpellScript + void FilterTargets(std::list& targets) { - PrepareSpellScript(spell_anraphet_alpha_beams_SpellScript); + if (targets.empty()) + return; - void FilterTargets(std::list& targets) - { - if (targets.empty()) - return; + Trinity::Containers::RandomResize(targets, 1); + } - Trinity::Containers::RandomResize(targets, 1); - } - - void Register() override - { - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - } - }; - - SpellScript* GetSpellScript() const override + void Register() override { - return new spell_anraphet_alpha_beams_SpellScript(); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_anraphet_alpha_beams::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; -class spell_anraphet_omega_stance : public SpellScriptLoader +class spell_anraphet_omega_stance : public AuraScript { - public: - spell_anraphet_omega_stance() : SpellScriptLoader("spell_anraphet_omega_stance") { } + PrepareAuraScript(spell_anraphet_omega_stance); - class spell_anraphet_omega_stance_AuraScript : public AuraScript - { - PrepareAuraScript(spell_anraphet_omega_stance_AuraScript); + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->CastSpell(GetTarget(), SPELL_OMEGA_STANCE_SUMMON, true); + } - void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - GetTarget()->CastSpell(GetTarget(), SPELL_OMEGA_STANCE_SUMMON, true); - } + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* omegaStanceDummy = GetTarget()->FindNearestCreature(NPC_OMEGA_STANCE, 50.0f, true)) + omegaStanceDummy->DespawnOrUnsummon(); + } - void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (Creature* omegaStanceDummy = GetTarget()->FindNearestCreature(NPC_OMEGA_STANCE, 50.0f, true)) - omegaStanceDummy->DespawnOrUnsummon(); - } - - void Register() override - { - OnEffectApply += AuraEffectApplyFn(spell_anraphet_omega_stance_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - OnEffectRemove += AuraEffectRemoveFn(spell_anraphet_omega_stance_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_anraphet_omega_stance_AuraScript(); - } + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_anraphet_omega_stance::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_anraphet_omega_stance::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + } }; // 77106 - Omega Stance (Summon) -class spell_anraphet_omega_stance_summon : public SpellScriptLoader +class spell_anraphet_omega_stance_summon : public SpellScript { -public: - spell_anraphet_omega_stance_summon() : SpellScriptLoader("spell_anraphet_omega_stance_summon") { } + PrepareSpellScript(spell_anraphet_omega_stance_summon); - class spell_anraphet_omega_stance_summon_SpellScript : public SpellScript + void SetDestPosition(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_anraphet_omega_stance_summon_SpellScript); - - void SetDestPosition(SpellEffIndex /*effIndex*/) + if (Unit* caster = GetCaster()) { - if (Unit* caster = GetCaster()) - { - float x = caster->GetPositionX(); - float y = caster->GetPositionY(); - float z = caster->GetPositionZ() + 30.0f; + float x = caster->GetPositionX(); + float y = caster->GetPositionY(); + float z = caster->GetPositionZ() + 30.0f; - const_cast(GetExplTargetDest())->Relocate(x, y, z); - GetHitDest()->Relocate(x, y, z); - } + const_cast(GetExplTargetDest())->Relocate(x, y, z); + GetHitDest()->Relocate(x, y, z); } + } - void Register() - { - OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_summon_SpellScript::SetDestPosition, EFFECT_0, SPELL_EFFECT_SUMMON); - } - }; - - SpellScript* GetSpellScript() const override + void Register() { - return new spell_anraphet_omega_stance_summon_SpellScript(); + OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_summon::SetDestPosition, EFFECT_0, SPELL_EFFECT_SUMMON); } }; // 77127 Omega Stance Spider Effect -class spell_anraphet_omega_stance_spider_effect : public SpellScriptLoader +class spell_anraphet_omega_stance_spider_effect : public SpellScript { -public: - spell_anraphet_omega_stance_spider_effect() : SpellScriptLoader("spell_anraphet_omega_stance_spider_effect") { } + PrepareSpellScript(spell_anraphet_omega_stance_spider_effect); - class spell_anraphet_omega_stance_spider_effect_SpellScript : public SpellScript + void SetDestPosition(SpellEffIndex /*effIndex*/) { - PrepareSpellScript(spell_anraphet_omega_stance_spider_effect_SpellScript); + Unit* caster = GetCaster(); + float angle = float(rand_norm()) * static_cast(2 * M_PI); + uint32 dist = caster->GetCombatReach() + GetSpellInfo()->Effects[EFFECT_0].CalcRadius(caster) * (float)rand_norm(); - void SetDestPosition(SpellEffIndex /*effIndex*/) - { - // Do our own calculations for the destination position. - /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration) - Unit* caster = GetCaster(); - float angle = float(rand_norm()) * static_cast(2 * M_PI); - uint32 dist = caster->GetCombatReach() + GetSpellInfo()->Effects[EFFECT_0].CalcRadius(caster) * (float)rand_norm(); + float x = caster->GetPositionX() + dist * std::cos(angle); + float y = caster->GetPositionY() + dist * std::sin(angle); + float z = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, caster->GetPositionZ()); + float o = GetHitDest()->GetOrientation(); - float x = caster->GetPositionX() + dist * std::cos(angle); - float y = caster->GetPositionY() + dist * std::sin(angle); - float z = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, caster->GetPositionZ()); - float o = GetHitDest()->GetOrientation(); - - GetHitDest()->Relocate({ x, y, z, o }); - } - - void Register() - { - OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_spider_effect_SpellScript::SetDestPosition, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_anraphet_omega_stance_spider_effect_SpellScript(); + GetHitDest()->Relocate({ x, y, z, o }); } + + void Register() + { + OnEffectLaunch += SpellEffectFn(spell_anraphet_omega_stance_spider_effect::SetDestPosition, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +// 5811 Brann's AreaTrigger +class at_hoo_brann_idle_emote : public AreaTriggerScript +{ + public: + at_hoo_brann_idle_emote() : AreaTriggerScript("at_hoo_brann_idle_emote") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + if (InstanceScript* instance = player->GetInstanceScript()) + if (Creature* brann = instance->GetCreature(DATA_BRANN_0)) + brann->AI()->DoAction(ACTION_BRANN_IDLE_EMOTE); + return true; + } }; void AddSC_boss_anraphet() { - new boss_anraphet(); + RegisterHallsOfOriginationCreatureAI(boss_anraphet); + RegisterHallsOfOriginationCreatureAI(npc_brann_bronzebeard_anraphet); + RegisterHallsOfOriginationCreatureAI(npc_alpha_beam); + RegisterHallsOfOriginationCreatureAI(npc_omega_stance); + RegisterSpellScript(spell_anraphet_destruction_protocol); + RegisterSpellScript(spell_anraphet_alpha_beams); + RegisterAuraScript(spell_anraphet_omega_stance); + RegisterSpellScript(spell_anraphet_omega_stance_summon); + RegisterSpellScript(spell_anraphet_omega_stance_spider_effect); new at_hoo_brann_idle_emote(); - new npc_brann_bronzebeard_anraphet(); - new npc_alpha_beam(); - new npc_omega_stance(); - new spell_whirling_winds_movement(); - new spell_anraphet_destruction_protocol(); - new spell_anraphet_alpha_beams(); - new spell_anraphet_omega_stance(); - new spell_anraphet_omega_stance_summon(); - new spell_anraphet_omega_stance_spider_effect(); } diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp index 0a2b307e3cf..ac1aa69599e 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp @@ -15,12 +15,6 @@ * with this program. If not, see . */ -/* To-do: */ -// - Summoner Enabler dummy npc: unknown purpose (at the entrance) -// - AreaTrigger: unknown purpose (id: 2275; pos: hole in the left wall at the entrance) -// - Find out what Dummy Nuke (68991) spell does. -// - Spatial Flux won't enter combat on second aggro from creature group (but it should). - #include "ScriptMgr.h" #include "CreatureGroups.h" #include "GameObject.h" diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h index d0687f296f5..7aff45e0822 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.h @@ -30,11 +30,6 @@ enum HOOData // Bosses DATA_TEMPLE_GUARDIAN_ANHUUR, DATA_EARTHRAGER_PTAH, - DATA_VAULT_OF_LIGHTS, - DATA_FIRE_WARDEN, - DATA_EARTH_WARDEN, - DATA_WATER_WARDEN, - DATA_AIR_WARDEN, DATA_ANRAPHET, DATA_ISISET, DATA_AMMUNAE, @@ -61,6 +56,7 @@ enum HOOData DATA_UPDATE_LASERBEAMS, DATA_ANRAPHET_SUN_MIRROR, DATA_ANRAPHET_DOOR, + DATA_VAULT_OF_LIGHTS, // Earthrager Ptah DATA_SUMMON_SANDSTORM_ADDS, @@ -100,7 +96,6 @@ enum HOOCreatures NPC_AIR_WARDEN = 39803, WARDEN_ENTRY_MAX_COUNT = 4, - WARDEN_ENTRY_DATA_DELTA = NPC_FIRE_WARDEN - DATA_FIRE_WARDEN, NPC_BRANN_BRONZEBEARD_0 = 39908, NPC_OMEGA_STANCE = 41194, @@ -194,13 +189,6 @@ enum HOOMisc SPELL_ZERO_ENERGY_NO_REGEN_AURA = 72242, // Zero Energy + Zero Regen (used by some npcs in HoO) // SPELL_SHRINK = 59632, // Used by static NPCs, summoned by bosses in The Four Seats (not in DBC!) - // Hmm... Do elementals use these spells to spawn on a random platform? - // Probably also 81796, 81798, 81799, 81800 (all hidden client-side). - SPELL_TELEPORT_EARTH = 82329, // South-West - SPELL_TELEPORT_AIR = 82330, // South-East - SPELL_TELEPORT_FIRE = 82331, // North-West - SPELL_TELEPORT_WATER = 82332, // North-East - // Cave In Stalker (beacons) SPELL_SHIELD_VISUAL_LEFT = 83697, SPELL_SHIELD_VISUAL_RIGHT = 83698, @@ -222,18 +210,28 @@ enum HOOGlobalActions ACTION_OMEGA_TRIGGER }; -enum DataStates +enum HoODataStates { ACTIVATE_SHIELD_OF_LIGHT = 0, DISABLE_SHIELD_OF_LIGHT }; +enum HoOEvents +{ + EVENT_RESPAWN_ANRAPHET = 1 +}; + +Position const AnraphetSpawnPos = { -90.2726f, 366.339f, 89.8639f, 3.14159f }; +Position const AnraphetRespawnPos = { -193.656f, 366.689f, 75.91001f, 3.138207f }; + template inline AI* GetHallsOfOriginationAI(Creature* creature) { return GetInstanceAI(creature, HoOScriptName); } +#define RegisterHallsOfOriginationCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetHallsOfOriginationAI) + template inline AI* GetHallsOfOriginationAI(GameObject* go) { diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp index 5a302a2208a..f8532ce4223 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp @@ -46,10 +46,6 @@ ObjectData const creatureData[] = { BOSS_TEMPLE_GUARDIAN_ANHUUR, DATA_TEMPLE_GUARDIAN_ANHUUR }, { BOSS_EARTHRAGER_PTAH, DATA_EARTHRAGER_PTAH }, { NPC_BRANN_BRONZEBEARD_0, DATA_BRANN_0 }, - { NPC_FIRE_WARDEN, DATA_FIRE_WARDEN }, - { NPC_EARTH_WARDEN, DATA_EARTH_WARDEN }, - { NPC_WATER_WARDEN, DATA_WATER_WARDEN }, - { NPC_AIR_WARDEN, DATA_AIR_WARDEN }, { BOSS_ANRAPHET, DATA_ANRAPHET }, { BOSS_ISISET, DATA_ISISET }, { BOSS_AMMUNAE, DATA_AMMUNAE }, @@ -89,11 +85,30 @@ class instance_halls_of_origination : public InstanceMapScript SetBossNumber(EncounterCount); LoadDoorData(doorData); LoadObjectData(creatureData, gameObjectData); + } + void Initialize() + { _brannIntroStarted = 0; _deadElementals = 0; + _anraphetInitialized = false; + _vaultOfLightState = NOT_STARTED; + } - RotateWardenPositions(); + void OnPlayerEnter(Player* /*player*/) override + { + if (!_anraphetInitialized) + { + if (GetData(DATA_VAULT_OF_LIGHTS) != DONE) + { + if (Creature* anraphet = instance->SummonCreature(BOSS_ANRAPHET, AnraphetSpawnPos)) + anraphet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_6 | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NOT_SELECTABLE); + } + else + instance->SummonCreature(BOSS_ANRAPHET, AnraphetRespawnPos); + + _anraphetInitialized = true; + } } void OnGameObjectCreate(GameObject* go) override @@ -111,31 +126,25 @@ class instance_halls_of_origination : public InstanceMapScript go->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 0); break; case GO_VAULT_OF_LIGHTS_DOOR: - if (_brannIntroStarted || GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) + if (_vaultOfLightState != NOT_STARTED) go->SetGoState(GO_STATE_ACTIVE); break; case GO_DOODAD_ULDUM_LASERBEAMS01: - if (GetBossState(DATA_EARTH_WARDEN) == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; case GO_DOODAD_ULDUM_LASERBEAMS_01: - if (GetBossState(DATA_FIRE_WARDEN) == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; case GO_DOODAD_ULDUM_LASERBEAMS_02: - if (GetBossState(DATA_AIR_WARDEN) == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; case GO_DOODAD_ULDUM_LASERBEAMS_03: - if (GetBossState(DATA_WATER_WARDEN) == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; + case GO_DOODAD_ULDUM_LIGHTMACHINE_01: + case GO_DOODAD_ULDUM_LIGHTMACHINE_02: + case GO_DOODAD_ULDUM_LIGHTMACHINE_03: + case GO_DOODAD_ULDUM_LIGHTMACHINE_04: case GO_SUN_MIRROR: case GO_ANRAPHET_DOOR: - if (GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) + go->SetFarVisible(true); + go->setActive(true); + if (GetData(DATA_VAULT_OF_LIGHTS) == DONE) go->SetGoState(GO_STATE_ACTIVE); break; - case GO_ULDUM_TEMPLE: // Research about these objects. + case GO_ULDUM_TEMPLE: case GO_REORIGINATION_MECHANISM_1: case GO_REORIGINATION_MECHANISM_2: case GO_REORIGINATION_MECHANISM_3: @@ -143,13 +152,6 @@ class instance_halls_of_origination : public InstanceMapScript case GO_REORIGINATION_MECHANISM_5: go->SetGoState(GO_STATE_ACTIVE); break; - case GO_DOODAD_ULDUM_LIGHTMACHINE_01: - case GO_DOODAD_ULDUM_LIGHTMACHINE_02: - case GO_DOODAD_ULDUM_LIGHTMACHINE_03: - case GO_DOODAD_ULDUM_LIGHTMACHINE_04: - if (GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; default: break; } @@ -175,18 +177,18 @@ class instance_halls_of_origination : public InstanceMapScript if (Creature* ptah = GetCreature(DATA_EARTHRAGER_PTAH)) ptah->AI()->JustSummoned(creature); break; - case BOSS_ANRAPHET: // Must be active (their AI runs the event at the Vault of Lights). + case BOSS_ANRAPHET: case NPC_BRANN_BRONZEBEARD_0: creature->setActive(true); + creature->SetFarVisible(true); break; - case NPC_FIRE_WARDEN: // random teleport spell + far-visibility + case NPC_FIRE_WARDEN: case NPC_EARTH_WARDEN: case NPC_WATER_WARDEN: case NPC_AIR_WARDEN: - creature->CastSpell(nullptr, _wardenPositionSpells[creature->GetEntry() - NPC_FIRE_WARDEN]); creature->SetFarVisible(true); break; - case NPC_STONE_TROGG_PILLAGER: // far-visibility + case NPC_STONE_TROGG_PILLAGER: case NPC_STONE_TROGG_BRUTE: case NPC_STONE_TROGG_ROCK_FLINGER: if (GetBossState(DATA_VAULT_OF_LIGHTS) == DONE) @@ -272,6 +274,21 @@ class instance_halls_of_origination : public InstanceMapScript else beetleStalker->CastSpell(beetleStalker, SPELL_BEETLE_BURROW); break; + case DATA_VAULT_OF_LIGHTS: + _vaultOfLightState = value; + + if (value == IN_PROGRESS) + { + if (GameObject* door = GetGameObject(DATA_VAULT_OF_LIGHTS_DOOR)) + door->SetGoState(GO_STATE_ACTIVE); + + DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_START_EVENT); + } + else if (value == DONE) + DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_VAULT_OF_LIGHTS_CREDIT); + + SaveToDB(); + break; default: break; } @@ -291,6 +308,8 @@ class instance_halls_of_origination : public InstanceMapScript return _isisetCelestialCallAlive; case DATA_ISISET_VEIL_OF_SKY_ALIVE: return _isisetVeilOfSkyAlive; + case DATA_VAULT_OF_LIGHTS: + return _vaultOfLightState; default: break; } @@ -303,7 +322,7 @@ class instance_halls_of_origination : public InstanceMapScript if (!InstanceScript::SetBossState(type, state)) return false; - if (state == DONE) // Respawn transit devices if needed. + if (state == DONE) for (ObjectGuid guid : _transitDeviceGUIDs) if (GameObject* transit = instance->GetGameObject(guid)) UpdateTransitDevice(transit); @@ -330,28 +349,9 @@ class instance_halls_of_origination : public InstanceMapScript beetleStalker->RemoveAllAuras(); } break; - case DATA_VAULT_OF_LIGHTS: - if (state == IN_PROGRESS) - { - HandleGameObject(ObjectGuid::Empty, true, GetGameObject(DATA_VAULT_OF_LIGHTS_DOOR)); - DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_START_EVENT); - } - else if (state == DONE) - { - DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, SPELL_VAULT_OF_LIGHTS_CREDIT); - } - break; - case DATA_FIRE_WARDEN: - case DATA_EARTH_WARDEN: - case DATA_WATER_WARDEN: - case DATA_AIR_WARDEN: - if (state == DONE) - { - UpdateAllLightMachines(); - ++_deadElementals; - if (Creature* brann = GetCreature(DATA_BRANN_0)) - brann->AI()->DoAction(ACTION_ELEMENTAL_DIED); - } + case DATA_ANRAPHET: + if (state == FAIL) + _events.ScheduleEvent(EVENT_RESPAWN_ANRAPHET, 30s); break; default: break; @@ -373,16 +373,14 @@ class instance_halls_of_origination : public InstanceMapScript if (Creature* ptah = GetCreature(DATA_EARTHRAGER_PTAH)) ptah->GetAI()->DoAction(ACTION_PTAH_ADD_DIED); break; - case NPC_FIRE_WARDEN: // We have to set boss states manually (wardens use SmartAI). - case NPC_EARTH_WARDEN: // To-do: check if smart scripts can handle this + case NPC_FIRE_WARDEN: + case NPC_EARTH_WARDEN: case NPC_WATER_WARDEN: case NPC_AIR_WARDEN: - { - uint32 data = creature->GetEntry() - WARDEN_ENTRY_DATA_DELTA; - SetBossState(data, IN_PROGRESS); // Needs to be set to IN_PROGRESS or else the gameobjects state won't be updated - SetBossState(data, DONE); + _deadElementals++; + if (Creature* brann = GetCreature(DATA_BRANN_0)) + brann->AI()->DoAction(ACTION_ELEMENTAL_DIED); break; - } case NPC_SPATIAL_ANOMALY: case NPC_FLUX_ANIMATOR: case NPC_STAR_SHARD: @@ -408,48 +406,44 @@ class instance_halls_of_origination : public InstanceMapScript } } + void Update(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RESPAWN_ANRAPHET: + instance->SummonCreature(BOSS_ANRAPHET, AnraphetRespawnPos); + break; + default: + break; + } + } + } + void WriteSaveDataMore(std::ostringstream& data) override { - data << _brannIntroStarted << ' ' << _deadElementals << ' '; - - for (uint8 i = 0; i < WARDEN_ENTRY_MAX_COUNT; i++) - data << _wardenPositionSpells[i] << ' '; + data << _vaultOfLightState << ' ' + << _deadElementals; } void ReadSaveDataMore(std::istringstream& data) override { - data >> _brannIntroStarted >> _deadElementals; - - for (uint8 i = 0; i < WARDEN_ENTRY_MAX_COUNT; i++) - data >> _wardenPositionSpells[i]; + data >> _vaultOfLightState; + data >> _deadElementals; } private: - void RotateWardenPositions() - { - uint32 startAt = urand(0, WARDEN_ENTRY_MAX_COUNT - 1); - for (uint32 i = 0; i < WARDEN_ENTRY_MAX_COUNT; i++) - _wardenPositionSpells[(i + startAt) % WARDEN_ENTRY_MAX_COUNT] = SPELL_TELEPORT_EARTH + i; - } - // Activated when warden dies (on SetBossState DONE). void UpdateAllLightMachines() { - for (uint8 i = 0; i < WARDEN_ENTRY_MAX_COUNT; i++) - { - uint32 positionIndex = _wardenPositionSpells[i] - SPELL_TELEPORT_EARTH; - HandleGameObject(ObjectGuid::Empty, GetBossState(DATA_FIRE_WARDEN + i) == DONE, GetGameObject(DATA_LIGHTMACHINE_EARTH + positionIndex)); - } } // Activated 9 seconds after warden dies (on SetData DATA_UPDATE_LASERBEAMS, called by Brann). void UpdateAllLaserBeams() { - for (uint8 i = 0; i < WARDEN_ENTRY_MAX_COUNT; i++) - { - uint32 positionIndex = _wardenPositionSpells[i] - SPELL_TELEPORT_EARTH; - HandleGameObject(ObjectGuid::Empty, GetBossState(DATA_FIRE_WARDEN + i) == DONE, GetGameObject(DATA_LIGHTMACHINE_EARTH + positionIndex)); - } } void UpdateTransitDevice(GameObject* transit) @@ -461,19 +455,21 @@ class instance_halls_of_origination : public InstanceMapScript else // All other transits. transit->SetRespawnTime(GetBossState(DATA_ANRAPHET) == DONE ? -1 : DAY); } - + + EventMap _events; GuidSet _transitDeviceGUIDs; GuidSet _hooCamelGUIDs; GuidSet _isisetTrashGUIDs; GuidSet _caveInStalkerGUIDs; GuidSet _beetleStalkerGUIDS; uint32 _brannIntroStarted; - uint32 _wardenPositionSpells[WARDEN_ENTRY_MAX_COUNT]; uint32 _deadElementals; uint32 _isisetPhase; uint32 _isisetAstralRainAlive; uint32 _isisetCelestialCallAlive; uint32 _isisetVeilOfSkyAlive; + uint8 _vaultOfLightState; + bool _anraphetInitialized; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override