Scripts/UBRS: The Beast (#20751)

This commit is contained in:
Riztazz
2017-12-16 01:58:45 +01:00
committed by Keader
parent 51c4196acf
commit 56b0433b6d
4 changed files with 259 additions and 60 deletions

View File

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

View File

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

View File

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