fix(Scripts/BlackrockSpire): implement pre-fight The Beast event. Source: TC (#8903)

- Closes #8312
- Closes #1878
This commit is contained in:
UltraNix
2021-11-05 00:34:42 +01:00
committed by GitHub
parent 70b0de4e1f
commit 122c93555b
4 changed files with 264 additions and 11 deletions

View File

@@ -0,0 +1,35 @@
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1635867595421095400');
SET @PATH:= 137969 * 10;
DELETE FROM `waypoint_data` WHERE `id` = @PATH;
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
(@PATH, 1 , 117.894, -560.9407, 107.8397, 0, 0, 1, 0, 100, 0),
(@PATH, 2 , 104.644, -557.4407, 108.0897, 0, 0, 1, 0, 100, 0),
(@PATH, 3 , 99.9641, -555.8882, 109.5087, 0, 0, 1, 0, 100, 0),
(@PATH, 4 , 96.7141, -554.3882, 110.7587, 0, 0, 1, 0, 100, 0),
(@PATH, 5 , 95.2141, -553.8882, 110.7587, 0, 0, 1, 0, 100, 0),
(@PATH, 6 , 91.2141, -552.1382, 110.7587, 0, 0, 1, 0, 100, 0),
(@PATH, 7 , 89.7141, -551.3882, 111.0087, 0, 0, 1, 0, 100, 0),
(@PATH, 8 , 87.9641, -550.6382, 111.0087, 0, 0, 1, 0, 100, 0),
(@PATH, 9 , 89.5555, -551.2523, 111.0189, 0, 0, 1, 0, 100, 0),
(@PATH, 10, 87.8055, -550.5023, 111.0189, 0, 0, 1, 0, 100, 0),
(@PATH, 11, 82.5555, -548.2523, 111.0189, 0, 0, 1, 0, 100, 0),
(@PATH, 12, 55.5090, -534.9372, 110.9415, 0, 0, 1, 0, 100, 0),
(@PATH, 13, 27.8879, -513.8772, 110.9468, 0, 0, 1, 0, 100, 0),
(@PATH, 14, 17.0559, -545.8477, 110.9305, 0, 0, 1, 0, 100, 0),
(@PATH, 15, 74.8466, -549.6145, 110.9279, 0, 0, 1, 0, 100, 0),
(@PATH, 16, 70.5093, -524.7200, 110.9333, 0, 0, 1, 0, 100, 0),
(@PATH, 17, 78.7893, -549.1487, 110.9274, 0, 0, 1, 0, 100, 0);
DELETE FROM `areatrigger_scripts` WHERE `entry` IN (2066, 2067);
INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
(2066, 'at_trigger_the_beast_movement'),
(2067, 'at_the_beast_room');
DELETE FROM `creature_text` WHERE `CreatureID` IN (10317, 10776);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(10317, 0, 0, "We're doomed!", 14, 0, 100, 0, 0, 0, 5622, 0, 'Blackhand elite'),
(10776, 0, 0, "Leaping leper gnomes! I've been stuck in there for months. Thanks, gang.", 12, 0, 100, 0, 0, 0, 6066, 0, 'Finkle Einhorn');
-- Its not perm spawn, its dynamic depending if the beast has been skinned or not
DELETE FROM `creature` WHERE `guid` = 42637;

View File

@@ -72,7 +72,8 @@ enum CreaturesIds
NPC_BLACKHAND_SUMMONER = 9818,
NPC_BLACKHAND_VETERAN = 9819,
NPC_BLACKHAND_INCARCERATOR = 10316,
NPC_LORD_VICTOR_NEFARIUS = 10162
NPC_LORD_VICTOR_NEFARIUS = 10162,
NPC_FINKLE_EINHORN = 10776
};
enum AdditionalData
@@ -82,7 +83,8 @@ enum AdditionalData
EVENT_PYROGUARD_EMBERSEER = 4884,
AREATRIGGER = 1,
AREATRIGGER_DRAGONSPIRE_HALL = 2046,
AREATRIGGER_BLACKROCK_STADIUM = 2026
AREATRIGGER_BLACKROCK_STADIUM = 2026,
SAY_FINKLE_GANG = 0
};
enum GameObjectsIds

View File

@@ -16,21 +16,75 @@
*/
#include "blackrock_spire.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
enum Spells
{
SPELL_FLAMEBREAK = 16785,
SPELL_IMMOLATE = 20294,
SPELL_IMMOLATE = 15570,
SPELL_TERRIFYINGROAR = 14100,
SPELL_BERSERKER_CHARGE = 16636,
SPELL_FIREBALL = 16788,
SPELL_FIREBLAST = 16144,
SPELL_SUICIDE = 8329
};
enum Events
{
EVENT_FLAME_BREAK = 1,
EVENT_IMMOLATE = 2,
EVENT_TERRIFYING_ROAR = 3,
EVENT_FLAME_BREAK = 1,
EVENT_IMMOLATE = 2,
EVENT_TERRIFYING_ROAR = 3,
EVENT_BERSERKER_CHARGE = 4,
EVENT_FIREBALL = 5,
EVENT_FIREBLAST = 6
};
enum BeastMisc
{
DATA_BEAST_REACHED = 1,
DATA_BEAST_ROOM = 2,
BEAST_MOVEMENT_ID = 1379690,
NPC_BLACKHAND_ELITE = 10317,
SAY_BLACKHAND_DOOMED = 0
};
Position const OrcsRunawayPosition = { 34.163567f, -536.852356f, 110.935196f, 6.056306f };
class OrcMoveEvent : public BasicEvent
{
public:
OrcMoveEvent(Creature* me) : _me(me) {}
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
{
_me->SetReactState(REACT_PASSIVE);
Position movePos;
_me->GetRandomPoint(OrcsRunawayPosition, 10.0f, movePos);
_me->GetMotionMaster()->MovePoint(1, movePos);
return true;
}
private:
Creature* _me;
};
class OrcDeathEvent : public BasicEvent
{
public:
OrcDeathEvent(Creature* me) : _me(me) { }
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
{
_me->CastSpell(_me, SPELL_SUICIDE, true);
return true;
}
private:
Creature* _me;
};
class boss_the_beast : public CreatureScript
@@ -45,35 +99,98 @@ public:
struct boss_thebeastAI : public BossAI
{
boss_thebeastAI(Creature* creature) : BossAI(creature, DATA_THE_BEAST) { }
boss_thebeastAI(Creature* creature) : BossAI(creature, DATA_THE_BEAST), _beastReached(false), _orcYelled(false) {}
void Reset() override
{
_Reset();
if (_beastReached)
{
me->GetMotionMaster()->MovePath(BEAST_MOVEMENT_ID, true);
}
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
events.ScheduleEvent(EVENT_FLAME_BREAK, 12 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_IMMOLATE, 3 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_FLAME_BREAK, 12 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_IMMOLATE, 3 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 23 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 2 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_FIREBALL, 8 * IN_MILLISECONDS, 21 * IN_MILLISECONDS);
events.ScheduleEvent(EVENT_FIREBLAST, 5 * IN_MILLISECONDS, 8 * IN_MILLISECONDS);
}
void JustDied(Unit* /*killer*/) override
void SetData(uint32 type, uint32 /*data*/) override
{
_JustDied();
switch (type)
{
case DATA_BEAST_ROOM:
{
if (!_orcYelled)
{
if (_nearbyOrcsGUIDs.empty())
{
FindNearbyOrcs();
}
//! vector still empty, creatures are missing
if (_nearbyOrcsGUIDs.empty())
{
return;
}
_orcYelled = true;
bool yelled = false;
for (ObjectGuid guid : _nearbyOrcsGUIDs)
{
if (Creature* orc = ObjectAccessor::GetCreature(*me, guid))
{
if (!yelled)
{
yelled = true;
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
}
orc->m_Events.AddEvent(new OrcMoveEvent(orc), me->m_Events.CalculateTime(3 * IN_MILLISECONDS));
orc->m_Events.AddEvent(new OrcDeathEvent(orc), me->m_Events.CalculateTime(9 * IN_MILLISECONDS));
}
}
}
break;
}
case DATA_BEAST_REACHED:
{
if (!_beastReached)
{
_beastReached = true;
me->GetMotionMaster()->MovePath(BEAST_MOVEMENT_ID, true);
// There is a chance player logged in between areatriggers (realm crash or restart)
// executing part of script which happens when player enters boss room
// otherwise we will see weird behaviour when someone steps on the previous areatrigger (dead mob yelling/moving)
SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
}
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
{
return;
}
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
while (uint32 eventId = events.ExecuteEvent())
{
@@ -85,21 +202,117 @@ public:
break;
case EVENT_IMMOLATE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(target, SPELL_IMMOLATE);
}
events.ScheduleEvent(EVENT_IMMOLATE, 8 * IN_MILLISECONDS);
break;
case EVENT_TERRIFYING_ROAR:
DoCastVictim(SPELL_TERRIFYINGROAR);
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 20 * IN_MILLISECONDS);
break;
case EVENT_BERSERKER_CHARGE:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 38.f, true))
{
DoCast(target, SPELL_BERSERKER_CHARGE);
}
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, 15 * IN_MILLISECONDS, 23 * IN_MILLISECONDS);
break;
case EVENT_FIREBALL:
DoCastVictim(SPELL_FIREBALL);
events.ScheduleEvent(EVENT_FIREBALL, 8 * IN_MILLISECONDS, 21 * IN_MILLISECONDS);
break;
case EVENT_FIREBLAST:
DoCastVictim(SPELL_FIREBLAST);
events.ScheduleEvent(EVENT_FIREBLAST, 5 * IN_MILLISECONDS, 8 * IN_MILLISECONDS);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
{
return;
}
}
DoMeleeAttackIfReady();
}
void FindNearbyOrcs()
{
std::list<Creature*> temp;
me->GetCreatureListWithEntryInGrid(temp, NPC_BLACKHAND_ELITE, 50.0f);
for (Creature* creature : temp)
{
if (creature->IsAlive())
{
_nearbyOrcsGUIDs.push_back(creature->GetGUID());
}
}
}
private:
bool _beastReached;
bool _orcYelled;
GuidVector _nearbyOrcsGUIDs;
};
};
//! The beast room areatrigger, this one triggers boss pathing. (AT Id 2066)
class at_trigger_the_beast_movement : public AreaTriggerScript
{
public:
at_trigger_the_beast_movement() : AreaTriggerScript("at_trigger_the_beast_movement") { }
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
{
if (player->IsGameMaster())
{
return false;
}
if (InstanceScript* instance = player->GetInstanceScript())
{
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
{
beast->AI()->SetData(DATA_BEAST_REACHED, DATA_BEAST_REACHED);
}
return true;
}
return false;
}
};
class at_the_beast_room : public AreaTriggerScript
{
public:
at_the_beast_room() : AreaTriggerScript("at_the_beast_room") { }
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
{
if (player->IsGameMaster())
{
return false;
}
if (InstanceScript* instance = player->GetInstanceScript())
{
if (Creature* beast = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THE_BEAST)))
{
beast->AI()->SetData(DATA_BEAST_ROOM, DATA_BEAST_ROOM);
}
return true;
}
return false;
}
};
void AddSC_boss_thebeast()
{
new boss_the_beast();
new at_trigger_the_beast_movement();
new at_the_beast_room();
}

View File

@@ -131,6 +131,9 @@ public:
if (GetBossState(DATA_GYTH) == DONE)
creature->DisappearAndDie();
break;
case NPC_FINKLE_EINHORN:
creature->AI()->Talk(SAY_FINKLE_GANG);
break;
}
}