diff --git a/data/sql/updates/pending_db_world/rev_1687609506371262000.sql b/data/sql/updates/pending_db_world/rev_1687609506371262000.sql new file mode 100644 index 000000000..b495cd874 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1687609506371262000.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `ScriptName` = '' WHERE `ScriptName` = 'npc_ahune_frozen_core'; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp index a6772b488..cf4652555 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SlavePens/boss_ahune.cpp @@ -81,234 +81,234 @@ enum eEvents EVENT_SPELL_SUMMON_COLDWAVE, }; -class boss_ahune : public CreatureScript +enum Misc { -public: - boss_ahune() : CreatureScript("boss_ahune") { } + SET_GUID_INVOKER = 1 +}; - CreatureAI* GetAI(Creature* pCreature) const override +struct boss_ahune : public ScriptedAI +{ + boss_ahune(Creature* c) : ScriptedAI(c), summons(me) { - return GetTheSlavePensAI(pCreature); + SetCombatMovement(false); + SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + InvokerGUID.Clear(); + events.Reset(); + events.RescheduleEvent(EVENT_EMERGE, 12000); + events.RescheduleEvent(EVENT_INVOKER_SAY_1, 1000); + events.RescheduleEvent(EVENT_SUMMON_TOTEMS, 4000); } - struct boss_ahuneAI : public ScriptedAI + EventMap events; + SummonList summons; + ObjectGuid InvokerGUID; + + void StartPhase1() { - boss_ahuneAI(Creature* c) : ScriptedAI(c), summons(me) + me->CastSpell(me, SPELL_AHUNES_SHIELD, true); + events.RescheduleEvent(EVENT_TOTEMS_ATTACK, 80000); + events.RescheduleEvent(EVENT_SPELL_COLD_SLAP, 1200); + events.RescheduleEvent(EVENT_SPELL_SUMMON_HAILSTONE, 2000); + events.RescheduleEvent(EVENT_SPELL_SUMMON_COLDWAVE, 5000); + } + + void JustEngagedWith(Unit* /*who*/) override + { + DoZoneInCombat(); + events.Reset(); + StartPhase1(); + } + + void SetGUID(ObjectGuid guid, int32 id) override + { + if (id == SET_GUID_INVOKER) { - SetCombatMovement(false); - SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - InvokerGUID.Clear(); - events.Reset(); - events.RescheduleEvent(EVENT_EMERGE, 12000); - events.RescheduleEvent(EVENT_INVOKER_SAY_1, 1000); - events.RescheduleEvent(EVENT_SUMMON_TOTEMS, 4000); + InvokerGUID = guid; } + } - EventMap events; - SummonList summons; - ObjectGuid InvokerGUID; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) + return; - void StartPhase1() + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - me->CastSpell(me, SPELL_AHUNES_SHIELD, true); - events.RescheduleEvent(EVENT_TOTEMS_ATTACK, 80000); - events.RescheduleEvent(EVENT_SPELL_COLD_SLAP, 1200); - events.RescheduleEvent(EVENT_SPELL_SUMMON_HAILSTONE, 2000); - events.RescheduleEvent(EVENT_SPELL_SUMMON_COLDWAVE, 5000); - } - - void JustEngagedWith(Unit* /*who*/) override - { - DoZoneInCombat(); + case 0: + break; + case EVENT_EMERGE: + me->SetVisible(true); + me->CastSpell(me, SPELL_EMERGE_0, false); + events.RescheduleEvent(EVENT_ATTACK, 2000); + break; + case EVENT_SUMMON_TOTEMS: + for (uint8 i = 0; i < 3; ++i) + DoSummon(NPC_TOTEM, TotemPos[i], 10 * 60 * 1000, TEMPSUMMON_TIMED_DESPAWN); + break; + case EVENT_INVOKER_SAY_1: + if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) + { + plr->Say("The Ice Stone has melted!", LANG_UNIVERSAL); + plr->CastSpell(plr, SPELL_MAKE_BONFIRE, true); + } + events.RescheduleEvent(EVENT_INVOKER_SAY_2, 2000); + break; + case EVENT_INVOKER_SAY_2: + if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) + plr->Say("Ahune, your strength grows no more!", LANG_UNIVERSAL); + events.RescheduleEvent(EVENT_INVOKER_SAY_3, 2000); + break; + case EVENT_INVOKER_SAY_3: + if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) + plr->Say("Your frozen reign will not come to pass!", LANG_UNIVERSAL); + break; + case EVENT_ATTACK: events.Reset(); + if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) + AttackStart(plr); + me->SetInCombatWithZone(); + if (!me->IsInCombat()) + { + EnterEvadeMode(EVADE_REASON_OTHER); + return; + } + else + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + break; + case EVENT_TOTEMS_ATTACK: + for (uint8 i = 0; i < 3; ++i) + if (Creature* bunny = me->FindNearestCreature(NPC_TOTEM_BUNNY_1 + i, 150.0f, true)) + bunny->CastSpell(me, SPELL_TOTEM_BEAM, false); + events.RescheduleEvent(EVENT_SUBMERGE, 10000); + break; + case EVENT_SUBMERGE: + Talk(EMOTE_RETREAT); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->CastSpell(me, SPELL_SUBMERGE_0, true); + me->CastSpell(me, SPELL_SELF_STUN, true); + if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN)) + { + c->SetHealth(me->GetHealth()); + } + events.Reset(); + events.RescheduleEvent(EVENT_COMBAT_EMERGE, 25000); + events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000); + break; + case EVENT_EMERGE_WARNING: + Talk(EMOTE_RESURFACE); + break; + case EVENT_COMBAT_EMERGE: + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAura(SPELL_SELF_STUN); + me->CastSpell(me, SPELL_EMERGE_0, false); + // me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn + me->RemoveAura(SPELL_SUBMERGE_0); StartPhase1(); - } + break; - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch(events.ExecuteEvent()) - { - case 0: - break; - case EVENT_EMERGE: - me->SetVisible(true); - me->CastSpell(me, SPELL_EMERGE_0, false); - events.RescheduleEvent(EVENT_ATTACK, 2000); - break; - case EVENT_SUMMON_TOTEMS: - for (uint8 i = 0; i < 3; ++i) - DoSummon(NPC_TOTEM, TotemPos[i], 10 * 60 * 1000, TEMPSUMMON_TIMED_DESPAWN); - break; - case EVENT_INVOKER_SAY_1: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - { - plr->Say("The Ice Stone has melted!", LANG_UNIVERSAL); - plr->CastSpell(plr, SPELL_MAKE_BONFIRE, true); - } - events.RescheduleEvent(EVENT_INVOKER_SAY_2, 2000); - break; - case EVENT_INVOKER_SAY_2: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - plr->Say("Ahune, your strength grows no more!", LANG_UNIVERSAL); - events.RescheduleEvent(EVENT_INVOKER_SAY_3, 2000); - break; - case EVENT_INVOKER_SAY_3: - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - plr->Say("Your frozen reign will not come to pass!", LANG_UNIVERSAL); - break; - case EVENT_ATTACK: - events.Reset(); - if (Player* plr = ObjectAccessor::GetPlayer(*me, InvokerGUID)) - AttackStart(plr); - me->SetInCombatWithZone(); - if (!me->IsInCombat()) - { - EnterEvadeMode(EVADE_REASON_OTHER); - return; - } - else - me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - break; - case EVENT_TOTEMS_ATTACK: - for (uint8 i = 0; i < 3; ++i) - if (Creature* bunny = me->FindNearestCreature(NPC_TOTEM_BUNNY_1 + i, 150.0f, true)) - bunny->CastSpell(me, SPELL_TOTEM_BEAM, false); - events.RescheduleEvent(EVENT_SUBMERGE, 10000); - break; - case EVENT_SUBMERGE: - Talk(EMOTE_RETREAT); - me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->CastSpell(me, SPELL_SUBMERGE_0, true); - me->CastSpell(me, SPELL_SELF_STUN, true); - if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_DESPAWN)) - { - c->SetHealth(me->GetHealth()); - } - events.Reset(); - events.RescheduleEvent(EVENT_COMBAT_EMERGE, 25000); - events.RescheduleEvent(EVENT_EMERGE_WARNING, 20000); - break; - case EVENT_EMERGE_WARNING: - Talk(EMOTE_RESURFACE); - break; - case EVENT_COMBAT_EMERGE: - me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAura(SPELL_SELF_STUN); - me->CastSpell(me, SPELL_EMERGE_0, false); - // me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn - me->RemoveAura(SPELL_SUBMERGE_0); - StartPhase1(); - break; - - case EVENT_SPELL_COLD_SLAP: - if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 5.0f, true)) - if (target->GetPositionZ() < me->GetPositionZ() + 6.0f) - { - int32 dmg = urand(5500, 6000); - me->CastCustomSpell(target, SPELL_COLD_SLAP, &dmg, nullptr, nullptr, false); - float x, y, z; - target->GetNearPoint(target, x, y, z, target->GetObjectSize(), 30.0f, target->GetAngle(me->GetPositionX(), me->GetPositionY()) + M_PI); - target->GetMotionMaster()->MoveJump(x, y, z + 20.0f, 10.0f, 20.0f); - } - events.RepeatEvent(1500); - break; - case EVENT_SPELL_SUMMON_HAILSTONE: - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false); - events.RepeatEvent(30000); - } - break; - case EVENT_SPELL_SUMMON_COLDWAVE: - for (uint8 i = 0; i < 2; ++i) - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false); - } - { - float dist = (float)urand(3, 10); - float angle = rand_norm() * 2 * M_PI; - me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false); - } - events.RepeatEvent(6000); - break; - - default: - break; - } - - DoMeleeAttackIfReady(); - } - - void MoveInLineOfSight(Unit* /*who*/) override {} - - void EnterEvadeMode(EvadeReason why) override - { - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - events.Reset(); - summons.DespawnAll(); - me->DespawnOrUnsummon(1); - - ScriptedAI::EnterEvadeMode(why); - } - - void JustSummoned(Creature* summon) override - { - if (summon) - { - summons.Summon(summon); - summon->SetInCombatWithZone(); - } - } - - void SummonedCreatureDespawn(Creature* summon) override - { - if (summon && summon->GetEntry() == NPC_FROZEN_CORE) - { - if (summon->GetHealth() > 0) + case EVENT_SPELL_COLD_SLAP: + if (Unit* target = SelectTarget(SelectTargetMethod::MaxDistance, 0, 5.0f, true)) + if (target->GetPositionZ() < me->GetPositionZ() + 6.0f) { - me->SetHealth(summon->GetHealth()); - summon->CastSpell(summon, SPELL_AHUNE_RESURFACES, true); + int32 dmg = urand(5500, 6000); + me->CastCustomSpell(target, SPELL_COLD_SLAP, &dmg, nullptr, nullptr, false); + float x, y, z; + target->GetNearPoint(target, x, y, z, target->GetObjectSize(), 30.0f, target->GetAngle(me->GetPositionX(), me->GetPositionY()) + M_PI); + target->GetMotionMaster()->MoveJump(x, y, z + 20.0f, 10.0f, 20.0f); } - else - Unit::Kill(me, me, false); - } - } - - void JustDied(Unit* /*killer*/) override + events.RepeatEvent(1500); + break; + case EVENT_SPELL_SUMMON_HAILSTONE: { - summons.DespawnAll(); - me->DespawnOrUnsummon(15000); - if (GameObject* chest = me->SummonGameObject(187892, MinionSummonPos.GetPositionX(), MinionSummonPos.GetPositionY(), MinionSummonPos.GetPositionZ(), M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 900000000)) // loot - me->RemoveGameObject(chest, false); - - bool finished = false; - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (!players.IsEmpty()) - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - if (Player* player = i->GetSource()) - { - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me); - - if (player->GetGroup() && !finished) - { - finished = true; - sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap()); - } - } + float dist = (float)urand(3, 10); + float angle = rand_norm() * 2 * M_PI; + me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false); + events.RepeatEvent(30000); } - }; + break; + case EVENT_SPELL_SUMMON_COLDWAVE: + for (uint8 i = 0; i < 2; ++i) + { + float dist = (float)urand(3, 10); + float angle = rand_norm() * 2 * M_PI; + me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false); + } + { + float dist = (float)urand(3, 10); + float angle = rand_norm() * 2 * M_PI; + me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false); + } + events.RepeatEvent(6000); + break; + + default: + break; + } + + DoMeleeAttackIfReady(); + } + + void MoveInLineOfSight(Unit* /*who*/) override {} + + void EnterEvadeMode(EvadeReason why) override + { + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + events.Reset(); + summons.DespawnAll(); + me->DespawnOrUnsummon(1); + + ScriptedAI::EnterEvadeMode(why); + } + + void JustSummoned(Creature* summon) override + { + if (summon) + { + summons.Summon(summon); + summon->SetInCombatWithZone(); + } + } + + void SummonedCreatureDespawn(Creature* summon) override + { + if (summon && summon->GetEntry() == NPC_FROZEN_CORE) + { + if (summon->GetHealth() > 0) + { + me->SetHealth(summon->GetHealth()); + summon->CastSpell(summon, SPELL_AHUNE_RESURFACES, true); + } + else + Unit::Kill(me, me, false); + } + } + + void JustDied(Unit* /*killer*/) override + { + summons.DespawnAll(); + me->DespawnOrUnsummon(15000); + if (GameObject* chest = me->SummonGameObject(187892, MinionSummonPos.GetPositionX(), MinionSummonPos.GetPositionY(), MinionSummonPos.GetPositionZ(), M_PI / 2, 0.0f, 0.0f, 0.0f, 0.0f, 900000000)) // loot + me->RemoveGameObject(chest, false); + + bool finished = false; + + me->GetMap()->DoForAllPlayers([&](Player* player) + { + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me); + + if (player->GetGroup() && !finished) + { + finished = true; + sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap()); + } + }); + } }; class go_ahune_ice_stone : public GameObjectScript @@ -369,7 +369,11 @@ public: c->SetVisible(false); c->SetDisplayId(AHUNE_DEFAULT_MODEL); c->SetFloatValue(UNIT_FIELD_COMBATREACH, 18.0f); - CAST_AI(boss_ahune::boss_ahuneAI, c->AI())->InvokerGUID = player->GetGUID(); + if (c->AI()) + { + c->AI()->SetGUID(player->GetGUID(), SET_GUID_INVOKER); + } + if (Creature* bunny = go->SummonCreature(NPC_AHUNE_SUMMON_LOC_BUNNY, AhuneSummonPos, TEMPSUMMON_TIMED_DESPAWN, 12000)) if (Creature* crystal_trigger = go->SummonCreature(WORLD_TRIGGER, go->GetPositionX(), go->GetPositionY(), 5.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 12000)) crystal_trigger->CastSpell(bunny, SPELL_STARTING_BEAM, false); @@ -380,30 +384,8 @@ public: } }; -class npc_ahune_frozen_core : public CreatureScript -{ -public: - npc_ahune_frozen_core() : CreatureScript("npc_ahune_frozen_core") { } - - CreatureAI* GetAI(Creature* pCreature) const override - { - return GetTheSlavePensAI(pCreature); - } - - struct npc_ahune_frozen_coreAI : public NullCreatureAI - { - npc_ahune_frozen_coreAI(Creature* c) : NullCreatureAI(c) {} - - void JustDied(Unit* /*killer*/) override - { - me->DespawnOrUnsummon(); - } - }; -}; - void AddSC_boss_ahune() { new go_ahune_ice_stone(); - new boss_ahune(); - new npc_ahune_frozen_core(); + RegisterTheSlavePensCreatureAI(boss_ahune); }