mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 10:26:28 +01:00
Scripts/UBRS: The Beast (#20751)
This commit is contained in:
34
sql/updates/world/3.3.5/2017_12_15_05_world_335.sql
Normal file
34
sql/updates/world/3.3.5/2017_12_15_05_world_335.sql
Normal file
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
@@ -75,7 +75,8 @@ enum BRSCreaturesIds
|
||||
NPC_BLACKHAND_VETERAN = 9819,
|
||||
NPC_BLACKHAND_INCARCERATOR = 10316,
|
||||
NPC_LORD_VICTOR_NEFARIUS = 10162,
|
||||
NPC_SCARSHIELD_INFILTRATOR = 10299
|
||||
NPC_SCARSHIELD_INFILTRATOR = 10299,
|
||||
NPC_FINKLE_EINHORN = 10776
|
||||
};
|
||||
|
||||
enum BRSAdditionalData
|
||||
@@ -85,7 +86,8 @@ enum BRSAdditionalData
|
||||
EVENT_PYROGUARD_EMBERSEER = 4884,
|
||||
AREATRIGGER = 1,
|
||||
AREATRIGGER_DRAGONSPIRE_HALL = 2046,
|
||||
AREATRIGGER_BLACKROCK_STADIUM = 2026
|
||||
AREATRIGGER_BLACKROCK_STADIUM = 2026,
|
||||
SAY_FINKLE_GANG = 0
|
||||
};
|
||||
|
||||
enum BRSGameObjectsIds
|
||||
@@ -128,4 +130,6 @@ inline AI* GetBlackrockSpireAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, BRSScriptName);
|
||||
}
|
||||
|
||||
#define RegisterBlackrockSpireCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetBlackrockSpireAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,90 +20,247 @@
|
||||
#include "blackrock_spire.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
enum Spells
|
||||
enum BeastSpells
|
||||
{
|
||||
SPELL_FLAMEBREAK = 16785,
|
||||
SPELL_IMMOLATE = 20294,
|
||||
SPELL_IMMOLATE = 15570,
|
||||
SPELL_TERRIFYINGROAR = 14100,
|
||||
SPELL_BERSERKER_CHARGE = 16636,
|
||||
SPELL_FIREBALL = 16788,
|
||||
SPELL_FIREBLAST = 16144,
|
||||
SPELL_FINKLE_IS_EINHORN = 16710,
|
||||
SPELL_SUICIDE = 7
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum BeastEvents
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
class boss_the_beast : public CreatureScript
|
||||
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 OrcDeathEvent : public BasicEvent
|
||||
{
|
||||
public:
|
||||
boss_the_beast() : CreatureScript("boss_the_beast") { }
|
||||
OrcDeathEvent(Creature* me) : _me(me) { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
|
||||
{
|
||||
return GetBlackrockSpireAI<boss_thebeastAI>(creature);
|
||||
_me->CastSpell(_me, SPELL_SUICIDE, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct boss_thebeastAI : public BossAI
|
||||
private:
|
||||
Creature* _me;
|
||||
};
|
||||
|
||||
struct boss_the_beast : public BossAI
|
||||
{
|
||||
boss_the_beast(Creature* creature) : BossAI(creature, DATA_THE_BEAST), _beastReached(false), _orcYelled(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
boss_thebeastAI(Creature* creature) : BossAI(creature, DATA_THE_BEAST) { }
|
||||
_Reset();
|
||||
if (_beastReached)
|
||||
me->GetMotionMaster()->MovePath(BEAST_MOVEMENT_ID, true);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
if (spell->Effects[i].IsEffect(SPELL_EFFECT_SKINNING))
|
||||
if (!me->IsAlive()) // can that even happen?
|
||||
DoCastAOE(SPELL_FINKLE_IS_EINHORN, true);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
_Reset();
|
||||
case DATA_BEAST_ROOM:
|
||||
{
|
||||
if (!_orcYelled)
|
||||
{
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
FindNearbyOrcs();
|
||||
|
||||
//! vector still empty, creatures are missing
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
return;
|
||||
|
||||
_orcYelled = true;
|
||||
|
||||
// we only need one orc to say the line
|
||||
if (Creature* orc = ObjectAccessor::GetCreature(*me, _nearbyOrcsGUIDs.front()))
|
||||
orc->AI()->Talk(SAY_BLACKHAND_DOOMED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_BEAST_REACHED:
|
||||
{
|
||||
if (!_beastReached)
|
||||
{
|
||||
_beastReached = true;
|
||||
me->GetMotionMaster()->MovePath(BEAST_MOVEMENT_ID, true);
|
||||
|
||||
if (_nearbyOrcsGUIDs.empty())
|
||||
FindNearbyOrcs();
|
||||
|
||||
for (ObjectGuid guid : _nearbyOrcsGUIDs)
|
||||
{
|
||||
if (Creature* orc = ObjectAccessor::GetCreature(*me, guid))
|
||||
{
|
||||
orc->GetMotionMaster()->MovePoint(1, orc->GetRandomPoint(OrcsRunawayPosition, 5.0f));
|
||||
orc->m_Events.AddEvent(new OrcDeathEvent(orc), me->m_Events.CalculateTime(6 * IN_MILLISECONDS));
|
||||
orc->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
}
|
||||
// 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 EnterCombat(Unit* /*who*/) override
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, Seconds(12));
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, Seconds(3));
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, Seconds(23));
|
||||
events.ScheduleEvent(EVENT_BERSERKER_CHARGE, Seconds(2));
|
||||
events.ScheduleEvent(EVENT_FIREBALL, Seconds(8), Seconds(21));
|
||||
events.ScheduleEvent(EVENT_FIREBLAST, Seconds(5), Seconds(8));
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
_EnterCombat();
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 12 * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_IMMOLATE, 3 * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_TERRIFYING_ROAR, 23 * IN_MILLISECONDS);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAME_BREAK:
|
||||
DoCastVictim(SPELL_FLAMEBREAK);
|
||||
events.Repeat(Seconds(10));
|
||||
break;
|
||||
case EVENT_IMMOLATE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.f, true))
|
||||
DoCast(target, SPELL_IMMOLATE);
|
||||
events.Repeat(Seconds(8));
|
||||
break;
|
||||
case EVENT_TERRIFYING_ROAR:
|
||||
DoCastVictim(SPELL_TERRIFYINGROAR);
|
||||
events.Repeat(Seconds(20));
|
||||
break;
|
||||
case EVENT_BERSERKER_CHARGE:
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 38.f, true))
|
||||
DoCast(target, SPELL_BERSERKER_CHARGE);
|
||||
events.Repeat(Seconds(15), Seconds(23));
|
||||
break;
|
||||
case EVENT_FIREBALL:
|
||||
DoCastVictim(SPELL_FIREBALL);
|
||||
events.Repeat(Seconds(8), Seconds(21));
|
||||
break;
|
||||
case EVENT_FIREBLAST:
|
||||
DoCastVictim(SPELL_FIREBLAST);
|
||||
events.Repeat(Seconds(5), Seconds(8));
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_FLAME_BREAK:
|
||||
DoCastVictim(SPELL_FLAMEBREAK);
|
||||
events.ScheduleEvent(EVENT_FLAME_BREAK, 10 * IN_MILLISECONDS);
|
||||
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;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void FindNearbyOrcs()
|
||||
{
|
||||
std::vector<Creature*> temp;
|
||||
me->GetCreatureListWithEntryInGrid(temp, NPC_BLACKHAND_ELITE, 50.0f);
|
||||
|
||||
for (Creature* creature : temp)
|
||||
_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, const AreaTriggerEntry* /*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, const AreaTriggerEntry* /*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();
|
||||
RegisterBlackrockSpireCreatureAI(boss_the_beast);
|
||||
new at_trigger_the_beast_movement();
|
||||
new at_the_beast_room();
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ public:
|
||||
case NPC_SCARSHIELD_INFILTRATOR:
|
||||
ScarshieldInfiltrator = creature->GetGUID();
|
||||
break;
|
||||
case NPC_FINKLE_EINHORN:
|
||||
creature->AI()->Talk(SAY_FINKLE_GANG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +286,7 @@ public:
|
||||
if (GetBossState(DATA_DRAGONSPIRE_ROOM) != DONE)
|
||||
Events.ScheduleEvent(EVENT_DARGONSPIRE_ROOM_STORE, 1000);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user