diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index a7b2be240..b9110e2e3 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -3051,95 +3051,110 @@ public: } }; -class npc_icc_spire_frostwyrm : public CreatureScript +enum SpireFrostwyrm { -public: - npc_icc_spire_frostwyrm() : CreatureScript("npc_icc_spire_frostwyrm") { } + SPELL_BLIZZARD = 70362, + SPELL_CLEAVE = 70361, + SPELL_FROSTBREATH = 70116, - struct npc_icc_spire_frostwyrmAI : public ScriptedAI + HORDE_AREATRIGGER = 5630 +}; + +struct npc_icc_spire_frostwyrm : public ScriptedAI +{ + npc_icc_spire_frostwyrm(Creature* creature) : ScriptedAI(creature) { - npc_icc_spire_frostwyrmAI(Creature* creature) : ScriptedAI(creature) + _scheduler.SetValidator([this] { - me->SetCanFly(true); - me->SetDisableGravity(true); - } + return !me->HasUnitState(UNIT_STATE_CASTING); + }); - EventMap events; - - void Reset() override - { - events.Reset(); - events.ScheduleEvent(1, 15s, 25s); // blizzard - events.ScheduleEvent(2, 5s); // cleave - events.ScheduleEvent(3, 10s, 15s); // frost breath - } - - void DoAction(int32 a) override - { - if (a != -1) - return; - if (me->GetHomePosition().GetPositionZ() < 225.0f) - return; - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), 191.26f, me->GetOrientation()); - me->GetMotionMaster()->MoveLand(1, me->GetPositionX(), me->GetPositionY(), 191.26f, 2.5f * 7.0f); - Talk(0); - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == EFFECT_MOTION_TYPE && id == 1) - { - me->SetCanFly(false); - me->SetDisableGravity(false); - - if (Player* p = SelectTargetFromPlayerList(100.0f)) - { - Talk(p->GetTeamId() == TEAM_HORDE ? 1 : 2); - AttackStart(p); - } - } - } - - bool CanAIAttack(Unit const* target) const override - { - return me->GetPositionZ() < 225.0f && me->GetHomePosition().GetExactDist(target) < 200.0f; - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case 1: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true)) - me->CastSpell(target, 70362, false); - events.Repeat(25s, 35s); - break; - case 2: - me->CastSpell(me->GetVictim(), 70361, false); - events.Repeat(5s); - break; - case 3: - me->CastSpell(me->GetVictim(), 70116, false); - events.Repeat(10s, 15s); - break; - } - - DoMeleeAttackIfReady(); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetIcecrownCitadelAI(creature); + _canResetFlyingEffects = true; } + + void Reset() override + { + if (!_canResetFlyingEffects) + { + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + } + } + + void JustEngagedWith(Unit* /*victim*/) override + { + _scheduler.Schedule(15s, 25s, [this](TaskContext context) + { + DoCastRandomTarget(SPELL_BLIZZARD); + context.Repeat(25s, 35s); + }).Schedule(5s, [this](TaskContext context) + { + DoCastVictim(SPELL_CLEAVE); + context.Repeat(); + }).Schedule(10s, 15s, [this](TaskContext context) + { + DoCastVictim(SPELL_FROSTBREATH); + context.Repeat(); + }); + + _canResetFlyingEffects = false; + } + + void DoAction(int32 action) override + { + const Position posHordeMove = { -433.667084f, 2080.347412f, 191.253860f, 3.825093f }; + const Position posAllianceMove = { -433.589508f, 2344.564697f, 191.253616f, 2.543328f }; + + bool hordeSide = action == HORDE_AREATRIGGER || action == HORDE_AREATRIGGER + 1; + Position landingPosition = hordeSide ? posHordeMove : posAllianceMove; + + me->GetMotionMaster()->MovePoint(1, landingPosition); + me->SetHomePosition(landingPosition); + + Talk(0); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type == EFFECT_MOTION_TYPE && id == 1) + { + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + _canResetFlyingEffects = false; + } + } + + void JustReachedHome() override + { + ScriptedAI::JustReachedHome(); + if (!_canResetFlyingEffects) + { + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + } + } + + bool CanAIAttack(Unit const* target) const override + { + return me->GetPositionZ() < 225.0f && me->GetHomePosition().GetExactDist(target) < 200.0f; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } + + private: + TaskScheduler _scheduler; + bool _canResetFlyingEffects; }; #define VENGEFUL_WP_COUNT 6 @@ -3746,16 +3761,27 @@ public: } }; -class at_icc_spire_frostwyrm : public AreaTriggerScript +class at_icc_spire_frostwyrm : public OnlyOnceAreaTriggerScript { public: - at_icc_spire_frostwyrm() : AreaTriggerScript("at_icc_spire_frostwyrm") { } + at_icc_spire_frostwyrm() : OnlyOnceAreaTriggerScript("at_icc_spire_frostwyrm") { } - bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override + bool _OnTrigger(Player* player, AreaTrigger const* areaTrigger) override { - if (Creature* frostwyrm = player->FindNearestCreature(NPC_SPIRE_FROSTWYRM, 150.0f, true)) - if (frostwyrm->GetPositionZ() > 250.0f && frostwyrm->AI()) - frostwyrm->AI()->DoAction(-1); + if (player->GetInstanceScript()->GetPersistentData(DATA_SPIRE_FROSTWYRM) != DONE) + { + player->GetInstanceScript()->StorePersistentData(DATA_SPIRE_FROSTWYRM, DONE); + const Position posHordeWyrm = { -375.538879f, 2120.774658f, 242.256775f, 3.714352f }; + const Position posAllianceWyrm = { -361.154358f, 2305.821289f, 244.771713f, 2.704335f }; + + bool hordeSide = areaTrigger->entry == HORDE_AREATRIGGER || areaTrigger->entry == HORDE_AREATRIGGER + 1; + + if (Creature* frostwyrm = player->SummonCreature(NPC_SPIRE_FROSTWYRM, hordeSide ? posHordeWyrm : posAllianceWyrm)) + { + frostwyrm->AI()->DoAction(areaTrigger->entry); + } + } + return true; } }; @@ -3803,7 +3829,7 @@ void AddSC_icecrown_citadel() new npc_icc_skybreaker_luminary(); new npc_icc_valkyr_herald(); new npc_icc_severed_essence(); - new npc_icc_spire_frostwyrm(); + RegisterIcecrownCitadelCreatureAI(npc_icc_spire_frostwyrm); new npc_icc_vengeful_fleshreaper(); new npc_icc_buff_switcher(); new npc_icc_nerubar_broodkeeper(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 73eac4e21..a76c44478 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -148,6 +148,12 @@ enum DataTypes DATA_BPC_TRASH_DIED = 300, }; +enum PersistentData +{ + DATA_SPIRE_FROSTWYRM = 0, + MAX_DATA_INDEXES +}; + enum CreaturesIds { // At Light's Hammer diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 09f4d47f8..7337551a2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -199,6 +199,7 @@ public: SetHeaders(DataHeader); SetBossNumber(MAX_ENCOUNTERS); + SetPersistentDataCount(MAX_DATA_INDEXES); LoadBossBoundaries(boundaries); LoadDoorData(doorData); TeamIdInInstance = TEAM_NEUTRAL;