fix(Scripts/DB): UBRS Solakar / father flame (#8236)

This commit is contained in:
patou01
2021-11-07 10:10:19 +01:00
committed by GitHub
parent c0728f6e2d
commit cb07d1fc8a
5 changed files with 398 additions and 9 deletions

View File

@@ -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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<npc_rookery_hatcherAI>(creature);
}
struct npc_rookery_hatcherAI : public CreatureAI
{
npc_rookery_hatcherAI(Creature* creature) : CreatureAI(creature) {}
EventMap events;
std::list<GameObject*> 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<GameObject*> nearbyEggs;
float tempDist = 20;
float minDist = 25;
std::list<Creature*> 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<boss_solakar_flamewreathAI>(creature);
}
};
void AddSC_boss_solakar_flamewreath()
{
new boss_solakar_flamewreath();
new npc_rookery_hatcher();
}

View File

@@ -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<TempSummon*> 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();
}

View File

@@ -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();