mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 06:36:24 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -50,8 +50,9 @@ public:
|
||||
break;
|
||||
case GO_FACTORY_DOOR:
|
||||
gameobject->UpdateSaveToDb(true);
|
||||
// GoState (Door opened) is restored during GO creation, but we need to set LootState to prevent Lever from closing it again
|
||||
if (_encounters[TYPE_RHAHK_ZOR] == DONE)
|
||||
gameobject->SetGoState(GO_STATE_ACTIVE);
|
||||
gameobject->SetLootState(GO_ACTIVATED);
|
||||
break;
|
||||
case GO_IRON_CLAD_DOOR:
|
||||
gameobject->UpdateSaveToDb(true);
|
||||
|
||||
@@ -301,7 +301,7 @@ public:
|
||||
|
||||
void JustEngagedWith(Unit*)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_POISON, 8ms);
|
||||
events.ScheduleEvent(EVENT_POISON, 8s);
|
||||
|
||||
if (Creature* Venoxis = GetVenoxis())
|
||||
{
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
case EVENT_POISON:
|
||||
{
|
||||
me->CastSpell(me->GetVictim(), SPELL_POISON);
|
||||
events.ScheduleEvent(EVENT_POISON, 15ms);
|
||||
events.ScheduleEvent(EVENT_POISON, 15s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,6 +50,7 @@ enum Data
|
||||
ACTION_STOP_LK_FIGHT,
|
||||
ACTION_DELETE_ICE_WALL,
|
||||
DATA_WAVE_NUMBER,
|
||||
DATA_LK_BATTLE,// in progress
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
@@ -84,6 +85,7 @@ enum Creatures
|
||||
NPC_SKY_REAVER_KORM_BLACKSKAR = 30824,
|
||||
NPC_ALTAR_BUNNY = 37704,
|
||||
NPC_QUEL_DELAR = 37158,
|
||||
|
||||
};
|
||||
|
||||
enum GameObjects
|
||||
@@ -263,8 +265,14 @@ enum hMisc
|
||||
SPELL_HOR_START_QUEST_ALLY = 71351,
|
||||
SPELL_HOR_START_QUEST_HORDE = 71542,
|
||||
SPELL_SHADOWMOURNE_VISUAL = 72523,
|
||||
SPELL_ARCANE_CAST_VISUAL = 65633,
|
||||
SPELL_UTHER_DESPAWN = 70693, //Sniffed
|
||||
SPELL_WELL_OF_SOULS_VISUAL = 72630,
|
||||
SPELL_SUMMON_SOULS = 72711, //Sniffed Sylvanas
|
||||
|
||||
//Battle of LK
|
||||
SPELL_BLIDING_RETREAT = 70199, //Sniffed LK
|
||||
SPELL_SOUL_REAPER = 69410, //Sniffed LK
|
||||
SPELL_EVASION = 70190, //Sniffed Sylvanas
|
||||
|
||||
// Frostsworn General
|
||||
EVENT_ACTIVATE_REFLECTIONS = 1,
|
||||
@@ -310,18 +318,24 @@ const uint32 allowedCompositions[8][5] =
|
||||
{NPC_WAVE_MERCENARY, NPC_WAVE_MAGE, NPC_WAVE_PRIEST, NPC_WAVE_FOOTMAN, NPC_WAVE_FOOTMAN}
|
||||
};
|
||||
|
||||
const Position CenterPos = {5309.459473f, 2006.478516f, 711.595459f, 0.0f};
|
||||
const Position SpawnPos = {5262.540527f, 1949.693726f, 707.695007f, 0.808736f}; // Jaina/Sylvanas Beginning Position
|
||||
const Position LoralenFollowPos = {5283.234863f, 1990.946777f, 707.695679f, 0.929097f};
|
||||
const Position MoveThronePos = {5306.952148f, 1998.499023f, 709.341431f, 1.277278f}; // Jaina/Sylvanas walks to throne
|
||||
const Position UtherSpawnPos = {5308.310059f, 2003.857178f, 709.341431f, 4.650315f};
|
||||
const Position CenterPos = {5309.459473f, 2006.478516f, 711.595459f, 0.0f};
|
||||
const Position SpawnPos = {5263.22412f, 1950.95544f, 707.695862f, 0.808736f}; // Jaina/Sylvanas Beginning Position
|
||||
const Position LoralenMidleFollowPos = {5274.25634f, 1976.04760f, 707.694763f, 0.929097f}; // Sniffed
|
||||
const Position LoralenFollowPos = {5283.29296f, 1992.43078f, 707.694763f, 0.549238f}; // Sniffed
|
||||
const Position LoralenFollowLk1 = {5292.94921f, 2008.25451f, 707.695801f, 1.047967f}; // Sniffed
|
||||
const Position LoralenFollowLk2 = {5298.94335f, 2016.37097f, 707.695801f, 0.694538f}; // Sniffed
|
||||
const Position LoralenFollowLk3 = {5336.94044f, 2040.21814f, 707.695801f, 0.439284f}; // Sniffed
|
||||
const Position LoralenFollowLkFinal = {5361.96777f, 2065.68310f, 707.693848f, 0.831989f}; // Sniffed
|
||||
const Position LoralenDeadPos = {5369.71289f, 2083.6330f, 707.695129f, 0.188739f}; // Sniffed
|
||||
const Position MoveThronePos = {5306.98535f, 1998.10302f, 709.341187f, 1.277278f}; // Jaina/Sylvanas walks to throne
|
||||
const Position UtherSpawnPos = {5308.310059f, 2003.857178f, 709.341431f, 4.650315f}; // Uther starting position
|
||||
const Position LichKingSpawnPos = {5362.917480f, 2062.307129f, 707.695374f, 3.945812f};
|
||||
const Position LichKingMoveThronePos = {5312.080566f, 2009.172119f, 709.341431f, 3.973301f}; // Lich King walks to throne
|
||||
const Position LichKingMoveAwayPos = {5400.069824f, 2102.7131689f, 707.69525f, 0.843803f}; // Lich King walks away
|
||||
const Position LichKingMoveMidlelThronePos = {5333.48437f, 2032.02648f, 707.695679f, 3.973301f}; // Lich King moves and hits Uther [sniff]
|
||||
const Position LichKingMoveThronePos = {5312.79638f, 2010.07141f, 709.3942183f, 3.973301f}; // Lich King walks to throne [sniff]
|
||||
const Position LichKingMoveAwayPos = {5400.069824f, 2102.7131689f, 707.69525f, 0.843803f}; // Lich King walks away [sniff]
|
||||
const Position FalricMovePos = {5284.161133f, 2030.691650f, 709.319336f, 5.489386f};
|
||||
const Position MarwynMovePos = {5335.330078f, 1982.376221f, 709.319580f, 2.339942f};
|
||||
const Position SylvanasFightPos = {5557.508301f, 2263.920654f, 733.011230f, 3.624075f};
|
||||
const Position LeaderEscapePos = {5577.654785f, 2235.347412f, 733.011230f, 2.359576f};
|
||||
const Position LeaderEscapePos = {5576.80566f, 2235.55004f, 733.012268f, 2.782125f}; //Sniff
|
||||
const Position ShipMasterSummonPos = {5262.773926f, 1669.980103f, 715.000000f, 0.000000f};
|
||||
const Position WalkCaveInPos = {5267.594238f, 1678.750000f, 784.302856f, 1.041739f};
|
||||
const Position AllyPortalPos = {5205.015625f, 1605.680298f, 806.444458f, 0.884375f};
|
||||
|
||||
@@ -230,6 +230,7 @@ public:
|
||||
{
|
||||
case NPC_SYLVANAS_PART1:
|
||||
creature->SetVisible(false);
|
||||
creature->SetSpeed(MOVE_RUN, 1.1);
|
||||
NPC_LeaderIntroGUID = creature->GetGUID();
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART1);
|
||||
@@ -296,12 +297,8 @@ public:
|
||||
creature->SetVisible(false);
|
||||
if (!(EncounterMask & (1 << DATA_LK_INTRO)))
|
||||
{
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK2HTIGHT);
|
||||
if (TeamIdInInstance != TEAM_ALLIANCE)
|
||||
{
|
||||
creature->StopMoving();
|
||||
creature->SetFacingTo(creature->GetAngle(&SylvanasFightPos));
|
||||
}
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACK2HTIGHT); //the fight cannot be in the form of an emote, it is causing bugs
|
||||
creature->CastSpell(creature, SPELL_SOUL_REAPER, true);
|
||||
}
|
||||
else if (!(EncounterMask & (1 << DATA_LICH_KING)))
|
||||
creature->AddAura(TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, creature);
|
||||
@@ -316,22 +313,20 @@ public:
|
||||
if (!creature->IsAlive())
|
||||
creature->Respawn();
|
||||
NPC_LeaderGUID = creature->GetGUID();
|
||||
creature->SetWalk(false);
|
||||
creature->SetSheath(SHEATH_STATE_MELEE);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART2);
|
||||
creature->SetWalk(false);
|
||||
creature->SetHealth(creature->GetMaxHealth() / 20);
|
||||
|
||||
if (!(EncounterMask & (1 << DATA_FROSTSWORN_GENERAL)))
|
||||
creature->SetVisible(false);
|
||||
if (!(EncounterMask & (1 << DATA_LK_INTRO)))
|
||||
{
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, TeamIdInInstance == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H);
|
||||
creature->SetSheath(SHEATH_STATE_MELEE);
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, TeamIdInInstance == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H); //the fight cannot be in the form of an emote, it is causing bugs.
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
|
||||
creature->CastSpell(creature, TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_BARRIER : SPELL_SYLVANAS_CLOAK_OF_DARKNESS, true);
|
||||
if (TeamIdInInstance != TEAM_ALLIANCE)
|
||||
{
|
||||
creature->UpdatePosition(SylvanasFightPos, true);
|
||||
creature->StopMovingOnCurrentPos();
|
||||
}
|
||||
}
|
||||
else if (!(EncounterMask & (1 << DATA_LICH_KING)))
|
||||
{
|
||||
@@ -346,6 +341,7 @@ public:
|
||||
creature->UpdatePosition(PathWaypoints[PATH_WP_COUNT - 1], true);
|
||||
creature->StopMovingOnCurrentPos();
|
||||
}
|
||||
creature->SetSheath(SHEATH_STATE_MELEE);
|
||||
creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
break;
|
||||
case NPC_ICE_WALL_TARGET:
|
||||
@@ -444,8 +440,13 @@ public:
|
||||
if (Creature* c = instance->GetCreature(NPC_FrostswornGeneralGUID))
|
||||
{
|
||||
c->SetVisible(true);
|
||||
c->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
c->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
if (Creature* c = instance->GetCreature(NPC_FrostswornGeneralGUID))
|
||||
{
|
||||
c->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE);
|
||||
}
|
||||
WaveNumber = 0;
|
||||
DoUpdateWorldState(WORLD_STATE_HOR_COUNTER, 0);
|
||||
|
||||
@@ -712,7 +713,6 @@ public:
|
||||
case GO_FRONT_DOOR:
|
||||
return GO_FrontDoorGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
@@ -772,7 +772,6 @@ public:
|
||||
++ur;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFinished5Waves)
|
||||
{
|
||||
for (; WaveNumber < 4; ++WaveNumber)
|
||||
@@ -860,9 +859,7 @@ public:
|
||||
num_to_activate = 3;
|
||||
else if (WaveNumber <= 4)
|
||||
num_to_activate = 4;
|
||||
|
||||
reqKillCount += num_to_activate;
|
||||
|
||||
for (uint8 i = 0; i < num_to_activate; ++i)
|
||||
{
|
||||
uint32 entry = chosenComposition[WaveNumber - (WaveNumber > 5 ? 2 : 1)][i];
|
||||
@@ -910,7 +907,6 @@ public:
|
||||
c->StopMovingOnCurrentPos();
|
||||
}
|
||||
memset(&TrashActive, 0, sizeof(TrashActive));
|
||||
|
||||
if (Creature* falric = instance->GetCreature(NPC_FalricGUID))
|
||||
falric->AI()->EnterEvadeMode();
|
||||
if (Creature* marwyn = instance->GetCreature(NPC_MarwynGUID))
|
||||
@@ -1014,7 +1010,6 @@ public:
|
||||
if (Aura* a = pMarwyn->AddAura(SPELL_SHADOWMOURNE_VISUAL, pMarwyn))
|
||||
a->SetDuration(8000);
|
||||
}
|
||||
|
||||
pMarwyn->AI()->Talk(EMOTE_MARWYN_INTRO_SPIRIT);
|
||||
}
|
||||
++ResumeFirstEventStep;
|
||||
@@ -1035,7 +1030,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetData(ACTION_SHOW_TRASH, 1);
|
||||
ResumeFirstEventStep = 0;
|
||||
ResumeFirstEventTimer = 0;
|
||||
@@ -1057,7 +1051,6 @@ public:
|
||||
else
|
||||
ResumeFirstEventTimer -= diff;
|
||||
}
|
||||
|
||||
if (outroStep)
|
||||
{
|
||||
if (outroTimer <= diff)
|
||||
@@ -1153,7 +1146,6 @@ public:
|
||||
if (StairsPos[index][i].GetPositionX())
|
||||
if (GameObject* go = leader->SummonGameObject(TeamIdInInstance == TEAM_ALLIANCE ? GO_STAIRS_ALLIANCE : GO_STAIRS_HORDE, StairsPos[index][i].GetPositionX(), StairsPos[index][i].GetPositionY(), StairsPos[index][i].GetPositionZ(), StairsPos[index][i].GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400, false))
|
||||
go->SetGameObjectFlag(GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE);
|
||||
|
||||
//Position pos = TeamIdInInstance == TEAM_ALLIANCE ? AllyPortalPos : HordePortalPos;
|
||||
//leader->SummonGameObject(GO_PORTAL_TO_DALARAN, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400);
|
||||
//pos = TeamIdInInstance == TEAM_ALLIANCE ? AllyChestPos : HordeChestPos;
|
||||
@@ -1169,6 +1161,7 @@ public:
|
||||
{
|
||||
c->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
c->GetMotionMaster()->MovePoint(0, WalkCaveInPos);
|
||||
c->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); // need gossip ID 10931
|
||||
}
|
||||
++outroStep;
|
||||
outroTimer = 6000;
|
||||
|
||||
@@ -1184,6 +1184,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_violet_hold_defense_system : public ScriptedAI
|
||||
{
|
||||
npc_violet_hold_defense_system(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
DoCast(RAND(SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT, SPELL_DEFENSE_SYSTEM_VISUAL));
|
||||
events.ScheduleEvent(EVENT_ARCANE_LIGHTNING, 4s);
|
||||
events.ScheduleEvent(EVENT_ARCANE_LIGHTNING_INSTAKILL, 4s);
|
||||
me->DespawnOrUnsummon(7s, 0s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_ARCANE_LIGHTNING:
|
||||
DoCastAOE(RAND(SPELL_ARCANE_LIGHTNING, SPELL_ARCANE_LIGHTNING_VISUAL));
|
||||
events.RepeatEvent(2000);
|
||||
break;
|
||||
case EVENT_ARCANE_LIGHTNING_INSTAKILL:
|
||||
DoCastAOE(SPELL_ARCANE_LIGHTNING_INSTAKILL);
|
||||
events.RepeatEvent(1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_violet_hold()
|
||||
{
|
||||
new go_vh_activation_crystal();
|
||||
@@ -1201,4 +1231,5 @@ void AddSC_violet_hold()
|
||||
new npc_azure_stalker();
|
||||
|
||||
new spell_destroy_door_seal();
|
||||
RegisterCreatureAI(npc_violet_hold_defense_system);
|
||||
}
|
||||
|
||||
@@ -98,13 +98,16 @@ enum VHWorldStates
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CONTROL_CRYSTAL_ACTIVATION = 57804,
|
||||
SPELL_ARCANE_LIGHTNING = 57912,
|
||||
SPELL_ARCANE_LIGHTNING_VISUAL = 57930,
|
||||
SPELL_PORTAL_CHANNEL = 58012,
|
||||
SPELL_DESTROY_DOOR_SEAL = 58040,
|
||||
SPELL_CYANIGOSA_TRANSFORM = 58668,
|
||||
SPELL_CYANIGOSA_BLUE_AURA = 45870,
|
||||
SPELL_CONTROL_CRYSTAL_ACTIVATION = 57804,
|
||||
SPELL_DEFENSE_SYSTEM_SPAWN_EFFECT = 57886,
|
||||
SPELL_DEFENSE_SYSTEM_VISUAL = 57887,
|
||||
SPELL_ARCANE_LIGHTNING = 57912,
|
||||
SPELL_ARCANE_LIGHTNING_VISUAL = 57930,
|
||||
SPELL_ARCANE_LIGHTNING_INSTAKILL = 58152,
|
||||
SPELL_PORTAL_CHANNEL = 58012,
|
||||
SPELL_DESTROY_DOOR_SEAL = 58040,
|
||||
SPELL_CYANIGOSA_TRANSFORM = 58668,
|
||||
SPELL_CYANIGOSA_BLUE_AURA = 45870
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -117,6 +120,10 @@ enum Events
|
||||
EVENT_SUMMON_PORTAL,
|
||||
EVENT_CYANIGOSSA_TRANSFORM,
|
||||
EVENT_CYANIGOSA_ATTACK,
|
||||
|
||||
// Event defense system
|
||||
EVENT_ARCANE_LIGHTNING,
|
||||
EVENT_ARCANE_LIGHTNING_INSTAKILL
|
||||
};
|
||||
|
||||
enum Data
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 "mana_tombs.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_EARTHQUAKE = 33919,
|
||||
SPELL_CRYSTAL_PRISON = 32361,
|
||||
SPELL_ARCING_SMASH_N = 8374,
|
||||
SPELL_ARCING_SMASH_H = 38761
|
||||
};
|
||||
|
||||
struct boss_tavarok : public BossAI
|
||||
{
|
||||
boss_tavarok(Creature* creature) : BossAI(creature, DATA_TAVAROK)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
scheduler.Schedule(10s, 14200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_EARTHQUAKE);
|
||||
context.Repeat(20s, 31s);
|
||||
}).Schedule(12s, 22s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_CRYSTAL_PRISON);
|
||||
context.Repeat(15s, 22s);
|
||||
}).Schedule(5900ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(DUNGEON_MODE(SPELL_ARCING_SMASH_N, SPELL_ARCING_SMASH_H));
|
||||
context.Repeat(8s, 12s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_tavarok()
|
||||
{
|
||||
RegisterManaTombsCreatureAI(boss_tavarok);
|
||||
}
|
||||
@@ -40,4 +40,6 @@ inline AI* GetManaTombsAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, MTScriptName);
|
||||
}
|
||||
|
||||
#define RegisterManaTombsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetManaTombsAI)
|
||||
|
||||
#endif // MANA_TOMBS_H_
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 "sethekk_halls.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_FLAME_SHOCK_N = 15039,
|
||||
SPELL_FLAME_SHOCK_H = 15616,
|
||||
SPELL_ARCANE_SHOCK_N = 33534,
|
||||
SPELL_ARCANE_SHOCK_H = 38135,
|
||||
SPELL_FROST_SHOCK_N = 12548,
|
||||
SPELL_FROST_SHOCK_H = 21401,
|
||||
SPELL_SHADOW_SHOCK_N = 33620,
|
||||
SPELL_SHADOW_SHOCK_H = 38137,
|
||||
SPELL_CHAIN_LIGHTNING_N = 15659,
|
||||
SPELL_CHAIN_LIGHTNING_H = 15305,
|
||||
SPELL_SUMMON_ARC_ELE = 33538,
|
||||
SPELL_SUMMON_FIRE_ELE = 33537,
|
||||
SPELL_SUMMON_FROST_ELE = 33539,
|
||||
SPELL_SUMMON_SHADOW_ELE = 33540
|
||||
};
|
||||
|
||||
enum Text
|
||||
{
|
||||
SAY_SUMMON = 0,
|
||||
SAY_AGGRO = 1,
|
||||
SAY_SLAY = 2,
|
||||
SAY_DEATH = 3
|
||||
};
|
||||
|
||||
struct boss_darkweaver_syth : public BossAI
|
||||
{
|
||||
boss_darkweaver_syth(Creature* creature) : BossAI(creature, DATA_DARKWEAVER_SYTH)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
ScheduleHealthCheckEvent({90, 50, 10}, [&] {
|
||||
Talk(SAY_SUMMON);
|
||||
DoCastSelf(SPELL_SUMMON_ARC_ELE);
|
||||
DoCastSelf(SPELL_SUMMON_FIRE_ELE);
|
||||
DoCastSelf(SPELL_SUMMON_FROST_ELE);
|
||||
DoCastSelf(SPELL_SUMMON_SHADOW_ELE);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
scheduler.Schedule(2s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_FLAME_SHOCK_N, SPELL_FLAME_SHOCK_H));
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(4s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_ARCANE_SHOCK_N, SPELL_ARCANE_SHOCK_H));
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_FROST_SHOCK_N, SPELL_FROST_SHOCK_H));
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_SHADOW_SHOCK_N, SPELL_SHADOW_SHOCK_H));
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(DUNGEON_MODE(SPELL_CHAIN_LIGHTNING_N, SPELL_CHAIN_LIGHTNING_H));
|
||||
context.Repeat(10s, 15s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_darkweaver_syth()
|
||||
{
|
||||
RegisterSethekkHallsCreatureAI(boss_darkweaver_syth);
|
||||
}
|
||||
@@ -28,8 +28,7 @@ enum GrandmasterVorpil
|
||||
SAY_SLAY = 3,
|
||||
SAY_DEATH = 4,
|
||||
|
||||
SPELL_RAIN_OF_FIRE_N = 33617,
|
||||
SPELL_RAIN_OF_FIRE_H = 39363,
|
||||
SPELL_RAIN_OF_FIRE = 33617,
|
||||
|
||||
SPELL_DRAW_SHADOWS = 33563,
|
||||
SPELL_SHADOWBOLT_VOLLEY = 33841,
|
||||
@@ -38,8 +37,7 @@ enum GrandmasterVorpil
|
||||
NPC_VOID_TRAVELER = 19226,
|
||||
SPELL_SACRIFICE = 33587,
|
||||
SPELL_SHADOW_NOVA = 33846,
|
||||
SPELL_EMPOWERING_SHADOWS_N = 33783,
|
||||
SPELL_EMPOWERING_SHADOWS_H = 39364,
|
||||
SPELL_EMPOWERING_SHADOWS = 33783,
|
||||
|
||||
NPC_VOID_PORTAL = 19224,
|
||||
SPELL_VOID_PORTAL_VISUAL = 33569,
|
||||
@@ -155,22 +153,17 @@ struct boss_grandmaster_vorpil : public BossAI
|
||||
context.Repeat();
|
||||
}).Schedule(36400ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_DRAW_SHADOWS, true);
|
||||
DoCastAOE(SPELL_DRAW_SHADOWS, true);
|
||||
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (player->IsAlive() && !player->HasAura(SPELL_BANISH))
|
||||
{
|
||||
player->TeleportTo(me->GetMapId(), VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT);
|
||||
}
|
||||
});
|
||||
me->NearTeleportTo(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f);
|
||||
me->GetMotionMaster()->Clear();
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastSelf(DUNGEON_MODE(SPELL_RAIN_OF_FIRE_N, SPELL_RAIN_OF_FIRE_H));
|
||||
DoCastSelf(SPELL_RAIN_OF_FIRE);
|
||||
me->ResumeChasingVictim();
|
||||
});
|
||||
|
||||
me->NearTeleportTo(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f);
|
||||
context.Repeat(36400ms, 44950ms);
|
||||
}).Schedule(10900ms, [this](TaskContext context)
|
||||
{
|
||||
@@ -203,52 +196,59 @@ struct npc_voidtraveler : public ScriptedAI
|
||||
{
|
||||
npc_voidtraveler(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
ObjectGuid VorpilGUID;
|
||||
uint32 moveTimer;
|
||||
bool sacrificed;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
moveTimer = 1000;
|
||||
sacrificed = false;
|
||||
}
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
{
|
||||
if (Unit* vorpil = summon->GetSummonerUnit())
|
||||
{
|
||||
me->GetMotionMaster()->MoveFollow(vorpil, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32) override
|
||||
{
|
||||
VorpilGUID = guid;
|
||||
_scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
{
|
||||
if (Unit* vorpil = summon->GetSummonerUnit())
|
||||
{
|
||||
if (me->IsWithinMeleeRange(vorpil))
|
||||
{
|
||||
DoCastSelf(SPELL_SACRIFICE);
|
||||
_scheduler.Schedule(1200ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (TempSummon* summon = me->ToTempSummon())
|
||||
{
|
||||
if (Unit* vorpil = summon->GetSummonerUnit())
|
||||
{
|
||||
DoCastAOE(SPELL_SHADOW_NOVA, true);
|
||||
me->CastSpell(vorpil, SPELL_EMPOWERING_SHADOWS, true, nullptr, nullptr, vorpil->GetGUID());
|
||||
vorpil->ModifyHealth(int32(vorpil->CountPctFromMaxHealth(4)));
|
||||
}
|
||||
}
|
||||
|
||||
_scheduler.Schedule(100ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->KillSelf();
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Repeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
moveTimer += diff;
|
||||
if (moveTimer >= 1000)
|
||||
{
|
||||
moveTimer = 0;
|
||||
Creature* Vorpil = ObjectAccessor::GetCreature(*me, VorpilGUID);
|
||||
if (!Vorpil)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
me->GetMotionMaster()->MoveFollow(Vorpil, 0.0f, 0.0f);
|
||||
|
||||
if (sacrificed)
|
||||
{
|
||||
Vorpil->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS_N, SPELL_EMPOWERING_SHADOWS_H), Vorpil);
|
||||
Vorpil->ModifyHealth(int32(Vorpil->CountPctFromMaxHealth(4)));
|
||||
DoCastAOE(SPELL_SHADOW_NOVA, true);
|
||||
me->KillSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->IsWithinDist(Vorpil, 3.0f))
|
||||
{
|
||||
DoCastSelf(SPELL_SACRIFICE);
|
||||
sacrificed = true;
|
||||
moveTimer = 500;
|
||||
}
|
||||
}
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
void AddSC_boss_grandmaster_vorpil()
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 "the_slave_pens.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_LIGHTNING_BOLT = 35010,
|
||||
SPELL_HEALING_WARD = 34980,
|
||||
SPELL_EARTHGRAB_TOTEM = 31981,
|
||||
SPELL_STONESKIN_TOTEM = 31985,
|
||||
SPELL_NOVA_TOTEM = 31991
|
||||
};
|
||||
|
||||
enum Text
|
||||
{
|
||||
SAY_AGGRO = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_JUST_DIED = 3
|
||||
};
|
||||
|
||||
struct boss_mennu_the_betrayer : public BossAI
|
||||
{
|
||||
boss_mennu_the_betrayer(Creature* creature) : BossAI(creature, DATA_MENNU_THE_BETRAYER)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
ScheduleHealthCheckEvent(60, [&] {
|
||||
DoCastSelf(SPELL_HEALING_WARD);
|
||||
});
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summon->GetMotionMaster()->Clear();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
scheduler.Schedule(5s, 8s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_LIGHTNING_BOLT);
|
||||
context.Repeat(7s, 10s);
|
||||
}).Schedule(20s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_NOVA_TOTEM);
|
||||
context.Repeat(26s);
|
||||
}).Schedule(19200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_EARTHGRAB_TOTEM);
|
||||
context.Repeat(26s);
|
||||
}).Schedule(18s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_STONESKIN_TOTEM);
|
||||
context.Repeat(26s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_JUST_DIED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_mennu_the_betrayer()
|
||||
{
|
||||
RegisterTheSlavePensCreatureAI(boss_mennu_the_betrayer);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "the_slave_pens.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ACID_SPRAY = 38153,
|
||||
SPELL_CLEAVE = 40504,
|
||||
SPELL_POISON_BOLT_VOLLEY_N = 34780,
|
||||
SPELL_POISON_BOLT_VOLLEY_H = 39340,
|
||||
SPELL_UPPERCUT = 32055
|
||||
};
|
||||
|
||||
struct boss_quagmirran : public BossAI
|
||||
{
|
||||
boss_quagmirran(Creature* creature) : BossAI(creature, DATA_QUAGMIRRAN)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
scheduler.Schedule(9100ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_CLEAVE);
|
||||
context.Repeat(18800ms, 24800ms);
|
||||
}).Schedule(20300ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_UPPERCUT);
|
||||
context.Repeat(21800ms);
|
||||
}).Schedule(25200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_ACID_SPRAY);
|
||||
context.Repeat(25s);
|
||||
}).Schedule(31800ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(DUNGEON_MODE(SPELL_POISON_BOLT_VOLLEY_N, SPELL_POISON_BOLT_VOLLEY_H));
|
||||
context.Repeat(24400ms);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_quagmirran()
|
||||
{
|
||||
RegisterTheSlavePensCreatureAI(boss_quagmirran);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 "the_slave_pens.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_ENSNARING_MOSS = 31948,
|
||||
SPELL_FRENZY = 34970,
|
||||
SPELL_GRIEVOUS_WOUND_N = 31956,
|
||||
SPELL_GRIEVOUS_WOUND_H = 38801,
|
||||
SPELL_WATER_SPIT = 35008
|
||||
};
|
||||
|
||||
struct boss_rokmar_the_crackler : public BossAI
|
||||
{
|
||||
boss_rokmar_the_crackler(Creature* creature) : BossAI(creature, DATA_ROKMAR_THE_CRACKLER)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
ScheduleHealthCheckEvent(20, [&] {
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
|
||||
scheduler.Schedule(8s, [this] (TaskContext context)
|
||||
{
|
||||
DoCastVictim(DUNGEON_MODE(SPELL_GRIEVOUS_WOUND_N, SPELL_GRIEVOUS_WOUND_H));
|
||||
context.Repeat(20700ms);
|
||||
}).Schedule(15300ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_ENSNARING_MOSS);
|
||||
context.Repeat(26s);
|
||||
}).Schedule(10700ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_WATER_SPIT);
|
||||
context.Repeat(19s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_rokmar_the_crackler()
|
||||
{
|
||||
RegisterTheSlavePensCreatureAI(boss_rokmar_the_crackler);
|
||||
}
|
||||
@@ -27,10 +27,11 @@ uint32 const EncounterCount = 3;
|
||||
|
||||
enum SPDataTypes
|
||||
{
|
||||
DATA_MENNU_THE_BETRAYER = 1,
|
||||
DATA_ROKMAR_THE_CRACKLER = 2,
|
||||
DATA_QUAGMIRRAN = 3,
|
||||
DATA_AHUNE = 4,
|
||||
DATA_MENNU_THE_BETRAYER = 0,
|
||||
DATA_ROKMAR_THE_CRACKLER = 1,
|
||||
DATA_QUAGMIRRAN = 2,
|
||||
DATA_AHUNE = 3,
|
||||
MAX_ENCOUNTER = 4,
|
||||
DATA_AHUNE_BUNNY = 5,
|
||||
DATA_FROZEN_CORE = 6,
|
||||
DATA_FLAMECALLER_000 = 7,
|
||||
@@ -65,6 +66,8 @@ enum SPCreaturesIds
|
||||
NPC_SHAMAN_BEAM_BUNNY_002 = 25966,
|
||||
NPC_WHISP_DEST_BUNNY = 26120,
|
||||
NPC_WHISP_SOURCE_BUNNY = 26121,
|
||||
NPC_MENNU_THE_BETRAYER = 17941,
|
||||
NPC_ROKMAR_THE_CRACKLER = 17991,
|
||||
NPC_QUAGMIRRAN = 17942
|
||||
};
|
||||
|
||||
@@ -80,4 +83,6 @@ inline AI* GetTheSlavePensAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, SPScriptName);
|
||||
}
|
||||
|
||||
#define RegisterTheSlavePensCreatureAI(ai_name) RegisterCreatureAIWithFactory (ai_name, GetTheSlavePensAI)
|
||||
|
||||
#endif // SLAVE_PENS_H
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 "the_underbog.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SHOOT = 22907,
|
||||
SPELL_KNOCKAWAY = 18813,
|
||||
SPELL_RAPTOR_STRIKE = 31566,
|
||||
SPELL_MULTISHOT = 34974,
|
||||
SPELL_THROW_FREEZING_TRAP = 31946,
|
||||
SPELL_AIMED_SHOT = 31623,
|
||||
SPELL_HUNTERS_MARK = 31615
|
||||
};
|
||||
|
||||
enum Text
|
||||
{
|
||||
SAY_AGGRO = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_JUST_DIED = 3
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
RANGED_GROUP = 1,
|
||||
RANGE_CHECK = 2
|
||||
};
|
||||
|
||||
struct boss_swamplord_muselek : public BossAI
|
||||
{
|
||||
boss_swamplord_muselek(Creature* creature) : BossAI(creature, DATA_MUSELEK)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_canChase = true;
|
||||
}
|
||||
|
||||
void AttackStart(Unit* victim) override
|
||||
{
|
||||
if (victim && me->Attack(victim, true) && me->IsWithinMeleeRange(victim))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(victim);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_JUST_DIED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
bool CanShootVictim()
|
||||
{
|
||||
return me->GetVictim() && !me->IsWithinRange(me->GetVictim(), 10.0f) && me->IsWithinLOSInMap(me->GetVictim());
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_JustEngagedWith();
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
scheduler.Schedule(3s, [this](TaskContext context)
|
||||
{
|
||||
if (CanShootVictim())
|
||||
{
|
||||
me->LoadEquipment(1, true);
|
||||
DoCastVictim(SPELL_SHOOT);
|
||||
me->GetMotionMaster()->Clear();
|
||||
}
|
||||
else if (_canChase)
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
|
||||
context.Repeat();
|
||||
}).Schedule(15s, 30s, [this](TaskContext context)
|
||||
{
|
||||
if (me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
DoCastVictim(SPELL_KNOCKAWAY);
|
||||
}
|
||||
|
||||
context.Repeat();
|
||||
}).Schedule(10s, 15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_MULTISHOT);
|
||||
context.Repeat(20s, 30s);
|
||||
}).Schedule(30s, 40s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, false, true))
|
||||
{
|
||||
_markTarget = target->GetGUID();
|
||||
_canChase = false;
|
||||
DoCastVictim(SPELL_THROW_FREEZING_TRAP);
|
||||
|
||||
scheduler.Schedule(3s, [this, target](TaskContext)
|
||||
{
|
||||
if (target && me->GetVictim())
|
||||
{
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveBackwards(me->GetVictim(), 10.0f);
|
||||
}
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
if (Unit* marktarget = ObjectAccessor::GetUnit(*me, _markTarget))
|
||||
{
|
||||
DoCast(marktarget, SPELL_HUNTERS_MARK);
|
||||
}
|
||||
}, 3s);
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.Schedule(5s, [this, target](TaskContext)
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
if (Unit* marktarget = ObjectAccessor::GetUnit(*me, _markTarget))
|
||||
{
|
||||
scheduler.DelayAll(5s);
|
||||
DoCast(marktarget, SPELL_AIMED_SHOT);
|
||||
_canChase = true;
|
||||
}
|
||||
}, 3s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
context.Repeat(12s, 16s);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _markTarget;
|
||||
bool _canChase;
|
||||
};
|
||||
|
||||
void AddSC_boss_swamplord_muselek()
|
||||
{
|
||||
RegisterUnderbogCreatureAI(boss_swamplord_muselek);
|
||||
}
|
||||
@@ -16,9 +16,55 @@
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "the_underbog.h"
|
||||
|
||||
enum UnderbatSpells
|
||||
{
|
||||
SPELL_TENTACLE_LASH = 34171
|
||||
};
|
||||
|
||||
struct npc_underbat : public ScriptedAI
|
||||
{
|
||||
npc_underbat(Creature* c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler.Schedule(2200ms, 6900ms, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [&](Unit* u)
|
||||
{
|
||||
return u->IsAlive() && !u->IsPet() && me->IsWithinCombatRange(u, 20.f) && !me->HasInArc(M_PI, u);
|
||||
}))
|
||||
{
|
||||
DoCast(target, SPELL_TENTACLE_LASH);
|
||||
}
|
||||
context.Repeat(5700ms, 9700ms);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
class spell_fungal_decay : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_fungal_decay);
|
||||
@@ -72,6 +118,7 @@ class spell_allergies : public AuraScript
|
||||
|
||||
void AddSC_underbog()
|
||||
{
|
||||
RegisterUnderbogCreatureAI(npc_underbat);
|
||||
RegisterSpellScript(spell_fungal_decay);
|
||||
RegisterSpellScript(spell_allergies);
|
||||
}
|
||||
|
||||
@@ -29,41 +29,41 @@ constexpr uint32 EncounterCount = 4;
|
||||
|
||||
enum bloodFurnace
|
||||
{
|
||||
DATA_THE_MAKER = 0,
|
||||
DATA_BROGGOK = 1,
|
||||
DATA_KELIDAN = 2,
|
||||
MAX_ENCOUNTER = 3,
|
||||
DATA_THE_MAKER = 0,
|
||||
DATA_BROGGOK = 1,
|
||||
DATA_KELIDAN = 2,
|
||||
MAX_ENCOUNTER = 3,
|
||||
|
||||
DATA_DOOR1 = 10,
|
||||
DATA_DOOR2 = 11,
|
||||
DATA_DOOR3 = 12,
|
||||
DATA_BROGGOK_REAR_DOOR = 13,
|
||||
DATA_BROGGOK_LEVER = 14,
|
||||
DATA_DOOR6 = 15,
|
||||
DATA_DOOR1 = 10,
|
||||
DATA_DOOR2 = 11,
|
||||
DATA_DOOR3 = 12,
|
||||
DATA_BROGGOK_REAR_DOOR = 13,
|
||||
DATA_BROGGOK_LEVER = 14,
|
||||
DATA_DOOR6 = 15,
|
||||
|
||||
DATA_PRISON_CELL1 = 20,
|
||||
DATA_PRISON_CELL2 = 21,
|
||||
DATA_PRISON_CELL3 = 22,
|
||||
DATA_PRISON_CELL4 = 23,
|
||||
DATA_PRISON_CELL1 = 20,
|
||||
DATA_PRISON_CELL2 = 21,
|
||||
DATA_PRISON_CELL3 = 22,
|
||||
DATA_PRISON_CELL4 = 23,
|
||||
|
||||
ACTION_ACTIVATE_BROGGOK = 30,
|
||||
ACTION_PREPARE_BROGGOK = 31
|
||||
ACTION_ACTIVATE_BROGGOK = 30,
|
||||
ACTION_PREPARE_BROGGOK = 31
|
||||
};
|
||||
|
||||
enum bloodFurnaceNPC
|
||||
{
|
||||
NPC_THE_MAKER = 17381,
|
||||
NPC_BROGGOK = 17380,
|
||||
NPC_KELIDAN = 17377,
|
||||
NPC_NASCENT_FEL_ORC = 17398,
|
||||
NPC_CHANNELER = 17653
|
||||
NPC_THE_MAKER = 17381,
|
||||
NPC_BROGGOK = 17380,
|
||||
NPC_KELIDAN = 17377,
|
||||
NPC_NASCENT_FEL_ORC = 17398,
|
||||
NPC_CHANNELER = 17653
|
||||
};
|
||||
|
||||
enum BloodFurnaceGO
|
||||
{
|
||||
GO_BROGGOK_DOOR_FRONT = 181822,
|
||||
GO_BROGGOK_DOOR_REAR = 181819,
|
||||
GO_BROGGOK_LEVER = 181982
|
||||
GO_BROGGOK_DOOR_FRONT = 181822,
|
||||
GO_BROGGOK_DOOR_REAR = 181819,
|
||||
GO_BROGGOK_LEVER = 181982
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
|
||||
@@ -21,14 +21,17 @@
|
||||
#include "SpellScript.h"
|
||||
#include "blood_furnace.h"
|
||||
|
||||
enum eEnums
|
||||
enum Say
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_AGGRO = 0
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_SLIME_SPRAY = 30913,
|
||||
SPELL_POISON_CLOUD = 30916,
|
||||
SPELL_POISON_BOLT = 30917,
|
||||
SPELL_POISON = 30914,
|
||||
SPELL_POISON = 30914
|
||||
};
|
||||
|
||||
struct boss_broggok : public BossAI
|
||||
@@ -52,7 +55,6 @@ struct boss_broggok : public BossAI
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
summons.Summon(summoned);
|
||||
|
||||
summoned->SetFaction(FACTION_MONSTER_2);
|
||||
summoned->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
summoned->CastSpell(summoned, SPELL_POISON, true, 0, 0, me->GetGUID());
|
||||
@@ -80,7 +82,6 @@ struct boss_broggok : public BossAI
|
||||
DoCastSelf(SPELL_POISON_CLOUD);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
@@ -106,7 +107,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go->UseDoorOrButton();
|
||||
return false;
|
||||
}
|
||||
@@ -121,6 +121,7 @@ class spell_broggok_poison_cloud : public AuraScript
|
||||
{
|
||||
if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -142,6 +143,6 @@ class spell_broggok_poison_cloud : public AuraScript
|
||||
void AddSC_boss_broggok()
|
||||
{
|
||||
RegisterBloodFurnaceCreatureAI(boss_broggok);
|
||||
new go_broggok_lever();
|
||||
RegisterSpellScript(spell_broggok_poison_cloud);
|
||||
new go_broggok_lever();
|
||||
}
|
||||
|
||||
@@ -20,343 +20,160 @@
|
||||
#include "SpellAuras.h"
|
||||
#include "blood_furnace.h"
|
||||
|
||||
enum eKelidan
|
||||
enum Says
|
||||
{
|
||||
SAY_WAKE = 0,
|
||||
SAY_ADD_AGGRO = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_NOVA = 3,
|
||||
SAY_DIE = 4,
|
||||
SAY_DIE = 4
|
||||
};
|
||||
|
||||
// Keldian spells
|
||||
enum Spells
|
||||
{
|
||||
SPELL_CORRUPTION = 30938,
|
||||
SPELL_EVOCATION = 30935,
|
||||
SPELL_FIRE_NOVA = 33132,
|
||||
SPELL_SHADOW_BOLT_VOLLEY = 28599,
|
||||
SPELL_BURNING_NOVA = 30940,
|
||||
SPELL_VORTEX = 37370,
|
||||
|
||||
// Channelers spells
|
||||
SPELL_SHADOW_BOLT = 12739,
|
||||
SPELL_SHADOW_BOLT_H = 15472,
|
||||
SPELL_MARK_OF_SHADOW = 30937,
|
||||
SPELL_CHANNELING = 39123,
|
||||
|
||||
// Events
|
||||
EVENT_SPELL_VOLLEY = 1,
|
||||
EVENT_SPELL_CORRUPTION = 2,
|
||||
EVENT_SPELL_BURNING_NOVA = 3,
|
||||
EVENT_SPELL_FIRE_NOVA = 4,
|
||||
EVENT_SPELL_SHADOW_BOLT = 5,
|
||||
EVENT_SPELL_MARK = 6,
|
||||
|
||||
// Actions
|
||||
ACTION_CHANNELER_ENGAGED = 1,
|
||||
ACTION_CHANNELER_DIED = 2,
|
||||
SPELL_VORTEX = 37370
|
||||
};
|
||||
|
||||
const float ShadowmoonChannelers[5][4] =
|
||||
enum Misc
|
||||
{
|
||||
{302.0f, -87.0f, -24.4f, 0.157f},
|
||||
{321.0f, -63.5f, -24.6f, 4.887f},
|
||||
{346.0f, -74.5f, -24.6f, 3.595f},
|
||||
{344.0f, -103.5f, -24.5f, 2.356f},
|
||||
{316.0f, -109.0f, -24.6f, 1.257f}
|
||||
NPC_SHADOWMOON_CHANNELER = 17653
|
||||
};
|
||||
|
||||
class boss_kelidan_the_breaker : public CreatureScript
|
||||
enum Actions
|
||||
{
|
||||
public:
|
||||
boss_kelidan_the_breaker() : CreatureScript("boss_kelidan_the_breaker")
|
||||
ACTION_CHANNELER_DIED = 1,
|
||||
ACTION_CHANNELER_AGGRO = 2
|
||||
};
|
||||
|
||||
struct boss_kelidan_the_breaker : public BossAI
|
||||
{
|
||||
boss_kelidan_the_breaker(Creature* creature) : BossAI(creature, DATA_KELIDAN)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_kelidan_the_breakerAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_kelidan_the_breakerAI(Creature* creature) : ScriptedAI(creature)
|
||||
_Reset();
|
||||
ApplyImmunities(true);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCastSelf(SPELL_EVOCATION);
|
||||
if (instance)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
instance->SetData(DATA_KELIDAN, NOT_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
ObjectGuid channelers[5];
|
||||
uint32 checkTimer;
|
||||
bool addYell;
|
||||
|
||||
void Reset() override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_WAKE);
|
||||
_JustEngagedWith();
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
if (instance)
|
||||
{
|
||||
addYell = false;
|
||||
checkTimer = 5000;
|
||||
|
||||
events.Reset();
|
||||
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
|
||||
}
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY);
|
||||
context.Repeat(8s, 13s);
|
||||
}).Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_CORRUPTION);
|
||||
context.Repeat(30s, 50s);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_NOVA);
|
||||
ApplyImmunities(false);
|
||||
me->AddAura(SPELL_BURNING_NOVA, me);
|
||||
ApplyImmunities(true);
|
||||
SummonChannelers();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(true);
|
||||
if (instance)
|
||||
instance->SetData(DATA_KELIDAN, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_VOLLEY, 1000);
|
||||
events.ScheduleEvent(EVENT_SPELL_CORRUPTION, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BURNING_NOVA, 15000);
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Talk(SAY_WAKE);
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (urand(0, 1))
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_CHANNELER_ENGAGED)
|
||||
if (IsHeroic())
|
||||
{
|
||||
if (!addYell)
|
||||
{
|
||||
addYell = true;
|
||||
Talk(SAY_ADD_AGGRO);
|
||||
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
|
||||
if (channeler && !channeler->IsInCombat())
|
||||
channeler->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
DoCastAOE(SPELL_VORTEX);
|
||||
}
|
||||
else if (param == ACTION_CHANNELER_DIED)
|
||||
scheduler.DelayGroup(0, 6s);
|
||||
scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
|
||||
if (channeler && channeler->IsAlive())
|
||||
return;
|
||||
}
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetImmuneToAll(false);
|
||||
if (Unit* target = me->SelectNearestPlayer(100.0f))
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckChannelers()
|
||||
{
|
||||
if (addYell)
|
||||
{
|
||||
if (!SelectTargetFromPlayerList(100.0f))
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
SummonChannelers();
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
|
||||
if (channeler && !channeler->HasUnitState(UNIT_STATE_CASTING) && !channeler->IsInCombat())
|
||||
{
|
||||
Creature* target = ObjectAccessor::GetCreature(*me, channelers[(i + 2) % 5]);
|
||||
if (target)
|
||||
channeler->CastSpell(target, SPELL_CHANNELING, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SummonChannelers()
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
Creature* channeler = ObjectAccessor::GetCreature(*me, channelers[i]);
|
||||
if (channeler && channeler->isDead())
|
||||
{
|
||||
channeler->DespawnOrUnsummon(1);
|
||||
channeler = nullptr;
|
||||
}
|
||||
if (!channeler)
|
||||
channeler = me->SummonCreature(NPC_CHANNELER, ShadowmoonChannelers[i][0], ShadowmoonChannelers[i][1], ShadowmoonChannelers[i][2], ShadowmoonChannelers[i][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 300000);
|
||||
|
||||
channelers[i] = channeler ? channeler->GetGUID() : ObjectGuid::Empty;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
if (instance)
|
||||
{
|
||||
// Xinef: load grid with start doors
|
||||
me->GetMap()->LoadGrid(0, -111.0f);
|
||||
instance->SetData(DATA_KELIDAN, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyImmunities(bool apply)
|
||||
{
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISTRACT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_BANISH, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SHACKLE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DAZE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
checkTimer += diff;
|
||||
if (checkTimer >= 5000)
|
||||
{
|
||||
checkTimer = 0;
|
||||
CheckChannelers();
|
||||
if (!me->HasUnitState(UNIT_STATE_CASTING))
|
||||
me->CastSpell(me, SPELL_EVOCATION, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_VOLLEY:
|
||||
me->CastSpell(me, SPELL_SHADOW_BOLT_VOLLEY, false);
|
||||
events.RepeatEvent(urand(8000, 13000));
|
||||
break;
|
||||
case EVENT_SPELL_CORRUPTION:
|
||||
me->CastSpell(me, SPELL_CORRUPTION, false);
|
||||
events.RepeatEvent(urand(30000, 50000));
|
||||
break;
|
||||
case EVENT_SPELL_BURNING_NOVA:
|
||||
Talk(SAY_NOVA);
|
||||
|
||||
ApplyImmunities(false);
|
||||
me->AddAura(SPELL_BURNING_NOVA, me);
|
||||
ApplyImmunities(true);
|
||||
|
||||
if (IsHeroic())
|
||||
DoTeleportAll(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
|
||||
|
||||
events.DelayEvents(6000, 0);
|
||||
events.RepeatEvent(urand(25000, 32000));
|
||||
events.ScheduleEvent(EVENT_SPELL_FIRE_NOVA, 5000);
|
||||
break;
|
||||
case EVENT_SPELL_FIRE_NOVA:
|
||||
me->CastSpell(me, SPELL_FIRE_NOVA, true);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBloodFurnaceAI<boss_kelidan_the_breakerAI>(creature);
|
||||
DoCastSelf(SPELL_FIRE_NOVA, true);
|
||||
});
|
||||
context.Repeat(25s, 32s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class npc_shadowmoon_channeler : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_shadowmoon_channeler() : CreatureScript("npc_shadowmoon_channeler") {}
|
||||
|
||||
struct npc_shadowmoon_channelerAI : public ScriptedAI
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
npc_shadowmoon_channelerAI(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
EventMap events;
|
||||
|
||||
void Reset() override
|
||||
if (urand(0, 1))
|
||||
{
|
||||
events.Reset();
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
Creature* GetKelidan()
|
||||
{
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
return instance->GetCreature(DATA_KELIDAN);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
if (Creature* kelidan = GetKelidan())
|
||||
kelidan->AI()->DoAction(ACTION_CHANNELER_ENGAGED);
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOW_BOLT, urand(1500, 3500));
|
||||
events.ScheduleEvent(EVENT_SPELL_MARK, urand(5000, 6500));
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (Creature* kelidan = GetKelidan())
|
||||
kelidan->AI()->DoAction(ACTION_CHANNELER_DIED);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOW_BOLT:
|
||||
me->CastSpell(me->GetVictim(), IsHeroic() ? SPELL_SHADOW_BOLT_H : SPELL_SHADOW_BOLT, false);
|
||||
events.RepeatEvent(urand(6000, 7500));
|
||||
break;
|
||||
case EVENT_SPELL_MARK:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_MARK_OF_SHADOW, false);
|
||||
events.RepeatEvent(urand(16000, 17500));
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetBloodFurnaceAI<npc_shadowmoon_channelerAI>(creature);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_CHANNELER_DIED)
|
||||
{
|
||||
if (me->FindNearestCreature(NPC_SHADOWMOON_CHANNELER, 100.0f))
|
||||
{
|
||||
return;
|
||||
}
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
else if (param == ACTION_CHANNELER_AGGRO)
|
||||
{
|
||||
Talk(SAY_ADD_AGGRO);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
if (instance)
|
||||
{
|
||||
me->GetMap()->LoadGrid(0, -111.0f);
|
||||
instance->SetData(DATA_KELIDAN, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyImmunities(bool apply)
|
||||
{
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DISTRACT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SILENCE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_KNOCKOUT, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_BANISH, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SHACKLE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_TURN, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_HORROR, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_DAZE, apply);
|
||||
me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void AddSC_boss_kelidan_the_breaker()
|
||||
{
|
||||
new boss_kelidan_the_breaker();
|
||||
new npc_shadowmoon_channeler();
|
||||
RegisterBloodFurnaceCreatureAI(boss_kelidan_the_breaker);
|
||||
}
|
||||
|
||||
@@ -19,111 +19,87 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "blood_furnace.h"
|
||||
|
||||
enum eEnums
|
||||
enum Says
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_KILL = 1,
|
||||
SAY_DIE = 2,
|
||||
|
||||
SPELL_EXPLODING_BREAKER = 30925,
|
||||
SPELL_DOMINATION = 30923,
|
||||
|
||||
EVENT_SPELL_EXPLODING = 1,
|
||||
EVENT_SPELL_DOMINATION = 2
|
||||
SAY_AGGRO = 0,
|
||||
SAY_KILL = 1,
|
||||
SAY_DIE = 2
|
||||
};
|
||||
|
||||
class boss_the_maker : public CreatureScript
|
||||
enum Spells
|
||||
{
|
||||
public:
|
||||
boss_the_maker() : CreatureScript("boss_the_maker")
|
||||
SPELL_EXPLODING_BEAKER = 30925,
|
||||
SPELL_DOMINATION = 30923
|
||||
};
|
||||
|
||||
struct boss_the_maker : public BossAI
|
||||
{
|
||||
boss_the_maker(Creature* creature) : BossAI(creature, DATA_THE_MAKER)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
struct boss_the_makerAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_the_makerAI(Creature* creature) : ScriptedAI(creature)
|
||||
_Reset();
|
||||
if (instance)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
instance->SetData(DATA_THE_MAKER, NOT_STARTED);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_EXPLODING, 6000);
|
||||
events.ScheduleEvent(EVENT_SPELL_DOMINATION, 120000);
|
||||
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && urand(0, 1))
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
instance->SetData(DATA_THE_MAKER, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_EXPLODING:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_EXPLODING_BREAKER, false);
|
||||
events.RepeatEvent(urand(7000, 11000));
|
||||
break;
|
||||
case EVENT_SPELL_DOMINATION:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_DOMINATION, false);
|
||||
events.RepeatEvent(120000);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
return GetBloodFurnaceAI<boss_the_makerAI>(creature);
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
|
||||
scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_EXPLODING_BEAKER);
|
||||
context.Repeat(7s, 11s);
|
||||
}).Schedule(2min, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_DOMINATION);
|
||||
context.Repeat(2min);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && urand(0, 1))
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
instance->SetData(DATA_THE_MAKER, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_the_maker()
|
||||
{
|
||||
new boss_the_maker();
|
||||
RegisterBloodFurnaceCreatureAI(boss_the_maker);
|
||||
}
|
||||
|
||||
@@ -34,134 +34,114 @@ enum Spells
|
||||
SPELL_SHADOW_BOLT = 30686,
|
||||
SPELL_SUMMON_FIENDISH_HOUND = 30707,
|
||||
SPELL_TREACHEROUS_AURA = 30695,
|
||||
SPELL_DEMONIC_SHIELD = 31901,
|
||||
SPELL_DEMONIC_SHIELD = 31901
|
||||
};
|
||||
|
||||
enum Misc
|
||||
struct boss_omor_the_unscarred : public BossAI
|
||||
{
|
||||
EVENT_SUMMON1 = 1,
|
||||
EVENT_SUMMON2 = 2,
|
||||
EVENT_TREACHEROUS_AURA = 3,
|
||||
EVENT_DEMONIC_SHIELD = 4,
|
||||
EVENT_KILL_TALK = 5
|
||||
};
|
||||
|
||||
class boss_omor_the_unscarred : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_omor_the_unscarred() : CreatureScript("boss_omor_the_unscarred") { }
|
||||
|
||||
struct boss_omor_the_unscarredAI : public BossAI
|
||||
boss_omor_the_unscarred(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
|
||||
{
|
||||
boss_omor_the_unscarredAI(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
|
||||
SetCombatMovement(false);
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Talk(SAY_WIPE);
|
||||
BossAI::Reset();
|
||||
_targetGUID.Clear();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
events.ScheduleEvent(EVENT_SUMMON1, 10000);
|
||||
events.ScheduleEvent(EVENT_SUMMON2, 25000);
|
||||
events.ScheduleEvent(EVENT_TREACHEROUS_AURA, 6000);
|
||||
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 1000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SUMMON1:
|
||||
Talk(SAY_SUMMON);
|
||||
me->CastSpell(me, SPELL_SUMMON_FIENDISH_HOUND, false);
|
||||
break;
|
||||
case EVENT_SUMMON2:
|
||||
me->CastSpell(me, SPELL_SUMMON_FIENDISH_HOUND, false);
|
||||
events.ScheduleEvent(EVENT_SUMMON2, 15000);
|
||||
break;
|
||||
case EVENT_TREACHEROUS_AURA:
|
||||
if (roll_chance_i(33))
|
||||
Talk(SAY_CURSE);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_TREACHEROUS_AURA, false);
|
||||
events.ScheduleEvent(EVENT_TREACHEROUS_AURA, urand(12000, 18000));
|
||||
break;
|
||||
case EVENT_DEMONIC_SHIELD:
|
||||
if (me->HealthBelowPct(21))
|
||||
{
|
||||
me->CastSpell(me, SPELL_DEMONIC_SHIELD, false);
|
||||
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 15000);
|
||||
}
|
||||
else
|
||||
events.ScheduleEvent(EVENT_DEMONIC_SHIELD, 1000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->GetVictim() || !me->isAttackReady())
|
||||
return;
|
||||
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_BOLT, false);
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _targetGUID;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetHellfireRampartsAI<boss_omor_the_unscarredAI>(creature);
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Talk(SAY_WIPE);
|
||||
_Reset();
|
||||
_targetGUID.Clear();
|
||||
ScheduleHealthCheckEvent(21, [&]{
|
||||
DoCastSelf(SPELL_DEMONIC_SHIELD);
|
||||
scheduler.Schedule(15s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_DEMONIC_SHIELD);
|
||||
context.Repeat(15s);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
if (roll_chance_i(33))
|
||||
{
|
||||
Talk(SAY_CURSE);
|
||||
}
|
||||
DoCastRandomTarget(SPELL_TREACHEROUS_AURA);
|
||||
context.Repeat(12s, 18s);
|
||||
}).Schedule(10s, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
|
||||
}).Schedule(25s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_FIENDISH_HOUND);
|
||||
context.Repeat(15s);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if(!_hasSpoken)
|
||||
{
|
||||
_hasSpoken = true;
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
scheduler.Schedule(6s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_hasSpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
Talk(SAY_SUMMON);
|
||||
summons.Summon(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (!me->GetVictim() || !me->isAttackReady())
|
||||
return;
|
||||
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoCastVictim(SPELL_SHADOW_BOLT);
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _targetGUID;
|
||||
bool _hasSpoken;
|
||||
};
|
||||
|
||||
void AddSC_boss_omor_the_unscarred()
|
||||
{
|
||||
new boss_omor_the_unscarred();
|
||||
RegisterHellfireRampartsCreatureAI(boss_omor_the_unscarred);
|
||||
}
|
||||
|
||||
@@ -21,40 +21,35 @@
|
||||
|
||||
enum Says
|
||||
{
|
||||
SAY_INTRO = 0,
|
||||
SAY_WIPE = 0,
|
||||
SAY_AGGRO = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_DIE = 3,
|
||||
EMOTE_NAZAN = 0
|
||||
SAY_INTRO = 0,
|
||||
SAY_WIPE = 0,
|
||||
SAY_AGGRO = 1,
|
||||
SAY_KILL = 2,
|
||||
SAY_DIE = 3,
|
||||
EMOTE_NAZAN = 0
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_FIREBALL = 33793,
|
||||
SPELL_SUMMON_LIQUID_FIRE = 31706,
|
||||
SPELL_REVENGE = 19130,
|
||||
SPELL_REVENGE_H = 40392,
|
||||
SPELL_CALL_NAZAN = 30693,
|
||||
SPELL_BELLOWING_ROAR = 39427,
|
||||
SPELL_CONE_OF_FIRE = 30926
|
||||
SPELL_FIREBALL = 33793,
|
||||
SPELL_SUMMON_LIQUID_FIRE = 31706,
|
||||
SPELL_REVENGE = 19130,
|
||||
SPELL_CALL_NAZAN = 30693,
|
||||
SPELL_BELLOWING_ROAR = 39427,
|
||||
SPELL_CONE_OF_FIRE = 30926
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
ACTION_FLY_DOWN = 0,
|
||||
ACTION_FLY_DOWN = 0,
|
||||
POINT_MIDDLE = 0,
|
||||
POINT_FLIGHT = 1
|
||||
};
|
||||
|
||||
POINT_MIDDLE = 0,
|
||||
POINT_FLIGHT = 1,
|
||||
|
||||
EVENT_SPELL_REVENGE = 1,
|
||||
EVENT_KILL_TALK = 2,
|
||||
EVENT_AGGRO_TALK = 3,
|
||||
EVENT_SPELL_FIREBALL = 4,
|
||||
EVENT_SPELL_CONE_OF_FIRE = 5,
|
||||
EVENT_SPELL_BELLOWING_ROAR = 6,
|
||||
EVENT_CHANGE_POS = 7,
|
||||
EVENT_RESTORE_COMBAT = 8
|
||||
enum GroupPhase
|
||||
{
|
||||
GROUP_PHASE_1 = 0,
|
||||
GROUP_PHASE_2 = 1
|
||||
};
|
||||
|
||||
const Position NazanPos[3] =
|
||||
@@ -64,347 +59,302 @@ const Position NazanPos[3] =
|
||||
{-1373.84f, 1771.57f, 111.0f, 0.0f}
|
||||
};
|
||||
|
||||
class boss_vazruden_the_herald : public CreatureScript
|
||||
struct boss_vazruden_the_herald : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_vazruden_the_herald() : CreatureScript("boss_vazruden_the_herald") { }
|
||||
boss_vazruden_the_herald(Creature* creature) : BossAI(creature, DATA_VAZRUDEN) {}
|
||||
|
||||
struct boss_vazruden_the_heraldAI : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
boss_vazruden_the_heraldAI(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
|
||||
{
|
||||
}
|
||||
BossAI::Reset();
|
||||
me->SetVisible(true);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1372.56f, 1724.31f, 82.967f, 5.3058f);
|
||||
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1383.39f, 1711.82f, 82.7961f, 5.67232f);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
void AttackStart(Unit*) override {}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
|
||||
{
|
||||
BossAI::Reset();
|
||||
me->SetVisible(true);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
instance->SetBossState(DATA_VAZRUDEN, DONE);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
|
||||
{
|
||||
me->SetVisible(false);
|
||||
me->SummonCreature(NPC_VAZRUDEN, me->GetPositionX(), me->GetPositionY(), 81.2f, 5.46f);
|
||||
me->SummonCreature(NPC_NAZAN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 5.46f);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit*) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (summon->GetEntry() == NPC_HELLFIRE_SENTRY && summons.size() == 0)
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
|
||||
me->setActive(true);
|
||||
}
|
||||
else if (summons.size() == 0)
|
||||
{
|
||||
me->KillSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
|
||||
{
|
||||
BossAI::EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == 0 && data == 1)
|
||||
{
|
||||
summons.DoZoneInCombat(NPC_HELLFIRE_SENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (!me->IsVisible() && summons.size() == 0)
|
||||
{
|
||||
BossAI::EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct boss_nazan : public BossAI
|
||||
{
|
||||
boss_nazan(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetCanFly(true);
|
||||
me->SetDisableGravity(true);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
scheduler.CancelGroup(GROUP_PHASE_2);
|
||||
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
|
||||
scheduler.DelayAll(7s);
|
||||
context.Repeat(30s);
|
||||
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_FIREBALL);
|
||||
context.Repeat(4s, 6s);
|
||||
});
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->IsLevitating())
|
||||
{
|
||||
me->Attack(who, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_FLY_DOWN)
|
||||
{
|
||||
Talk(EMOTE_NAZAN);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1372.56f, 1724.31f, 82.967f, 5.3058f);
|
||||
me->SummonCreature(NPC_HELLFIRE_SENTRY, -1383.39f, 1711.82f, 82.7961f, 5.67232f);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 81.2f, false);
|
||||
}
|
||||
|
||||
void AttackStart(Unit*) override
|
||||
{
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
instance->SetBossState(DATA_VAZRUDEN, DONE);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
|
||||
{
|
||||
me->SetVisible(false);
|
||||
me->SummonCreature(NPC_VAZRUDEN, me->GetPositionX(), me->GetPositionY(), 81.2f, 5.46f);
|
||||
me->SummonCreature(NPC_NAZAN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 5.46f);
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit*) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (summon->GetEntry() == NPC_HELLFIRE_SENTRY && summons.size() == 0)
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
|
||||
me->setActive(true);
|
||||
}
|
||||
else if (summons.size() == 0)
|
||||
{
|
||||
me->KillSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summon) override
|
||||
{
|
||||
summons.Despawn(summon);
|
||||
if (summon->GetEntry() != NPC_HELLFIRE_SENTRY)
|
||||
BossAI::EnterEvadeMode();
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
if (type == 0 && data == 1)
|
||||
{
|
||||
summons.DoZoneInCombat(NPC_HELLFIRE_SENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
if (!me->IsVisible() && summons.size() == 0)
|
||||
BossAI::EnterEvadeMode();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetHellfireRampartsAI<boss_vazruden_the_heraldAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_nazan : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_nazan() : CreatureScript("boss_nazan") { }
|
||||
|
||||
struct boss_nazanAI : public ScriptedAI
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
boss_nazanAI(Creature* creature) : ScriptedAI(creature)
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
|
||||
{
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetCanFly(true);
|
||||
me->SetDisableGravity(true);
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_CHANGE_POS, 0);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 5000);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (me->IsLevitating())
|
||||
me->Attack(who, true);
|
||||
else
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_FLY_DOWN)
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
scheduler.CancelGroup(GROUP_PHASE_1);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
{
|
||||
Talk(EMOTE_NAZAN);
|
||||
events.Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 81.2f, false);
|
||||
DoCastVictim(SPELL_CONE_OF_FIRE);
|
||||
context.Repeat(12s);
|
||||
}).Schedule(6s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_FIREBALL);
|
||||
context.Repeat(4s, 6s);
|
||||
});
|
||||
if (IsHeroic())
|
||||
{
|
||||
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_BELLOWING_ROAR);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
|
||||
{
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
events.ScheduleEvent(EVENT_RESTORE_COMBAT, 1);
|
||||
events.ScheduleEvent(EVENT_SPELL_CONE_OF_FIRE, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL, 6000);
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_FIREBALL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_FIREBALL, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_FIREBALL, urand(4000, 6000));
|
||||
break;
|
||||
case EVENT_CHANGE_POS:
|
||||
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
|
||||
events.DelayEvents(7000);
|
||||
events.ScheduleEvent(EVENT_CHANGE_POS, 30000);
|
||||
break;
|
||||
case EVENT_RESTORE_COMBAT:
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
break;
|
||||
case EVENT_SPELL_CONE_OF_FIRE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CONE_OF_FIRE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_CONE_OF_FIRE, 12000);
|
||||
break;
|
||||
case EVENT_SPELL_BELLOWING_ROAR:
|
||||
me->CastSpell(me, SPELL_BELLOWING_ROAR, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_BELLOWING_ROAR, 30000);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->IsLevitating())
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetHellfireRampartsAI<boss_nazanAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_vazruden : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_vazruden() : CreatureScript("boss_vazruden") { }
|
||||
|
||||
struct boss_vazrudenAI : public ScriptedAI
|
||||
void UpdateAI(uint32 /*diff*/) override
|
||||
{
|
||||
boss_vazrudenAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
_nazanCalled = false;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
Talk(SAY_WIPE);
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_AGGRO_TALK, 5000);
|
||||
events.ScheduleEvent(EVENT_SPELL_REVENGE, 4000);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_nazanCalled && me->HealthBelowPctDamaged(35, damage))
|
||||
{
|
||||
_nazanCalled = true;
|
||||
me->CastSpell(me, SPELL_CALL_NAZAN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_AGGRO_TALK:
|
||||
Talk(SAY_AGGRO);
|
||||
break;
|
||||
case EVENT_SPELL_REVENGE:
|
||||
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_REVENGE, SPELL_REVENGE_H), false);
|
||||
events.ScheduleEvent(EVENT_SPELL_REVENGE, 6000);
|
||||
break;
|
||||
}
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (!me->IsLevitating())
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
EventMap events;
|
||||
bool _nazanCalled;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetHellfireRampartsAI<boss_vazrudenAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vazruden_fireball : public SpellScriptLoader
|
||||
struct boss_vazruden : public BossAI
|
||||
{
|
||||
public:
|
||||
spell_vazruden_fireball() : SpellScriptLoader("spell_vazruden_fireball") { }
|
||||
|
||||
class spell_vazruden_fireball_SpellScript : public SpellScript
|
||||
boss_vazruden(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
|
||||
{
|
||||
PrepareSpellScript(spell_vazruden_fireball_SpellScript);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->CastSpell(target, SPELL_SUMMON_LIQUID_FIRE, true);
|
||||
}
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vazruden_fireball_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Reset() override
|
||||
{
|
||||
return new spell_vazruden_fireball_SpellScript();
|
||||
_nazanCalled = false;
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||
{
|
||||
Talk(SAY_WIPE);
|
||||
me->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit*) override
|
||||
{
|
||||
scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
}).Schedule(4s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_REVENGE);
|
||||
context.Repeat(6s);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (!_hasSpoken)
|
||||
{
|
||||
_hasSpoken = true;
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
scheduler.Schedule(6s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_hasSpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
|
||||
{
|
||||
if (!_nazanCalled && me->HealthBelowPctDamaged(35, damage))
|
||||
{
|
||||
_nazanCalled = true;
|
||||
DoCastSelf(SPELL_CALL_NAZAN, true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit*) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _hasSpoken;
|
||||
bool _nazanCalled;
|
||||
};
|
||||
|
||||
class spell_vazruden_fireball : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_vazruden_fireball);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
target->CastSpell(target, SPELL_SUMMON_LIQUID_FIRE, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vazruden_fireball::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vazruden_call_nazan : public SpellScriptLoader
|
||||
class spell_vazruden_call_nazan : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_vazruden_call_nazan() : SpellScriptLoader("spell_vazruden_call_nazan") { }
|
||||
PrepareSpellScript(spell_vazruden_call_nazan);
|
||||
|
||||
class spell_vazruden_call_nazan_SpellScript : public SpellScript
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
PrepareSpellScript(spell_vazruden_call_nazan_SpellScript);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->GetAI()->DoAction(ACTION_FLY_DOWN);
|
||||
target->GetAI()->DoAction(ACTION_FLY_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vazruden_call_nazan_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_vazruden_call_nazan_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vazruden_call_nazan::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_vazruden_the_herald()
|
||||
{
|
||||
new boss_vazruden_the_herald();
|
||||
new boss_vazruden();
|
||||
new boss_nazan();
|
||||
new spell_vazruden_fireball();
|
||||
new spell_vazruden_call_nazan();
|
||||
RegisterHellfireRampartsCreatureAI(boss_vazruden_the_herald);
|
||||
RegisterHellfireRampartsCreatureAI(boss_vazruden);
|
||||
RegisterHellfireRampartsCreatureAI(boss_nazan);
|
||||
RegisterSpellScript(spell_vazruden_fireball);
|
||||
RegisterSpellScript(spell_vazruden_call_nazan);
|
||||
}
|
||||
|
||||
@@ -38,129 +38,113 @@ enum Spells
|
||||
|
||||
enum Misc
|
||||
{
|
||||
NPC_HELLFIRE_WATCHER = 17309,
|
||||
|
||||
EVENT_MORTAL_WOUND = 1,
|
||||
EVENT_SURGE = 2,
|
||||
EVENT_RETALIATION = 3,
|
||||
EVENT_KILL_TALK = 4,
|
||||
EVENT_CHECK_HEALTH = 5
|
||||
NPC_HELLFIRE_WATCHER = 17309
|
||||
};
|
||||
|
||||
class boss_watchkeeper_gargolmar : public CreatureScript
|
||||
struct boss_watchkeeper_gargolmar : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_watchkeeper_gargolmar() : CreatureScript("boss_watchkeeper_gargolmar") { }
|
||||
|
||||
struct boss_watchkeeper_gargolmarAI : public BossAI
|
||||
boss_watchkeeper_gargolmar(Creature* creature) : BossAI(creature, DATA_WATCHKEEPER_GARGOLMAR)
|
||||
{
|
||||
boss_watchkeeper_gargolmarAI(Creature* creature) : BossAI(creature, DATA_WATCHKEEPER_GARGOLMAR)
|
||||
_taunted = false;
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
_taunted = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, 5000);
|
||||
events.ScheduleEvent(EVENT_SURGE, 3000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
events.ScheduleEvent(EVENT_RETALIATION, 1000);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!_taunted)
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
_taunted = true;
|
||||
Talk(SAY_TAUNT);
|
||||
}
|
||||
}
|
||||
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
events.ScheduleEvent(EVENT_KILL_TALK, 6000);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_MORTAL_WOUND:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MORTAL_WOUND, false);
|
||||
events.ScheduleEvent(EVENT_MORTAL_WOUND, 8000);
|
||||
break;
|
||||
case EVENT_SURGE:
|
||||
Talk(SAY_SURGE);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
|
||||
me->CastSpell(target, SPELL_SURGE, false);
|
||||
events.ScheduleEvent(EVENT_SURGE, 11000);
|
||||
break;
|
||||
case EVENT_RETALIATION:
|
||||
if (me->HealthBelowPct(20))
|
||||
{
|
||||
me->CastSpell(me, SPELL_RETALIATION, false);
|
||||
events.ScheduleEvent(EVENT_RETALIATION, 30000);
|
||||
}
|
||||
else
|
||||
events.ScheduleEvent(EVENT_RETALIATION, 500);
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(50))
|
||||
{
|
||||
Talk(SAY_HEAL);
|
||||
std::list<Creature*> clist;
|
||||
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
|
||||
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
|
||||
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
|
||||
break;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 500);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _taunted;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetHellfireRampartsAI<boss_watchkeeper_gargolmarAI>(creature);
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
ScheduleHealthCheckEvent(50, [&]{
|
||||
Talk(SAY_HEAL);
|
||||
std::list<Creature*> clist;
|
||||
me->GetCreaturesWithEntryInRange(clist, 100.0f, NPC_HELLFIRE_WATCHER);
|
||||
for (std::list<Creature*>::const_iterator itr = clist.begin(); itr != clist.end(); ++itr)
|
||||
{
|
||||
(*itr)->AI()->SetData(NPC_HELLFIRE_WATCHER, 0);
|
||||
}
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(20, [&]{
|
||||
DoCastSelf(SPELL_RETALIATION);
|
||||
scheduler.Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_RETALIATION);
|
||||
context.Repeat(30s);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
scheduler.Schedule(5s, [this] (TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_MORTAL_WOUND);
|
||||
context.Repeat(8s);
|
||||
}).Schedule(3s, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_SURGE);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0))
|
||||
{
|
||||
me->CastSpell(target, SPELL_SURGE);
|
||||
}
|
||||
context.Repeat(11s);
|
||||
});
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (!_taunted)
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
_taunted = true;
|
||||
Talk(SAY_TAUNT);
|
||||
}
|
||||
}
|
||||
BossAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit*) override
|
||||
{
|
||||
if (!_hasSpoken)
|
||||
{
|
||||
_hasSpoken = true;
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
scheduler.Schedule(6s, [this](TaskContext /*context*/)
|
||||
{
|
||||
_hasSpoken = false;
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _taunted;
|
||||
bool _hasSpoken;
|
||||
|
||||
};
|
||||
|
||||
void AddSC_boss_watchkeeper_gargolmar()
|
||||
{
|
||||
new boss_watchkeeper_gargolmar();
|
||||
RegisterHellfireRampartsCreatureAI(boss_watchkeeper_gargolmar);
|
||||
}
|
||||
|
||||
@@ -52,4 +52,6 @@ inline AI* GetHellfireRampartsAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, HellfireRampartsScriptName);
|
||||
}
|
||||
|
||||
#define RegisterHellfireRampartsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetHellfireRampartsAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,292 +20,295 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "shattered_halls.h"
|
||||
|
||||
enum eGrandWarlockNethekurse
|
||||
enum Texts
|
||||
{
|
||||
SAY_INTRO = 0,
|
||||
SAY_PEON_ATTACKED = 1,
|
||||
SAY_PEON_DIES = 2,
|
||||
SAY_TAUNT = 3,
|
||||
SAY_AGGRO = 4,
|
||||
SAY_SLAY = 5,
|
||||
SAY_DIE = 6,
|
||||
SAY_SKIP_INTRO = 0,
|
||||
SAY_INTRO_2 = 1,
|
||||
SAY_PEON_ATTACKED = 2,
|
||||
SAY_PEON_DIES = 3,
|
||||
SAY_SHADOW_SEAR = 4,
|
||||
SAY_SHADOW_FISSURE = 5,
|
||||
SAY_DEATH_COIL = 6,
|
||||
SAY_SLAY = 7,
|
||||
SAY_DIE = 8
|
||||
};
|
||||
|
||||
SPELL_DEATH_COIL_N = 30500,
|
||||
SPELL_DEATH_COIL_H = 35954,
|
||||
SPELL_DARK_SPIN = 30502,
|
||||
SPELL_SHADOW_FISSURE = 30496,
|
||||
SPELL_SHADOW_CLEAVE_N = 30495,
|
||||
SPELL_SHADOW_SLAM_H = 35953,
|
||||
enum Spells
|
||||
{
|
||||
SPELL_DEATH_COIL = 30500,
|
||||
SPELL_DARK_SPIN = 30502,
|
||||
SPELL_SHADOW_FISSURE = 30496,
|
||||
SPELL_SHADOW_CLEAVE = 30495,
|
||||
|
||||
// Spells used exclusively in RP
|
||||
SPELL_SHADOW_SEAR = 30735,
|
||||
SPELL_DEATH_COIL = 30741,
|
||||
SPELL_SHADOW_SEAR = 30735,
|
||||
SPELL_DEATH_COIL_RP = 30741,
|
||||
SPELL_SHADOW_FISSURE_RP = 30745,
|
||||
SPELL_LESSER_SHADOW_FISSURE = 30744
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_INTRO = 1,
|
||||
EVENT_SPELL_DEATH_COIL = 2,
|
||||
EVENT_SPELL_SHADOW_FISSURE = 3,
|
||||
EVENT_SPELL_CLEAVE = 4,
|
||||
EVENT_CHECK_HEALTH = 5,
|
||||
EVENT_START_ATTACK = 6,
|
||||
EVENT_START_ATTACK = 2,
|
||||
|
||||
EVENT_STAGE_NONE = 0,
|
||||
EVENT_STAGE_INTRO = 1,
|
||||
EVENT_STAGE_TAUNT = 2,
|
||||
EVENT_STAGE_MAIN = 3,
|
||||
EVENT_STAGE_MAIN = 3
|
||||
};
|
||||
|
||||
enum Data
|
||||
{
|
||||
SETDATA_DATA = 1,
|
||||
SETDATA_PEON_AGGRO = 1,
|
||||
SETDATA_PEON_DEATH = 2
|
||||
};
|
||||
|
||||
// ########################################################
|
||||
// Grand Warlock Nethekurse
|
||||
// ########################################################
|
||||
|
||||
class boss_grand_warlock_nethekurse : public CreatureScript
|
||||
enum Groups
|
||||
{
|
||||
public:
|
||||
boss_grand_warlock_nethekurse() : CreatureScript("boss_grand_warlock_nethekurse") { }
|
||||
GROUP_RP = 0
|
||||
};
|
||||
|
||||
struct boss_grand_warlock_nethekurseAI : public BossAI
|
||||
enum Actions
|
||||
{
|
||||
ACTION_START_INTRO = 0,
|
||||
ACTION_CANCEL_INTRO = 1,
|
||||
ACTION_START_COMBAT = 2,
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_PEON = 17083
|
||||
};
|
||||
|
||||
struct PeonRoleplay
|
||||
{
|
||||
uint32 spellId;
|
||||
uint8 textId;
|
||||
};
|
||||
|
||||
PeonRoleplay PeonRoleplayData[3] =
|
||||
{
|
||||
{ SPELL_DEATH_COIL_RP, SAY_DEATH_COIL },
|
||||
{ SPELL_SHADOW_FISSURE_RP, SAY_SHADOW_FISSURE },
|
||||
{ SPELL_SHADOW_SEAR, SAY_SHADOW_SEAR }
|
||||
};
|
||||
|
||||
struct boss_grand_warlock_nethekurse : public BossAI
|
||||
{
|
||||
boss_grand_warlock_nethekurse(Creature* creature) : BossAI(creature, DATA_NETHEKURSE)
|
||||
{
|
||||
boss_grand_warlock_nethekurseAI(Creature* creature) : BossAI(creature, DATA_NETHEKURSE) { }
|
||||
|
||||
EventMap events2;
|
||||
void Reset() override
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
EventStage = EVENT_STAGE_NONE;
|
||||
_Reset();
|
||||
events2.Reset();
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
ScheduleHealthCheckEvent(25, [&] {
|
||||
DoCastSelf(SPELL_DARK_SPIN);
|
||||
});
|
||||
|
||||
instance->SetBossState(DATA_NETHEKURSE, NOT_STARTED);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
{
|
||||
if (data != SETDATA_DATA)
|
||||
return;
|
||||
|
||||
if (value == SETDATA_PEON_AGGRO && PeonEngagedCount <= 4)
|
||||
{
|
||||
Talk(SAY_PEON_ATTACKED);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
else if (value == SETDATA_PEON_DEATH && PeonKilledCount <= 4)
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
}
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->SetFacingTo(4.572762489318847656f);
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
{
|
||||
if (data != SETDATA_DATA)
|
||||
return;
|
||||
|
||||
switch (value)
|
||||
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
|
||||
{
|
||||
case SETDATA_PEON_AGGRO:
|
||||
if (PeonEngagedCount >= 4)
|
||||
return;
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
|
||||
me->GetMotionMaster()->Initialize();
|
||||
Talk(SAY_PEON_DIES);
|
||||
|
||||
if (EventStage < EVENT_STAGE_TAUNT)
|
||||
Talk(SAY_PEON_ATTACKED);
|
||||
break;
|
||||
case SETDATA_PEON_DEATH:
|
||||
if (PeonKilledCount >= 4)
|
||||
return;
|
||||
|
||||
if (EventStage < EVENT_STAGE_TAUNT)
|
||||
Talk(SAY_PEON_DIES);
|
||||
|
||||
if (++PeonKilledCount == 4)
|
||||
events2.ScheduleEvent(EVENT_START_ATTACK, 5000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (EventStage < EVENT_STAGE_MAIN)
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
{
|
||||
DoStartMovement(who);
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (me->IsWithinDistInMap(who, 30.0f))
|
||||
{
|
||||
if (who->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (EventStage == EVENT_STAGE_NONE && PeonKilledCount < 4)
|
||||
if (++PeonKilledCount == 4)
|
||||
{
|
||||
events2.ScheduleEvent(EVENT_INTRO, 90000);
|
||||
Talk(SAY_INTRO);
|
||||
EventStage = EVENT_STAGE_INTRO;
|
||||
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
else if (PeonKilledCount >= 4)
|
||||
{
|
||||
events2.ScheduleEvent(EVENT_START_ATTACK, 1000);
|
||||
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
if (EventStage < EVENT_STAGE_MAIN)
|
||||
return;
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
uint32 eventId = events2.ExecuteEvent();
|
||||
|
||||
if (EventStage < EVENT_STAGE_MAIN && instance->GetBossState(DATA_NETHEKURSE) == IN_PROGRESS)
|
||||
{
|
||||
if (eventId == EVENT_INTRO)
|
||||
{
|
||||
Talk(SAY_TAUNT);
|
||||
EventStage = EVENT_STAGE_TAUNT;
|
||||
me->CastSpell(me, SPELL_SHADOW_SEAR, false);
|
||||
}
|
||||
else if (eventId == EVENT_START_ATTACK)
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
EventStage = EVENT_STAGE_MAIN;
|
||||
if (Unit* target = me->SelectNearestPlayer(50.0f))
|
||||
Talk(SAY_INTRO_2);
|
||||
DoAction(ACTION_CANCEL_INTRO);
|
||||
if (Unit* target = me->SelectNearestPlayer(80.0f))
|
||||
{
|
||||
AttackStart(target);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_DEATH_COIL, 20000);
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOW_FISSURE, 8000);
|
||||
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
return;
|
||||
void IntroRP()
|
||||
{
|
||||
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext context)
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->SetFacingTo(4.572762489318847656f);
|
||||
|
||||
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
|
||||
{
|
||||
scheduler.Schedule(2500ms, GROUP_RP, [this](TaskContext /*context*/)
|
||||
{
|
||||
PeonRoleplay roleplayData = Acore::Containers::SelectRandomContainerElement(PeonRoleplayData);
|
||||
DoCast(me, roleplayData.spellId);
|
||||
Talk(roleplayData.textId);
|
||||
me->GetMotionMaster()->Initialize();
|
||||
});
|
||||
});
|
||||
context.Repeat(16400ms, 28500ms);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
if (who->GetEntry() == NPC_PEON)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_JustEngagedWith();
|
||||
DoAction(ACTION_CANCEL_INTRO);
|
||||
|
||||
scheduler.CancelAll();
|
||||
|
||||
scheduler.Schedule(12150ms, 19850ms, [this](TaskContext context)
|
||||
{
|
||||
if (me->HealthBelowPct(90))
|
||||
{
|
||||
DoCastRandomTarget(SPELL_DEATH_COIL, 0, 30.0f, true);
|
||||
}
|
||||
context.Repeat();
|
||||
}).Schedule(8100ms, 17300ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_SHADOW_FISSURE, 0, 60.0f, true);
|
||||
context.Repeat(8450ms, 9450ms);
|
||||
}).Schedule(10950ms, 21850ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_CLEAVE);
|
||||
context.Repeat(1200ms, 23900ms);
|
||||
});
|
||||
|
||||
if (PeonKilledCount < 4)
|
||||
{
|
||||
Talk(SAY_SKIP_INTRO);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_CANCEL_INTRO)
|
||||
{
|
||||
scheduler.CancelGroup(GROUP_RP);
|
||||
me->SetInCombatWithZone();
|
||||
return;
|
||||
}
|
||||
else if (action == ACTION_START_INTRO)
|
||||
{
|
||||
IntroRP();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
if (!me->HealthBelowPct(25))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 PeonEngagedCount = 0;
|
||||
uint8 PeonKilledCount = 0;
|
||||
};
|
||||
|
||||
class spell_tsh_shadow_bolt : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_tsh_shadow_bolt);
|
||||
|
||||
void SelectRandomPlayer(WorldObject*& target)
|
||||
{
|
||||
if (Creature* caster = GetCaster()->ToCreature())
|
||||
{
|
||||
if (Unit* randomTarget = caster->AI()->SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
|
||||
{
|
||||
target = randomTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_tsh_shadow_bolt::SelectRandomPlayer, EFFECT_0, TARGET_UNIT_TARGET_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_target_fissures : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_target_fissures);
|
||||
|
||||
void HandleEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_LESSER_SHADOW_FISSURE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_target_fissures::HandleEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class at_rp_nethekurse : public OnlyOnceAreaTriggerScript
|
||||
{
|
||||
public:
|
||||
at_rp_nethekurse() : OnlyOnceAreaTriggerScript("at_rp_nethekurse") { }
|
||||
|
||||
bool _OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||
{
|
||||
if (InstanceScript* instance = player->GetInstanceScript())
|
||||
{
|
||||
if (instance->GetBossState(DATA_NETHEKURSE) != DONE && instance->GetBossState(DATA_NETHEKURSE) != IN_PROGRESS)
|
||||
{
|
||||
if (Creature* nethekurse = instance->GetCreature(DATA_NETHEKURSE))
|
||||
{
|
||||
nethekurse->AI()->DoAction(ACTION_START_INTRO);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (EventStage < EVENT_STAGE_MAIN || me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOW_FISSURE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, SPELL_SHADOW_FISSURE, false);
|
||||
events.RescheduleEvent(EVENT_SPELL_SHADOW_FISSURE, urand(7500, 10000));
|
||||
break;
|
||||
case EVENT_SPELL_DEATH_COIL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
me->CastSpell(target, DUNGEON_MODE(SPELL_DEATH_COIL_N, SPELL_DEATH_COIL_H), false);
|
||||
events.RescheduleEvent(EVENT_SPELL_DEATH_COIL, urand(15000, 20000));
|
||||
break;
|
||||
case EVENT_SPELL_CLEAVE:
|
||||
me->CastSpell(me->GetVictim(), DUNGEON_MODE(SPELL_SHADOW_CLEAVE_N, SPELL_SHADOW_SLAM_H), false);
|
||||
events.RescheduleEvent(EVENT_SPELL_CLEAVE, urand(6000, 8000));
|
||||
break;
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(21))
|
||||
{
|
||||
events.Reset();
|
||||
me->CastSpell(me, SPELL_DARK_SPIN, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
events.RescheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!me->HealthBelowPct(21))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8 PeonEngagedCount = 0;
|
||||
uint8 PeonKilledCount = 0;
|
||||
uint8 EventStage;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetShatteredHallsAI<boss_grand_warlock_nethekurseAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_tsh_shadow_sear : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_tsh_shadow_sear() : SpellScriptLoader("spell_tsh_shadow_sear") { }
|
||||
|
||||
class spell_tsh_shadow_sear_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_tsh_shadow_sear_AuraScript);
|
||||
|
||||
void CalculateDamageAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
amount = 1000;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_tsh_shadow_sear_AuraScript::CalculateDamageAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_tsh_shadow_sear_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_tsh_shadow_bolt : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_tsh_shadow_bolt() : SpellScriptLoader("spell_tsh_shadow_bolt") { }
|
||||
|
||||
class spell_tsh_shadow_bolt_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_tsh_shadow_bolt_SpellScript);
|
||||
|
||||
void SelectRandomPlayer(WorldObject*& target)
|
||||
{
|
||||
if (Creature* caster = GetCaster()->ToCreature())
|
||||
{
|
||||
std::list<Player*> playerList;
|
||||
Map::PlayerList const& players = caster->GetMap()->GetPlayers();
|
||||
for (auto itr = players.begin(); itr != players.end(); ++itr)
|
||||
if (Player* player = itr->GetSource()->ToPlayer())
|
||||
if (player->IsWithinDist(caster, 100.0f) && player->IsAlive())
|
||||
playerList.push_back(player);
|
||||
|
||||
if (!playerList.empty())
|
||||
target = Acore::Containers::SelectRandomContainerElement(playerList);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_tsh_shadow_bolt_SpellScript::SelectRandomPlayer, EFFECT_0, TARGET_UNIT_TARGET_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_tsh_shadow_bolt_SpellScript();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_grand_warlock_nethekurse()
|
||||
{
|
||||
new boss_grand_warlock_nethekurse();
|
||||
new spell_tsh_shadow_sear();
|
||||
new spell_tsh_shadow_bolt();
|
||||
RegisterShatteredHallsCreatureAI(boss_grand_warlock_nethekurse);
|
||||
RegisterSpellScript(spell_tsh_shadow_bolt);
|
||||
RegisterSpellScript(spell_target_fissures);
|
||||
new at_rp_nethekurse();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "shattered_halls.h"
|
||||
|
||||
enum Spells
|
||||
@@ -24,249 +26,264 @@ enum Spells
|
||||
SPELL_BLAST_WAVE = 30600,
|
||||
SPELL_FEAR = 30584,
|
||||
SPELL_THUNDERCLAP = 30633,
|
||||
SPELL_BURNING_MAUL_N = 30598,
|
||||
SPELL_BURNING_MAUL_H = 36056,
|
||||
SPELL_BEATDOWN = 30618,
|
||||
SPELL_BURNING_MAUL = 30598
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
enum Equip
|
||||
{
|
||||
NPC_LEFT_HEAD = 19523,
|
||||
NPC_RIGHT_HEAD = 19524
|
||||
EQUIP_STANDARD = 1,
|
||||
EQUIP_BURNING_MAUL = 2
|
||||
};
|
||||
|
||||
enum HeadYells
|
||||
{
|
||||
SAY_ON_AGGRO = 0,
|
||||
SAY_ON_AGGRO_2,
|
||||
SAY_ON_AGGRO_3,
|
||||
SAY_ON_BEATDOWN,
|
||||
SAY_ON_BEATDOWN_2,
|
||||
SAY_ON_BEATDOWN_3,
|
||||
SAY_ON_KILL,
|
||||
SAY_ON_KILL_2,
|
||||
SAY_ON_DEATH
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
EMOTE_ENRAGE = 0,
|
||||
|
||||
SETDATA_DATA = 1,
|
||||
SETDATA_YELL = 1
|
||||
EMOTE_BURNING_MAUL = 0,
|
||||
DATA_BURNING_MAUL_END = 1
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum Phase
|
||||
{
|
||||
EVENT_AGGRO_YELL_1 = 1,
|
||||
EVENT_AGGRO_YELL_2 = 2,
|
||||
EVENT_AGGRO_YELL_3 = 3,
|
||||
|
||||
EVENT_THREAT_YELL_L_1 = 4,
|
||||
EVENT_THREAT_YELL_L_2 = 5,
|
||||
EVENT_THREAT_YELL_L_3 = 6,
|
||||
|
||||
EVENT_THREAT_YELL_R_1 = 7,
|
||||
|
||||
EVENT_KILL_YELL_LEFT = 8,
|
||||
EVENT_KILL_YELL_RIGHT = 9,
|
||||
EVENT_DEATH_YELL = 10,
|
||||
|
||||
EVENT_SPELL_FEAR = 20,
|
||||
EVENT_SPELL_BURNING_MAUL = 21,
|
||||
EVENT_SPELL_THUNDER_CLAP = 22,
|
||||
EVENT_RESET_THREAT = 23,
|
||||
EVENT_SPELL_BLAST_WAVE = 24
|
||||
GROUP_NON_BURNING_PHASE = 0,
|
||||
GROUP_BURNING_PHASE = 1,
|
||||
GROUP_FULL_PHASE = 2
|
||||
};
|
||||
|
||||
// ########################################################
|
||||
// Warbringer_Omrogg
|
||||
// ########################################################
|
||||
|
||||
class boss_warbringer_omrogg : public CreatureScript
|
||||
struct boss_warbringer_omrogg : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_warbringer_omrogg() : CreatureScript("boss_warbringer_omrogg") { }
|
||||
|
||||
struct boss_warbringer_omroggAI : public BossAI
|
||||
boss_warbringer_omrogg(Creature* creature) : BossAI(creature, DATA_OMROGG)
|
||||
{
|
||||
boss_warbringer_omroggAI(Creature* creature) : BossAI(creature, DATA_OMROGG)
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
}
|
||||
|
||||
EventMap events2;
|
||||
|
||||
Creature* GetLeftHead()
|
||||
{
|
||||
return summons.GetCreatureWithEntry(NPC_LEFT_HEAD);
|
||||
}
|
||||
|
||||
Creature* GetRightHead()
|
||||
{
|
||||
return summons.GetCreatureWithEntry(NPC_RIGHT_HEAD);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0);
|
||||
|
||||
if (Creature* LeftHead = GetLeftHead())
|
||||
{
|
||||
uint8 aggroYell = urand(EVENT_AGGRO_YELL_1, EVENT_AGGRO_YELL_3);
|
||||
LeftHead->AI()->Talk(aggroYell - 1);
|
||||
events2.ScheduleEvent(aggroYell, 3000);
|
||||
}
|
||||
|
||||
_JustEngagedWith();
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_FEAR, 8000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BURNING_MAUL, 25000);
|
||||
events.ScheduleEvent(EVENT_SPELL_THUNDER_CLAP, 15000);
|
||||
events.ScheduleEvent(EVENT_RESET_THREAT, 30000);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
summons.Summon(summoned);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Creature* head = nullptr;
|
||||
uint32 eventId = EVENT_KILL_YELL_LEFT;
|
||||
if (urand(0, 1))
|
||||
{
|
||||
head = GetLeftHead();
|
||||
eventId = EVENT_KILL_YELL_LEFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
head = GetRightHead();
|
||||
eventId = EVENT_KILL_YELL_RIGHT;
|
||||
}
|
||||
|
||||
if (head)
|
||||
head->AI()->Talk(eventId - 1);
|
||||
|
||||
events2.ScheduleEvent(eventId, 3000);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Creature* LeftHead = GetLeftHead();
|
||||
Creature* RightHead = GetRightHead();
|
||||
if (!LeftHead || !RightHead)
|
||||
return;
|
||||
|
||||
LeftHead->DespawnOrUnsummon(5000);
|
||||
RightHead->DespawnOrUnsummon(5000);
|
||||
|
||||
LeftHead->AI()->Talk(EVENT_DEATH_YELL - 1);
|
||||
RightHead->AI()->SetData(SETDATA_DATA, SETDATA_YELL);
|
||||
|
||||
instance->SetBossState(DATA_OMROGG, DONE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events2.Update(diff);
|
||||
switch (uint32 eventId = events2.ExecuteEvent())
|
||||
{
|
||||
case EVENT_AGGRO_YELL_1:
|
||||
case EVENT_AGGRO_YELL_2:
|
||||
case EVENT_AGGRO_YELL_3:
|
||||
case EVENT_KILL_YELL_LEFT:
|
||||
case EVENT_THREAT_YELL_L_1:
|
||||
case EVENT_THREAT_YELL_L_2:
|
||||
case EVENT_THREAT_YELL_L_3:
|
||||
if (Creature* RightHead = GetRightHead())
|
||||
RightHead->AI()->Talk(eventId - 1);
|
||||
break;
|
||||
case EVENT_KILL_YELL_RIGHT:
|
||||
case EVENT_THREAT_YELL_R_1:
|
||||
if (Creature* LeftHead = GetLeftHead())
|
||||
LeftHead->AI()->Talk(eventId - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_FEAR:
|
||||
me->CastSpell(me, SPELL_FEAR, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_FEAR, 22000);
|
||||
break;
|
||||
case EVENT_SPELL_THUNDER_CLAP:
|
||||
me->CastSpell(me, SPELL_THUNDERCLAP, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_THUNDER_CLAP, 25000);
|
||||
break;
|
||||
case EVENT_RESET_THREAT:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
uint8 threatYell = urand(EVENT_THREAT_YELL_L_1, EVENT_THREAT_YELL_R_1);
|
||||
if (Creature* head = threatYell == EVENT_THREAT_YELL_R_1 ? GetRightHead() : GetLeftHead())
|
||||
head->AI()->Talk(threatYell - 1);
|
||||
events.ScheduleEvent(threatYell, 3000);
|
||||
|
||||
DoResetThreatList();
|
||||
me->AddThreat(target, 10.0f);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_RESET_THREAT, 30000);
|
||||
break;
|
||||
case EVENT_SPELL_BURNING_MAUL:
|
||||
Talk(EMOTE_ENRAGE);
|
||||
me->CastSpell(me, DUNGEON_MODE(SPELL_BURNING_MAUL_N, SPELL_BURNING_MAUL_H), false);
|
||||
events.ScheduleEvent(EVENT_SPELL_BURNING_MAUL, 40000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BLAST_WAVE, 15000);
|
||||
events.ScheduleEvent(EVENT_SPELL_BLAST_WAVE, 20000);
|
||||
break;
|
||||
case EVENT_SPELL_BLAST_WAVE:
|
||||
me->CastSpell(me, SPELL_BLAST_WAVE, false);
|
||||
break;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetShatteredHallsAI<boss_warbringer_omroggAI>(creature);
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void HandleHeadTalk(HeadYells yell)
|
||||
{
|
||||
switch (yell)
|
||||
{
|
||||
case SAY_ON_AGGRO:
|
||||
{
|
||||
uint8 group = urand(SAY_ON_AGGRO, SAY_ON_AGGRO_3);
|
||||
if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD))
|
||||
{
|
||||
leftHead->AI()->Talk(group);
|
||||
_headTalk.Schedule(3600ms, [this, group](TaskContext /*context*/)
|
||||
{
|
||||
if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD))
|
||||
rightHead->AI()->Talk(group);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SAY_ON_BEATDOWN:
|
||||
{
|
||||
if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD))
|
||||
{
|
||||
leftHead->AI()->Talk(SAY_ON_BEATDOWN);
|
||||
_headTalk.Schedule(3600ms, [this](TaskContext context)
|
||||
{
|
||||
if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD))
|
||||
rightHead->AI()->Talk(SAY_ON_BEATDOWN);
|
||||
context.Schedule(3600ms, [this](TaskContext context)
|
||||
{
|
||||
uint8 group = urand(SAY_ON_BEATDOWN_2, SAY_ON_BEATDOWN_3);
|
||||
if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD))
|
||||
leftHead->AI()->Talk(group);
|
||||
context.Schedule(3600ms, [this, group](TaskContext /*context*/)
|
||||
{
|
||||
if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD))
|
||||
rightHead->AI()->Talk(group);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SAY_ON_KILL:
|
||||
{
|
||||
uint8 group = urand(SAY_ON_KILL, SAY_ON_KILL_2);
|
||||
if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD))
|
||||
leftHead->AI()->Talk(group);
|
||||
_headTalk.Schedule(3600ms, [this, group](TaskContext /*context*/)
|
||||
{
|
||||
if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD))
|
||||
rightHead->AI()->Talk(group);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SAY_ON_DEATH:
|
||||
{
|
||||
if (Creature* leftHead = instance->GetCreature(DATA_OMROGG_LEFT_HEAD))
|
||||
leftHead->AI()->Talk(SAY_ON_DEATH);
|
||||
_headTalk.Schedule(3600ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (Creature* rightHead = instance->GetCreature(DATA_OMROGG_RIGHT_HEAD))
|
||||
rightHead->AI()->Talk(SAY_ON_DEATH);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 data, uint32) override
|
||||
{
|
||||
if (data != DATA_BURNING_MAUL_END)
|
||||
return;
|
||||
|
||||
scheduler.CancelGroup(GROUP_BURNING_PHASE);
|
||||
ScheduleNonBurningPhase();
|
||||
ScheduleBurningPhase();
|
||||
}
|
||||
|
||||
void ScheduleNonBurningPhase()
|
||||
{
|
||||
scheduler.
|
||||
Schedule(12100ms, 17300ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_THUNDERCLAP);
|
||||
context.Repeat(17200ms, 24200ms);
|
||||
})
|
||||
.Schedule(20s, 30s, GROUP_NON_BURNING_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_BEATDOWN);
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
context.Schedule(200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoResetThreatList();
|
||||
if (Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 1))
|
||||
me->AddThreat(newTarget, 2250.f);
|
||||
HandleHeadTalk(SAY_ON_BEATDOWN);
|
||||
context.Schedule(1200ms, GROUP_NON_BURNING_PHASE, [this](TaskContext /*context*/)
|
||||
{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
});
|
||||
});
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void ScheduleBurningPhase()
|
||||
{
|
||||
scheduler.
|
||||
Schedule(45s, 60s, GROUP_BURNING_PHASE, [this](TaskContext context)
|
||||
{
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
context.CancelGroup(GROUP_NON_BURNING_PHASE);
|
||||
context.Schedule(1200ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_FEAR);
|
||||
DoCast(SPELL_BURNING_MAUL);
|
||||
context.Schedule(200ms, [this](TaskContext context)
|
||||
{
|
||||
Talk(EMOTE_BURNING_MAUL);
|
||||
context.Schedule(2200ms, [this](TaskContext context)
|
||||
{
|
||||
DoResetThreatList();
|
||||
if (Unit* newTarget = SelectTarget(SelectTargetMethod::Random, 1))
|
||||
me->AddThreat(newTarget, 2250.f);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
context.Schedule(4850ms, 8500ms, GROUP_BURNING_PHASE, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_BLAST_WAVE);
|
||||
context.Repeat();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
_headTalk.CancelAll();
|
||||
HandleHeadTalk(SAY_ON_AGGRO);
|
||||
|
||||
ScheduleNonBurningPhase();
|
||||
ScheduleBurningPhase();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
|
||||
HandleHeadTalk(SAY_ON_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
HandleHeadTalk(SAY_ON_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_headTalk.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
TaskScheduler _headTalk;
|
||||
};
|
||||
|
||||
class npc_omrogg_heads : public CreatureScript
|
||||
class spell_burning_maul : public AuraScript
|
||||
{
|
||||
public:
|
||||
npc_omrogg_heads() : CreatureScript("npc_omrogg_heads") { }
|
||||
PrepareAuraScript(spell_burning_maul);
|
||||
|
||||
struct npc_omrogg_headsAI : public NullCreatureAI
|
||||
void HandleOnRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */)
|
||||
{
|
||||
npc_omrogg_headsAI(Creature* creature) : NullCreatureAI(creature) { timer = 0; }
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (data == SETDATA_DATA && value == SETDATA_YELL)
|
||||
timer = 1;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (timer)
|
||||
if (Creature* omrogg = caster->ToCreature())
|
||||
{
|
||||
timer += diff;
|
||||
if (timer >= 3000)
|
||||
{
|
||||
timer = 0;
|
||||
Talk(EVENT_DEATH_YELL - 1);
|
||||
}
|
||||
omrogg->LoadEquipment(EQUIP_STANDARD);
|
||||
omrogg->AI()->SetData(DATA_BURNING_MAUL_END, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 timer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void HandleOnApply(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */)
|
||||
{
|
||||
return GetShatteredHallsAI<npc_omrogg_headsAI>(creature);
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Creature* omrogg = caster->ToCreature())
|
||||
omrogg->LoadEquipment(EQUIP_BURNING_MAUL);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_burning_maul::HandleOnRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectApply += AuraEffectApplyFn(spell_burning_maul::HandleOnApply, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_warbringer_omrogg()
|
||||
{
|
||||
new boss_warbringer_omrogg();
|
||||
new npc_omrogg_heads();
|
||||
RegisterShatteredHallsCreatureAI(boss_warbringer_omrogg);
|
||||
RegisterSpellScript(spell_burning_maul);
|
||||
}
|
||||
|
||||
@@ -17,174 +17,305 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "TaskScheduler.h"
|
||||
#include "shattered_halls.h"
|
||||
|
||||
enum Says
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_DEATH = 2
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SLAY = 1,
|
||||
SAY_DEATH = 2,
|
||||
SAY_EVADE = 5
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_BLADE_DANCE = 30739,
|
||||
SPELL_CHARGE = 25821,
|
||||
SPELL_SPRINT = 32720,
|
||||
// Blade dance
|
||||
SPELL_BLADE_DANCE_TARGETING = 30738,
|
||||
SPELL_BLADE_DANCE_DMG = 30739,
|
||||
SPELL_BLADE_DANCE_CHARGE = 30751,
|
||||
|
||||
// Warchief portal
|
||||
SPELL_SUMMON_HEATHEN = 30737,
|
||||
SPELL_SUMMON_REAVER = 30785,
|
||||
SPELL_SUMMON_SHARPSHOOTER = 30786
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_SHATTERED_ASSASSIN = 17695,
|
||||
NPC_HEARTHEN_GUARD = 17621,
|
||||
NPC_SHARPSHOOTER_GUARD = 17622,
|
||||
NPC_REAVER_GUARD = 17623
|
||||
NPC_SHATTERED_ASSASSIN = 17695,
|
||||
NPC_BLADE_DANCE_TARGET = 20709
|
||||
};
|
||||
|
||||
float AssassEntrance[3] = { 275.136f, -84.29f, 2.3f }; // y -8
|
||||
float AssassExit[3] = { 184.233f, -84.29f, 2.3f }; // y -8
|
||||
float AddsEntrance[3] = { 306.036f, -84.29f, 1.93f };
|
||||
|
||||
enum Misc
|
||||
enum PortalData
|
||||
{
|
||||
EVENT_CHECK_ROOM = 1,
|
||||
EVENT_SUMMON_ADDS = 2,
|
||||
EVENT_SUMMON_ASSASSINS = 3,
|
||||
EVENT_SPELL_CHARGE = 4,
|
||||
EVENT_MOVE_TO_NEXT_POINT = 5,
|
||||
EVENT_BLADE_DANCE = 6,
|
||||
EVENT_FINISH_BLADE_DANCE = 7
|
||||
DATA_START_FIGHT = 1,
|
||||
DATA_RESET_FIGHT = 2
|
||||
};
|
||||
|
||||
class boss_warchief_kargath_bladefist : public CreatureScript
|
||||
std::array<uint32, 3> const summonSpells = { SPELL_SUMMON_HEATHEN, SPELL_SUMMON_REAVER, SPELL_SUMMON_SHARPSHOOTER };
|
||||
std::vector<Position> const assassinsPos =
|
||||
{
|
||||
{ 172.68164f, -80.65692f, 2.0834563f, 5.4279f },
|
||||
{ 167.8295f, -86.55783f, 1.9949634f, 0.8118f },
|
||||
{ 287.0375f, -88.17879f, 2.0663502f, 3.2490f },
|
||||
{ 292.1491f, -82.25267f, 1.9973913f, 5.8568f }
|
||||
};
|
||||
|
||||
Position const kargathRespawnPos = { 231.25f, -83.6449f, 5.02341f };
|
||||
|
||||
struct boss_warchief_kargath_bladefist : public BossAI
|
||||
{
|
||||
boss_warchief_kargath_bladefist(Creature* creature) : BossAI(creature, DATA_KARGATH)
|
||||
{
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
if (instance)
|
||||
{
|
||||
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
|
||||
{
|
||||
executioner->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
summon->SetVisible(false);
|
||||
scheduler.Schedule(20s, [summon](TaskContext /*context*/)
|
||||
{
|
||||
if (summon)
|
||||
{
|
||||
summon->Respawn(true);
|
||||
summon->SetVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void RespawnAssassins()
|
||||
{
|
||||
for (Position const& summonPos : assassinsPos)
|
||||
me->SummonCreature(NPC_SHATTERED_ASSASSIN, summonPos);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL))
|
||||
warchiefPortal->AI()->SetData(DATA_RESET_FIGHT, 0);
|
||||
_danceCount = 0;
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
BossAI::JustDied(killer);
|
||||
if (instance)
|
||||
{
|
||||
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
|
||||
{
|
||||
executioner->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL))
|
||||
warchiefPortal->AI()->SetData(DATA_START_FIGHT, 0);
|
||||
RespawnAssassins();
|
||||
scheduler
|
||||
.Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
_danceCount = 0;
|
||||
DoCastAOE(SPELL_BLADE_DANCE_TARGETING);
|
||||
context.Repeat(32850ms, 41350ms);
|
||||
});
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (_danceCount < 8)
|
||||
{
|
||||
_danceCount++;
|
||||
scheduler.Schedule(100ms, [this](TaskContext /*context*/)
|
||||
{
|
||||
DoCastAOE(SPELL_BLADE_DANCE_TARGETING);
|
||||
});
|
||||
}
|
||||
else
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
bool IsInRoom()
|
||||
{
|
||||
if (me->GetExactDist2d(kargathRespawnPos) >= 42.f)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!IsInRoom())
|
||||
{
|
||||
Talk(SAY_EVADE);
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8 _danceCount;
|
||||
};
|
||||
|
||||
struct npc_warchief_portal : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
boss_warchief_kargath_bladefist() : CreatureScript("boss_warchief_kargath_bladefist") { }
|
||||
npc_warchief_portal(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
struct boss_warchief_kargath_bladefistAI : public BossAI
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
boss_warchief_kargath_bladefistAI(Creature* creature) : BossAI(creature, DATA_KARGATH) { }
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
void JustSummoned(Creature* creature) override
|
||||
{
|
||||
InstanceScript* instance = me->GetInstanceScript();
|
||||
if (!instance)
|
||||
return;
|
||||
|
||||
if (Creature* kargath = instance->GetCreature(DATA_KARGATH))
|
||||
kargath->AI()->JustSummoned(creature);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 /*data*/) override
|
||||
{
|
||||
if (type == DATA_START_FIGHT)
|
||||
{
|
||||
BossAI::InitializeAI();
|
||||
if (instance)
|
||||
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
|
||||
executioner->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_scheduler.Schedule(20600ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(summonSpells[context.GetRepeatCounter() % 3]);
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
if (type == DATA_RESET_FIGHT)
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
|
||||
if (instance)
|
||||
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
|
||||
executioner->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
protected:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
events.ScheduleEvent(EVENT_CHECK_ROOM, 5000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
|
||||
events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 5000);
|
||||
events.ScheduleEvent(EVENT_BLADE_DANCE, 30000);
|
||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 0);
|
||||
}
|
||||
class spell_blade_dance_targeting : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_blade_dance_targeting);
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
if (summon->GetEntry() != NPC_SHATTERED_ASSASSIN)
|
||||
summon->AI()->AttackStart(SelectTarget(SelectTargetMethod::Random, 0));
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BLADE_DANCE_CHARGE, SPELL_BLADE_DANCE_DMG });
|
||||
}
|
||||
|
||||
summons.Summon(summon);
|
||||
}
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE || id != 1)
|
||||
return;
|
||||
|
||||
me->CastSpell(me, SPELL_BLADE_DANCE, true);
|
||||
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
targets.remove_if([&](WorldObject* target) -> bool
|
||||
{
|
||||
case EVENT_CHECK_ROOM:
|
||||
if (me->GetPositionX() > 255 || me->GetPositionX() < 205)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_CHECK_ROOM, 5000);
|
||||
break;
|
||||
case EVENT_SUMMON_ASSASSINS:
|
||||
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] + 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassEntrance[0], AssassEntrance[1] - 8, AssassEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] + 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||
me->SummonCreature(NPC_SHATTERED_ASSASSIN, AssassExit[0], AssassExit[1] - 8, AssassExit[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||
break;
|
||||
case EVENT_SUMMON_ADDS:
|
||||
for (uint8 i = 0; i < 2; ++i)
|
||||
me->SummonCreature(NPC_HEARTHEN_GUARD + urand(0, 2), AddsEntrance[0], AddsEntrance[1], AddsEntrance[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
|
||||
float dist = caster->GetDistance2d(target);
|
||||
// Do not target dummies that are too close or too far away
|
||||
if (dist < 5.f || dist > 16.f)
|
||||
return true;
|
||||
// Do not target anything that is not a target dummy
|
||||
if (target->GetEntry() != NPC_BLADE_DANCE_TARGET)
|
||||
return true;
|
||||
|
||||
events.ScheduleEvent(EVENT_SUMMON_ADDS, 30000);
|
||||
break;
|
||||
case EVENT_BLADE_DANCE:
|
||||
events.DelayEvents(10001);
|
||||
events.ScheduleEvent(EVENT_BLADE_DANCE, 40000);
|
||||
events.ScheduleEvent(EVENT_MOVE_TO_NEXT_POINT, 0);
|
||||
events.ScheduleEvent(EVENT_FINISH_BLADE_DANCE, 10000);
|
||||
events.SetPhase(1);
|
||||
me->CastSpell(me, SPELL_SPRINT, true);
|
||||
break;
|
||||
case EVENT_MOVE_TO_NEXT_POINT:
|
||||
{
|
||||
float x = 210 + frand(0.0f, 35.0f);
|
||||
float y = -65.0f - frand(0.0f, 35.0f);
|
||||
me->GetMotionMaster()->MovePoint(1, x, y, me->GetPositionZ());
|
||||
break;
|
||||
}
|
||||
case EVENT_FINISH_BLADE_DANCE:
|
||||
events.SetPhase(0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
if (IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 3000);
|
||||
break;
|
||||
case EVENT_SPELL_CHARGE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CHARGE, false);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!events.IsInPhase(1))
|
||||
DoMeleeAttackIfReady();
|
||||
std::list<WorldObject*> targets2 = targets;
|
||||
|
||||
targets.remove_if([&](WorldObject* target) -> bool
|
||||
{
|
||||
if (target->SelectNearestPlayer(15.f))
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
Acore::Containers::RandomResize(targets2, 1);
|
||||
|
||||
if (urand(0, 2))
|
||||
{
|
||||
if (targets.empty())
|
||||
targets = targets2;
|
||||
else
|
||||
Acore::Containers::RandomResize(targets, 1);
|
||||
}
|
||||
};
|
||||
else
|
||||
targets = targets2;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void HandleOnHit()
|
||||
{
|
||||
return GetShatteredHallsAI<boss_warchief_kargath_bladefistAI>(creature);
|
||||
Unit* caster = GetCaster();
|
||||
Unit* target = GetHitUnit();
|
||||
if (!caster || !target)
|
||||
return;
|
||||
|
||||
caster->CastSpell(target, SPELL_BLADE_DANCE_CHARGE, true);
|
||||
caster->CastSpell(target, SPELL_BLADE_DANCE_DMG, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blade_dance_targeting::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnHit += SpellHitFn(spell_blade_dance_targeting::HandleOnHit);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_warchief_kargath_bladefist()
|
||||
{
|
||||
new boss_warchief_kargath_bladefist();
|
||||
RegisterShatteredHallsCreatureAI(boss_warchief_kargath_bladefist);
|
||||
RegisterShatteredHallsCreatureAI(npc_warchief_portal);
|
||||
RegisterSpellScript(spell_blade_dance_targeting);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,23 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "shattered_halls.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_GRAND_WARLOCK_NETHEKURSE , DATA_NETHEKURSE },
|
||||
{ NPC_WARCHIEF_KARGATH , DATA_KARGATH },
|
||||
{ NPC_OMROGG_LEFT_HEAD , DATA_OMROGG_LEFT_HEAD },
|
||||
{ NPC_OMROGG_RIGHT_HEAD , DATA_OMROGG_RIGHT_HEAD },
|
||||
{ NPC_WARCHIEF_PORTAL , DATA_WARCHIEF_PORTAL },
|
||||
{ 0 , 0 }
|
||||
};
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE },
|
||||
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
class instance_shattered_halls : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -37,6 +54,8 @@ public:
|
||||
void Initialize() override
|
||||
{
|
||||
SetBossNumber(ENCOUNTER_COUNT);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
RescueTimer = 100 * MINUTE * IN_MILLISECONDS;
|
||||
@@ -48,23 +67,6 @@ public:
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
|
||||
nethekurseDoor1GUID = go->GetGUID();
|
||||
if (GetBossState(DATA_NETHEKURSE) == DONE)
|
||||
HandleGameObject(ObjectGuid::Empty, true, go);
|
||||
break;
|
||||
case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
|
||||
nethekurseDoor2GUID = go->GetGUID();
|
||||
if (GetBossState(DATA_NETHEKURSE) == DONE)
|
||||
HandleGameObject(ObjectGuid::Empty, true, go);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
@@ -77,9 +79,6 @@ public:
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_WARCHIEF_KARGATH:
|
||||
warchiefKargathGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_SHATTERED_EXECUTIONER:
|
||||
if (RescueTimer > 25 * MINUTE * IN_MILLISECONDS)
|
||||
creature->AddLootMode(2);
|
||||
@@ -101,29 +100,7 @@ public:
|
||||
prisonerGUID[2] = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SetBossState(uint32 type, EncounterState state) override
|
||||
{
|
||||
if (!InstanceScript::SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_NETHEKURSE:
|
||||
if (state == IN_PROGRESS)
|
||||
{
|
||||
HandleGameObject(nethekurseDoor1GUID, false);
|
||||
HandleGameObject(nethekurseDoor2GUID, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleGameObject(nethekurseDoor1GUID, true);
|
||||
HandleGameObject(nethekurseDoor2GUID, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
@@ -133,7 +110,7 @@ public:
|
||||
DoCastSpellOnPlayers(SPELL_KARGATHS_EXECUTIONER_1);
|
||||
instance->LoadGrid(230, -80);
|
||||
|
||||
if (Creature* kargath = instance->GetCreature(warchiefKargathGUID))
|
||||
if (Creature* kargath = GetCreature(DATA_KARGATH))
|
||||
sCreatureTextMgr->SendChat(kargath, TeamIdInInstance == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
|
||||
|
||||
RescueTimer = 80 * MINUTE * IN_MILLISECONDS;
|
||||
@@ -197,10 +174,6 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjectGuid warchiefKargathGUID;
|
||||
ObjectGuid nethekurseDoor1GUID;
|
||||
ObjectGuid nethekurseDoor2GUID;
|
||||
|
||||
ObjectGuid executionerGUID;
|
||||
ObjectGuid prisonerGUID[3];
|
||||
uint32 RescueTimer;
|
||||
|
||||
@@ -35,14 +35,23 @@ enum DataTypes
|
||||
DATA_PRISONER_1 = 11,
|
||||
DATA_PRISONER_2 = 12,
|
||||
DATA_PRISONER_3 = 13,
|
||||
DATA_EXECUTIONER = 14
|
||||
DATA_EXECUTIONER = 14,
|
||||
DATA_OMROGG_LEFT_HEAD = 15,
|
||||
DATA_OMROGG_RIGHT_HEAD = 16,
|
||||
DATA_WARCHIEF_PORTAL = 17
|
||||
};
|
||||
|
||||
enum CreatureIds
|
||||
{
|
||||
NPC_GRAND_WARLOCK_NETHEKURSE = 16807,
|
||||
NPC_WARCHIEF_KARGATH = 16808,
|
||||
NPC_FEL_ORC_CONVERT = 17083,
|
||||
// Warchief Kargath
|
||||
NPC_WARCHIEF_KARGATH = 16808,
|
||||
NPC_WARCHIEF_PORTAL = 17611,
|
||||
|
||||
// O'MROGG
|
||||
NPC_OMROGG_LEFT_HEAD = 19523,
|
||||
NPC_OMROGG_RIGHT_HEAD = 19524,
|
||||
|
||||
// Trial of the Naaru: Mercy
|
||||
NPC_SHATTERED_EXECUTIONER = 17301,
|
||||
@@ -73,4 +82,6 @@ inline AI* GetShatteredHallsAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, ShatteredHallsLairScriptName);
|
||||
}
|
||||
|
||||
#define RegisterShatteredHallsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShatteredHallsAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,11 +46,6 @@ enum Yells
|
||||
SAY_DEATH = 4
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_NETHER_CHARGE = 20405
|
||||
};
|
||||
|
||||
struct boss_mechano_lord_capacitus : public BossAI
|
||||
{
|
||||
boss_mechano_lord_capacitus(Creature* creature) : BossAI(creature, DATA_MECHANOLORD_CAPACITUS)
|
||||
@@ -127,7 +122,6 @@ struct boss_mechano_lord_capacitus : public BossAI
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon->GetMotionMaster()->MoveRandom(30.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,9 +21,11 @@ void AddSC_instance_auchenai_crypts();
|
||||
void AddSC_boss_shirrak_the_dead_watcher();
|
||||
void AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs
|
||||
void AddSC_boss_pandemonius();
|
||||
void AddSC_boss_tavarok();
|
||||
void AddSC_instance_mana_tombs();
|
||||
void AddSC_boss_talon_king_ikiss(); //Auchindoun Sekketh Halls
|
||||
void AddSC_boss_anzu();
|
||||
void AddSC_boss_darkweaver_syth();
|
||||
void AddSC_instance_sethekk_halls();
|
||||
void AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth
|
||||
void AddSC_boss_ambassador_hellmaw();
|
||||
@@ -54,10 +56,14 @@ void AddSC_instance_steam_vault();
|
||||
void AddSC_underbog(); //CR Underbog
|
||||
void AddSC_boss_hungarfen();
|
||||
void AddSC_boss_ghazan();
|
||||
void AddSC_boss_swamplord_muselek();
|
||||
void AddSC_boss_the_black_stalker();
|
||||
void AddSC_instance_the_underbog();
|
||||
void AddSC_the_slave_pens(); // The Slave Pens
|
||||
void AddSC_boss_ahune();
|
||||
void AddSC_boss_mennu_the_betrayer();
|
||||
void AddSC_boss_rokmar_the_crackler();
|
||||
void AddSC_boss_quagmirran();
|
||||
void AddSC_instance_the_slave_pens();
|
||||
void AddSC_boss_gruul(); //Gruul's Lair
|
||||
void AddSC_boss_high_king_maulgar();
|
||||
@@ -119,9 +125,11 @@ void AddOutlandScripts()
|
||||
AddSC_boss_shirrak_the_dead_watcher();
|
||||
AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs
|
||||
AddSC_boss_pandemonius();
|
||||
AddSC_boss_tavarok();
|
||||
AddSC_instance_mana_tombs();
|
||||
AddSC_boss_talon_king_ikiss(); //Auchindoun Sekketh Halls
|
||||
AddSC_boss_anzu();
|
||||
AddSC_boss_darkweaver_syth();
|
||||
AddSC_instance_sethekk_halls();
|
||||
AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth
|
||||
AddSC_boss_ambassador_hellmaw();
|
||||
@@ -152,10 +160,14 @@ void AddOutlandScripts()
|
||||
AddSC_underbog(); //CR Underbog
|
||||
AddSC_boss_hungarfen();
|
||||
AddSC_boss_ghazan();
|
||||
AddSC_boss_swamplord_muselek();
|
||||
AddSC_boss_the_black_stalker();
|
||||
AddSC_instance_the_underbog();
|
||||
AddSC_the_slave_pens(); // The Slave Pens
|
||||
AddSC_the_slave_pens(); //CR The Slave Pens
|
||||
AddSC_boss_ahune();
|
||||
AddSC_boss_mennu_the_betrayer();
|
||||
AddSC_boss_rokmar_the_crackler();
|
||||
AddSC_boss_quagmirran();
|
||||
AddSC_instance_the_slave_pens();
|
||||
AddSC_boss_gruul(); //Gruul's Lair
|
||||
AddSC_boss_high_king_maulgar();
|
||||
@@ -207,4 +219,4 @@ void AddOutlandScripts()
|
||||
AddSC_shattrath_city();
|
||||
AddSC_terokkar_forest();
|
||||
//AddSC_zangarmarsh();
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Shattrath_City
|
||||
SD%Complete: 100
|
||||
SDComment: Quest support: 10004, 10009, 10211. Flask vendors, Teleport to Caverns of Time
|
||||
SDCategory: Shattrath City
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_raliq_the_drunk
|
||||
npc_salsalabim
|
||||
npc_shattrathflaskvendors
|
||||
npc_zephyr
|
||||
npc_kservant
|
||||
EndContentData */
|
||||
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
@@ -37,176 +22,6 @@ EndContentData */
|
||||
#include "ScriptedGossip.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
/*######
|
||||
## npc_raliq_the_drunk
|
||||
######*/
|
||||
|
||||
#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!"
|
||||
|
||||
enum Raliq
|
||||
{
|
||||
SPELL_UPPERCUT = 10966,
|
||||
QUEST_CRACK_SKULLS = 10009,
|
||||
EMOTE_DRINK = 7,
|
||||
};
|
||||
|
||||
class npc_raliq_the_drunk : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_raliq_the_drunk() : CreatureScript("npc_raliq_the_drunk") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->SetFaction(FACTION_OGRE);
|
||||
creature->AI()->AttackStart(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE)
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
SendGossipMenuFor(player, 9440, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_raliq_the_drunkAI(creature);
|
||||
}
|
||||
|
||||
struct npc_raliq_the_drunkAI : public ScriptedAI
|
||||
{
|
||||
npc_raliq_the_drunkAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
m_uiNormFaction = creature->GetFaction();
|
||||
}
|
||||
|
||||
uint32 m_uiNormFaction;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->RestoreFaction();
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
me->HandleEmoteCommand(EMOTE_DRINK);
|
||||
context.Repeat(5s);
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
_scheduler
|
||||
.Schedule(5s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_UPPERCUT);
|
||||
context.Repeat(15s);
|
||||
});
|
||||
};
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
# npc_salsalabim
|
||||
######*/
|
||||
|
||||
enum Salsalabim
|
||||
{
|
||||
// Quests
|
||||
QUEST_10004 = 10004,
|
||||
|
||||
// Spells
|
||||
SPELL_MAGNETIC_PULL = 31705
|
||||
};
|
||||
|
||||
class npc_salsalabim : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_salsalabim() : CreatureScript("npc_salsalabim") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
creature->SetFaction(FACTION_DEMON);
|
||||
creature->AI()->AttackStart(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_salsalabimAI(creature);
|
||||
}
|
||||
|
||||
struct npc_salsalabimAI : public ScriptedAI
|
||||
{
|
||||
npc_salsalabimAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
uint32 MagneticPull_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
MagneticPull_Timer = 15000;
|
||||
me->RestoreFaction();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* done_by, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
// xinef: some corrections
|
||||
if (done_by)
|
||||
if (Player* player = done_by->GetCharmerOrOwnerPlayerOrPlayerItself())
|
||||
if (me->HealthBelowPctDamaged(20, damage))
|
||||
{
|
||||
player->GroupEventHappens(QUEST_10004, me);
|
||||
damage = 0;
|
||||
EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (MagneticPull_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_MAGNETIC_PULL);
|
||||
MagneticPull_Timer = 15000;
|
||||
}
|
||||
else MagneticPull_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
##################################################
|
||||
Shattrath City Flask Vendors provides flasks to people exalted with 3 fActions:
|
||||
@@ -436,8 +251,6 @@ public:
|
||||
|
||||
void AddSC_shattrath_city()
|
||||
{
|
||||
new npc_raliq_the_drunk();
|
||||
new npc_salsalabim();
|
||||
new npc_shattrathflaskvendors();
|
||||
new npc_zephyr();
|
||||
new npc_kservant();
|
||||
|
||||
@@ -15,22 +15,6 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Terokkar_Forest
|
||||
SD%Complete: 85
|
||||
SDComment: Quest support: 9889, 10009, 10873, 10896, 10898, 11096, 10052, 10051. Skettis->Ogri'la Flight
|
||||
SDCategory: Terokkar Forest
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_unkor_the_ruthless
|
||||
npc_rotting_forest_rager
|
||||
npc_netherweb_victim
|
||||
npc_floon
|
||||
npc_isla_starmane
|
||||
npc_slim
|
||||
EndContentData */
|
||||
|
||||
#include "Group.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
@@ -477,115 +461,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_floon
|
||||
######*/
|
||||
|
||||
#define GOSSIP_FLOON1 "You owe Sim'salabim money. Hand them over or die!"
|
||||
#define GOSSIP_FLOON2 "Hand over the money or die...again!"
|
||||
|
||||
enum Floon
|
||||
{
|
||||
SAY_FLOON_ATTACK = 0,
|
||||
|
||||
SPELL_SILENCE = 6726,
|
||||
SPELL_FROSTBOLT = 9672,
|
||||
SPELL_FROST_NOVA = 11831,
|
||||
|
||||
QUEST_CRACK_SKULLS = 10009
|
||||
};
|
||||
|
||||
class npc_floon : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_floon() : CreatureScript("npc_floon") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF)
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_FLOON2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, 9443, creature->GetGUID());
|
||||
}
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->SetFaction(FACTION_ARAKKOA);
|
||||
creature->AI()->Talk(SAY_FLOON_ATTACK, player);
|
||||
creature->AI()->AttackStart(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE)
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_FLOON1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
|
||||
SendGossipMenuFor(player, 9442, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_floonAI(creature);
|
||||
}
|
||||
|
||||
struct npc_floonAI : public ScriptedAI
|
||||
{
|
||||
npc_floonAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
m_uiNormFaction = creature->GetFaction();
|
||||
}
|
||||
|
||||
uint32 m_uiNormFaction;
|
||||
uint32 Silence_Timer;
|
||||
uint32 Frostbolt_Timer;
|
||||
uint32 FrostNova_Timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Silence_Timer = 2000;
|
||||
Frostbolt_Timer = 4000;
|
||||
FrostNova_Timer = 9000;
|
||||
if (me->GetFaction() != m_uiNormFaction)
|
||||
me->SetFaction(m_uiNormFaction);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (Silence_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SILENCE);
|
||||
Silence_Timer = 30000;
|
||||
}
|
||||
else Silence_Timer -= diff;
|
||||
|
||||
if (FrostNova_Timer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FROST_NOVA);
|
||||
FrostNova_Timer = 20000;
|
||||
}
|
||||
else FrostNova_Timer -= diff;
|
||||
|
||||
if (Frostbolt_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FROSTBOLT);
|
||||
Frostbolt_Timer = 5000;
|
||||
}
|
||||
else Frostbolt_Timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_isla_starmane
|
||||
######*/
|
||||
@@ -840,7 +715,6 @@ void AddSC_terokkar_forest()
|
||||
// Theirs
|
||||
new npc_unkor_the_ruthless();
|
||||
new npc_rotting_forest_rager();
|
||||
new npc_floon();
|
||||
new npc_isla_starmane();
|
||||
new go_skull_pile();
|
||||
new npc_slim();
|
||||
|
||||
@@ -96,24 +96,17 @@ struct npc_pet_hunter_snake_trap : public ScriptedAI
|
||||
{
|
||||
_init = true;
|
||||
|
||||
CreatureTemplate const* Info = me->GetCreatureTemplate();
|
||||
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(me->GetLevel(), Info->unit_class);
|
||||
uint32 health = uint32(107 * (me->GetLevel() - 40) * 0.025f);
|
||||
me->SetCreateHealth(health);
|
||||
|
||||
for (uint8 stat = 0; stat < MAX_STATS; ++stat)
|
||||
{
|
||||
me->SetStat(Stats(stat), 0);
|
||||
me->SetCreateStat(Stats(stat), 0);
|
||||
}
|
||||
|
||||
me->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
|
||||
me->SetMaxHealth(health);
|
||||
|
||||
//Add delta to make them not all hit the same time
|
||||
uint32 delta = urand(0, 700);
|
||||
me->SetAttackTime(BASE_ATTACK, Info->BaseAttackTime + delta);
|
||||
me->SetStatFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER, float(stats->AttackPower));
|
||||
me->CastSpell(me, SPELL_HUNTER_DEADLY_POISON_PASSIVE, true);
|
||||
me->SetAttackTime(BASE_ATTACK, me->GetAttackTime(BASE_ATTACK) + delta);
|
||||
|
||||
if (me->GetEntry() == NPC_VENOMOUS_SNAKE)
|
||||
DoCastSelf(SPELL_HUNTER_DEADLY_POISON_PASSIVE, true);
|
||||
|
||||
// Glyph of Snake Trap
|
||||
if (Unit* owner = me->GetOwner())
|
||||
|
||||
Reference in New Issue
Block a user