From cb07d1fc8a40b44595a785045458f3f41bbba95c Mon Sep 17 00:00:00 2001
From: patou01 <2592673+patou01@users.noreply.github.com>
Date: Sun, 7 Nov 2021 10:10:19 +0100
Subject: [PATCH] fix(Scripts/DB): UBRS Solakar / father flame (#8236)
---
.../rev_1633268017505597200.sql | 27 ++
.../BlackrockSpire/blackrock_spire.h | 11 +-
.../boss_solakar_flamewreath.cpp | 248 ++++++++++++++++++
.../instance_blackrock_spire.cpp | 119 ++++++++-
.../eastern_kingdoms_script_loader.cpp | 2 +
5 files changed, 398 insertions(+), 9 deletions(-)
create mode 100644 data/sql/updates/pending_db_world/rev_1633268017505597200.sql
create mode 100644 src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_solakar_flamewreath.cpp
diff --git a/data/sql/updates/pending_db_world/rev_1633268017505597200.sql b/data/sql/updates/pending_db_world/rev_1633268017505597200.sql
new file mode 100644
index 000000000..d64872cb0
--- /dev/null
+++ b/data/sql/updates/pending_db_world/rev_1633268017505597200.sql
@@ -0,0 +1,27 @@
+INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1633268017505597200');
+
+-- rookery guardians
+UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 10258;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 10258 AND `source_type` = 0 AND (`id` IN (0, 1, 2, 3));
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(10258, 0, 0, 0, 63, 0, 100, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 25, 500, 1, 0, 0, 0, 0, 0, 0, 'Rookery Guardian - On Just Created - Start Attacking'),
+(10258, 0, 1, 0, 0, 0, 100, 2, 10000, 12000, 10000, 15000, 0, 11, 15572, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rookery Guardian - In Combat - Cast \'Sunder Armor\' (Normal Dungeon)'),
+(10258, 0, 2, 0, 0, 0, 100, 2, 5000, 7000, 4000, 6000, 0, 11, 15580, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Rookery Guardian - In Combat - Cast \'Strike\' (Normal Dungeon)');
+
+-- rookery hatcher
+UPDATE `creature_template` SET `ScriptName` = 'npc_rookery_hatcher' WHERE `entry` = 10683;
+DELETE FROM `creature_text` WHERE `CreatureID` = 10683;
+INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `Comment`) VALUES
+(10683, 0, 0, 'Intruders are destroying our eggs! Stop!!', 14, 0, 0, 0, 5538, 0, 'UBRS - Solakar event');
+
+-- solakar
+UPDATE `creature_template` SET `ScriptName` = 'boss_solakar_flamewreath' WHERE `entry` = 10264;
+
+-- father flame
+UPDATE `gameobject_template` SET `ScriptName` = 'go_father_flame' WHERE `entry` = 175245;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 175245 AND `source_type` = 1 AND `id` = 0;
+
+-- partial cleanup for the eggs
+DELETE FROM `gameobject_template` WHERE `entry` = 175622;
+DELETE FROM `gameobject_template_addon` WHERE `entry` = 175622;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 175622;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h
index 335cda813..5fb2739c3 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h
@@ -49,7 +49,8 @@ enum DataTypes
DATA_HALL_RUNE_4 = 19,
DATA_HALL_RUNE_5 = 20,
DATA_HALL_RUNE_6 = 21,
- DATA_HALL_RUNE_7 = 22
+ DATA_HALL_RUNE_7 = 22,
+ DATA_SOLAKAR_FLAMEWREATH = 23
};
enum CreaturesIds
@@ -73,6 +74,12 @@ enum CreaturesIds
NPC_BLACKHAND_VETERAN = 9819,
NPC_BLACKHAND_INCARCERATOR = 10316,
NPC_LORD_VICTOR_NEFARIUS = 10162,
+
+ NPC_SOLAKAR = 10264,
+ NPC_ROOKERY_GUARDIAN = 10258,
+ NPC_ROOKERY_HATCHER = 10683,
+ NPC_ROOKERY_WHELP = 10161,
+
NPC_UROK_MAGUS = 10602,
NPC_UROK_ENFORCER = 10601,
NPC_FINKLE_EINHORN = 10776
@@ -91,7 +98,7 @@ enum AdditionalData
enum GameObjectsIds
{
- GO_WHELP_SPAWNER = 175622, // trap spawned by go id 175124
+ GO_ROOKERY_EGG = 175124,
// Doors
GO_EMBERSEER_IN = 175244, // First door to Pyroguard Emberseer
GO_DOORS = 175705, // Second door to Pyroguard Emberseer
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_solakar_flamewreath.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_solakar_flamewreath.cpp
new file mode 100644
index 000000000..9e5b57c81
--- /dev/null
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_solakar_flamewreath.cpp
@@ -0,0 +1,248 @@
+/*
+ * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "blackrock_spire.h"
+
+enum Spells
+{
+ SPELL_WAR_STOMP = 16727,
+ SPELL_HATCH_EGG = 15746
+};
+
+enum Timer
+{
+ TIMER_WAR_STOMP = 20000
+};
+
+constexpr float RANGE_SPELL_HATCH_EGG = 3.0f; // needed because the eggs seem to hatch if the mobs goes too close
+constexpr float RANGE_WHELP_CALL_HELP = 15.0f; // range for the hatchers to call nearby whelps after having summoned them.
+
+enum Says
+{
+ SAY_SUMMON = 0,
+};
+
+class npc_rookery_hatcher : public CreatureScript
+{
+public:
+ npc_rookery_hatcher() : CreatureScript("npc_rookery_hatcher") {}
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetBlackrockSpireAI(creature);
+ }
+
+ struct npc_rookery_hatcherAI : public CreatureAI
+ {
+ npc_rookery_hatcherAI(Creature* creature) : CreatureAI(creature) {}
+
+ EventMap events;
+ std::list nearbyEggs;
+ GameObject* targetEgg;
+ Position targetPosition;
+
+ void InitializeAI() override
+ {
+ CreatureAI::InitializeAI();
+ DoZoneInCombat(nullptr, 100.0f);
+ nearbyEggs.clear();
+ targetEgg = nullptr;
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ events.ScheduleEvent(SPELL_HATCH_EGG, 1000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ std::list nearbyEggs;
+ float tempDist = 20;
+ float minDist = 25;
+ std::list nearbyWhelps;
+
+ if (!UpdateVictim())
+ {
+ return;
+ }
+
+ GetCreatureListWithEntryInGrid(nearbyWhelps, me, NPC_ROOKERY_WHELP, RANGE_WHELP_CALL_HELP);
+ for (const auto& whelp : nearbyWhelps)
+ {
+ if (!whelp->IsInCombat())
+ {
+ whelp->SetInCombatWith(me->GetVictim());
+ whelp->AI()->AttackStart(me->GetVictim());
+ }
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case SPELL_HATCH_EGG:
+ if (!targetEgg) // no target, try to find one
+ {
+ minDist = 50;
+ tempDist = 50;
+ me->GetGameObjectListWithEntryInGrid(nearbyEggs, GO_ROOKERY_EGG, 40);
+ for (const auto& egg : nearbyEggs)
+ {
+ if (egg->isSpawned() && egg->getLootState() == GO_READY)
+ {
+ tempDist = me->GetDistance2d(egg);
+ if (tempDist < minDist)
+ {
+ minDist = tempDist;
+ targetEgg = egg;
+ }
+ }
+ }
+ }
+
+ if (targetEgg) //have a target, go to it and cast it
+ {
+ me->GetMotionMaster()->MovePoint(0, targetEgg->GetPosition());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // cast takes 1.5second, during which we don't have a target
+ if (targetEgg && targetEgg->getLootState() == GO_READY && me->GetDistance2d(targetEgg) < RANGE_SPELL_HATCH_EGG)
+ {
+ me->StopMovingOnCurrentPos();
+ me->SetFacingToObject(targetEgg);
+ targetPosition = me->GetPosition();
+ DoCast(SPELL_HATCH_EGG);
+ targetEgg = nullptr;
+ events.ScheduleEvent(SPELL_HATCH_EGG, urand(6000, 8000));
+ }
+ else if (!me->HasUnitState(UNIT_STATE_CASTING) && !targetEgg)
+ {
+ if (Unit* victim = me->GetVictim())
+ {
+ AttackStart(victim);
+ }
+
+ if (me->GetDistance2d(me->GetVictim()) > me->GetMeleeReach())
+ {
+ me->GetMotionMaster()->MovePoint(0, me->GetVictim()->GetPosition()); // a bit hacky, but needed to start moving once we've summoned an egg
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ };
+};
+
+class boss_solakar_flamewreath : public CreatureScript
+{
+public:
+ boss_solakar_flamewreath() : CreatureScript("boss_solakar_flamewreath") { }
+
+ struct boss_solakar_flamewreathAI : public BossAI
+ {
+ boss_solakar_flamewreathAI(Creature* creature) : BossAI(creature, DATA_SOLAKAR_FLAMEWREATH) {}
+
+ uint32 resetTimer;
+
+ void Reset() override
+ {
+ _Reset();
+ resetTimer = 10000;
+ }
+
+ void InitializeAI() override
+ {
+ BossAI::InitializeAI();
+ Talk(SAY_SUMMON);
+ DoZoneInCombat(nullptr, 100.0f);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ events.ScheduleEvent(SPELL_WAR_STOMP, urand(17000, 20000));
+ resetTimer = 0;
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ instance->SetData(DATA_SOLAKAR_FLAMEWREATH, DONE);
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case SPELL_WAR_STOMP:
+ DoCastVictim(SPELL_WAR_STOMP);
+ events.ScheduleEvent(SPELL_WAR_STOMP, urand(17000, 20000));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ {
+ resetTimer -= diff;
+ if (resetTimer < diff)
+ {
+ instance->SetData(DATA_SOLAKAR_FLAMEWREATH, FAIL);
+ }
+ return;
+ }
+ resetTimer = 10000;
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ {
+ return;
+ }
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ ExecuteEvent(eventId);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetBlackrockSpireAI(creature);
+ }
+};
+
+void AddSC_boss_solakar_flamewreath()
+{
+ new boss_solakar_flamewreath();
+ new npc_rookery_hatcher();
+}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
index 844788307..b297a7a85 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
@@ -26,19 +26,34 @@
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
-//uint32 const DragonspireRunes[7] = { GO_HALL_RUNE_1, GO_HALL_RUNE_2, GO_HALL_RUNE_3, GO_HALL_RUNE_4, GO_HALL_RUNE_5, GO_HALL_RUNE_6, GO_HALL_RUNE_7 };
-
uint32 const DragonspireMobs[3] = { NPC_BLACKHAND_DREADWEAVER, NPC_BLACKHAND_SUMMONER, NPC_BLACKHAND_VETERAN };
enum EventIds
{
EVENT_DARGONSPIRE_ROOM_STORE = 1,
- EVENT_DARGONSPIRE_ROOM_CHECK = 2
+ EVENT_DARGONSPIRE_ROOM_CHECK = 2,
+
+ EVENT_SOLAKAR_WAVE = 3
};
+enum Timers
+{
+ TIMER_SOLAKAR_WAVE = 30000
+};
+
+enum SolakarWaves
+{
+ MAX_WAVE_COUNT = 5
+};
+
+Position SolakarPosLeft = Position(78.0f, -280.0f, 93.0f, 3.0f * M_PI / 2.0);
+Position SolakarPosRight = Position(84.0f, -280.0f, 93.0f, 3.0f * M_PI / 2.0);
+Position SolakarPosBoss = Position(80.0f, -280.0f, 93.0f, 3.0f * M_PI / 2.0);
+
enum Texts
{
- SAY_NEFARIUS_REND_WIPE = 11
+ SAY_NEFARIUS_REND_WIPE = 11,
+ SAY_SOLAKAR_FIRST_HATCHER = 0
};
class instance_blackrock_spire : public InstanceMapScript
@@ -48,9 +63,16 @@ public:
struct instance_blackrock_spireMapScript : public InstanceScript
{
+ uint32 CurrentSolakarWave = 0;
+ uint32 SolakarState = NOT_STARTED; // there should be a global instance encounter state, where is it?
+ std::vector SolakarSummons;
+
instance_blackrock_spireMapScript(InstanceMap* map) : InstanceScript(map)
{
SetBossNumber(EncounterCount);
+ CurrentSolakarWave = 0;
+ SolakarState = NOT_STARTED;
+ SolakarSummons.clear();
}
void CreatureLooted(Creature* creature, LootType loot) override
@@ -140,9 +162,6 @@ public:
{
switch (go->GetEntry())
{
- case GO_WHELP_SPAWNER:
- go->CastSpell(nullptr, SPELL_SUMMON_ROOKERY_WHELP);
- break;
case GO_EMBERSEER_IN:
go_emberseerin = go->GetGUID();
HandleGameObject(ObjectGuid::Empty, GetBossState(DATA_DRAGONSPIRE_ROOM) == DONE, go);
@@ -331,6 +350,29 @@ public:
Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_STORE, 1000);
}
break;
+ case DATA_SOLAKAR_FLAMEWREATH:
+ switch(data)
+ {
+ case IN_PROGRESS:
+ if (SolakarState == NOT_STARTED)
+ {
+ Events.ScheduleEvent(EVENT_SOLAKAR_WAVE, 500);
+ }
+ break;
+ case FAIL:
+ for (const auto& creature : SolakarSummons)
+ {
+ creature->RemoveFromWorld();
+ }
+ SolakarSummons.clear();
+ CurrentSolakarWave = 0;
+ SetData(DATA_SOLAKAR_FLAMEWREATH, NOT_STARTED);
+ break;
+ case DONE:
+ break;
+ }
+ SolakarState = data;
+ break;
case DATA_UROK_DOOMHOWL:
if (data == FAIL)
{
@@ -368,6 +410,38 @@ public:
}
}
+ uint32 GetData(uint32 type) const override
+ {
+ if (type == DATA_SOLAKAR_FLAMEWREATH)
+ {
+ return SolakarState;
+ }
+ else
+ {
+ return InstanceScript::GetData(type);
+ }
+ }
+
+ void SummonSolakarWave(uint8 number)
+ {
+ if (number < MAX_WAVE_COUNT)
+ {
+ SolakarSummons.push_back(instance->SummonCreature(NPC_ROOKERY_GUARDIAN, SolakarPosLeft));
+ SolakarSummons.push_back(instance->SummonCreature(NPC_ROOKERY_HATCHER, SolakarPosRight));
+ if (number == 0)
+ {
+ if (Creature* FirstHatcher = SolakarSummons.back()) // works because we spawned a hatcher second
+ {
+ FirstHatcher->AI()->Talk(SAY_SOLAKAR_FIRST_HATCHER);
+ }
+ }
+ }
+ else if (number == MAX_WAVE_COUNT)
+ {
+ SolakarSummons.push_back(instance->SummonCreature(NPC_SOLAKAR, SolakarPosBoss));
+ }
+ }
+
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
@@ -462,6 +536,14 @@ public:
if ((GetBossState(DATA_DRAGONSPIRE_ROOM) != DONE))
Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_CHECK, 3000);
break;
+ case EVENT_SOLAKAR_WAVE:
+ SummonSolakarWave(CurrentSolakarWave);
+ if (CurrentSolakarWave < MAX_WAVE_COUNT)
+ {
+ Events.ScheduleEvent(EVENT_SOLAKAR_WAVE, TIMER_SOLAKAR_WAVE);
+ CurrentSolakarWave++;
+ }
+ break;
default:
break;
}
@@ -704,9 +786,32 @@ public:
}
};
+class go_father_flame : public GameObjectScript
+{
+public:
+ go_father_flame() : GameObjectScript("go_father_flame") {}
+
+ void OnLootStateChanged(GameObject* go, uint32 state, Unit* /*unit*/) override
+ {
+ if (InstanceScript* instance = go->GetInstanceScript())
+ {
+ if (state == GO_ACTIVATED)
+ {
+ if (instance->GetData(DATA_SOLAKAR_FLAMEWREATH) == IN_PROGRESS || instance->GetData(DATA_SOLAKAR_FLAMEWREATH) == DONE)
+ {
+ return;
+ }
+
+ instance->SetData(DATA_SOLAKAR_FLAMEWREATH, IN_PROGRESS);
+ }
+ }
+ }
+};
+
void AddSC_instance_blackrock_spire()
{
new instance_blackrock_spire();
new at_dragonspire_hall();
new at_blackrock_stadium();
+ new go_father_flame();
}
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 5862cc2c1..f0fef63a5 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -43,6 +43,7 @@ void AddSC_boss_pyroguard_emberseer();
void AddSC_boss_gyth();
void AddSC_boss_rend_blackhand();
void AddSC_boss_urok_doomhowl();
+void AddSC_boss_solakar_flamewreath();
void AddSC_instance_blackrock_spire();
void AddSC_boss_razorgore(); //Blackwing lair
void AddSC_boss_vaelastrasz();
@@ -179,6 +180,7 @@ void AddEasternKingdomsScripts()
AddSC_boss_warmastervoone();
AddSC_boss_pyroguard_emberseer();
AddSC_boss_gyth();
+ AddSC_boss_solakar_flamewreath();
AddSC_boss_rend_blackhand();
AddSC_boss_urok_doomhowl();
AddSC_instance_blackrock_spire();