525 lines
19 KiB
C++
525 lines
19 KiB
C++
/*
|
|
* 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 "halls_of_stone.h"
|
|
#include "Player.h"
|
|
#include "ScriptedCreature.h"
|
|
#include "ScriptMgr.h"
|
|
|
|
enum Spells
|
|
{
|
|
// SJONNIR
|
|
SPELL_FRENZY = 28747, //at 20% hp
|
|
SPELL_CHAIN_LIGHTNING = 50830,
|
|
SPELL_CHAIN_LIGHTNING_H = 59844,
|
|
SPELL_LIGHTNING_SHIELD = 50831,
|
|
SPELL_LIGHTNING_SHIELD_H = 59845,
|
|
SPELL_STATIC_CHARGE = 50834,
|
|
SPELL_STATIC_CHARGE_H = 59846,
|
|
SPELL_LIGHTNING_RING = 50840,
|
|
SPELL_LIGHTNING_RING_H = 59848,
|
|
|
|
// IRON SLUDGE
|
|
SPELL_TOXIC_VOLLEY = 50838,
|
|
SPELL_TOXIC_VOLLEY_H = 59853,
|
|
|
|
// FORGED IRON DWARF
|
|
SPELL_LIGHTNING_TETHER = 50895,
|
|
SPELL_LIGHTNING_TETHER_H = 59851,
|
|
|
|
// FORGED IRON TROGG
|
|
SPELL_LIGHTNING_SHOCK = 50900,
|
|
SPELL_LIGHTNING_SHOCK_H = 59852,
|
|
};
|
|
|
|
enum Npc
|
|
{
|
|
NPC_IRON_SLUDGE = 28165, // if 2 ooze then spawn 1 iron_sludge
|
|
NPC_DWARFES_FRIENDLY = 27980, //after fix the machine by Brann
|
|
NPC_OOZE = 27981, //spawn after killing dwarf
|
|
NPC_FORGED_IRON_DWARF = 27982,
|
|
NPC_FORGED_IRON_TROGG = 27979,
|
|
};
|
|
|
|
enum Yells
|
|
{
|
|
SAY_AGGRO = 0,
|
|
SAY_SLAY = 1,
|
|
SAY_DEATH = 2
|
|
};
|
|
|
|
enum Events
|
|
{
|
|
// SJONNIR
|
|
EVENT_SHIELD = 1,
|
|
EVENT_CHAIN_LIGHTNING = 2,
|
|
EVENT_STATIC_CHARGE = 3,
|
|
EVENT_LIGHTNING_RING = 4,
|
|
EVENT_CHECK_HEALTH = 5,
|
|
EVENT_SUMMON = 6,
|
|
EVENT_SUMMON_SPEACH = 7,
|
|
|
|
// TRASH
|
|
EVENT_MALFORMED_OOZE_CHECK = 10,
|
|
EVENT_TOXIC_VOLLEY = 11,
|
|
EVENT_FORGED_LIGHTNING_SHOCK = 12,
|
|
EVENT_FORGED_LIGHTNING_TETHER = 13,
|
|
};
|
|
|
|
enum Misc
|
|
{
|
|
POS_GEN_RIGHT = 0,
|
|
POS_GEN_LEFT = 1,
|
|
POS_ROOM_CENTER = 2,
|
|
|
|
// ACTIONS
|
|
ACTION_SLUG_KILLED = 1,
|
|
};
|
|
|
|
enum SummonPhases
|
|
{
|
|
PHASE_SUMMON_UNFRIENDLY_DWARFES = 0,
|
|
PHASE_SUMMON_OOZE = 1,
|
|
PHASE_SUMMON_FRIENDLY_DWARFES = 2,
|
|
};
|
|
|
|
static Position RoomPosition[] =
|
|
{
|
|
{1293.0f, 610.0f, 199.3f, 0.0f},
|
|
{1294.2f, 724.3f, 199.3f, 0.0f},
|
|
{1295.2f, 667.1f, 189.7f, 0.0f},
|
|
};
|
|
|
|
class boss_sjonnir : public CreatureScript
|
|
{
|
|
public:
|
|
boss_sjonnir() : CreatureScript("boss_sjonnir") { }
|
|
|
|
CreatureAI* GetAI(Creature* pCreature) const override
|
|
{
|
|
return GetHallsOfStoneAI<boss_sjonnirAI>(pCreature);
|
|
}
|
|
|
|
struct boss_sjonnirAI : public ScriptedAI
|
|
{
|
|
boss_sjonnirAI(Creature* c) : ScriptedAI(c), summons(me)
|
|
{
|
|
pInstance = c->GetInstanceScript();
|
|
}
|
|
|
|
InstanceScript* pInstance;
|
|
EventMap events;
|
|
SummonList summons;
|
|
|
|
uint8 SummonPhase;
|
|
uint8 SlugeCount;
|
|
|
|
void Reset() override
|
|
{
|
|
events.Reset();
|
|
summons.DespawnAll();
|
|
|
|
SlugeCount = 0;
|
|
SummonPhase = PHASE_SUMMON_UNFRIENDLY_DWARFES;
|
|
|
|
if (pInstance)
|
|
{
|
|
pInstance->SetData(BOSS_SJONNIR, NOT_STARTED);
|
|
pInstance->SetData(DATA_SJONNIR_ACHIEVEMENT, false);
|
|
|
|
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
if (pInstance->GetData(BOSS_TRIBUNAL_OF_AGES) == DONE)
|
|
{
|
|
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
|
if (GameObject* doors = me->GetMap()->GetGameObject(pInstance->GetGuidData(GO_SJONNIR_DOOR)))
|
|
doors->SetGoState(GO_STATE_ACTIVE);
|
|
|
|
if (GameObject* console = me->GetMap()->GetGameObject( pInstance->GetGuidData(GO_SJONNIR_CONSOLE)))
|
|
console->SetGoState(GO_STATE_READY);
|
|
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
{
|
|
brann->setDeathState(JUST_DIED);
|
|
brann->Respawn();
|
|
brann->AI()->DoAction(5);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnterCombat(Unit* /*who*/) override
|
|
{
|
|
Talk(SAY_AGGRO);
|
|
|
|
events.ScheduleEvent(EVENT_CHECK_HEALTH, 1000);
|
|
events.ScheduleEvent(EVENT_SHIELD, 14000 + rand() % 5000);
|
|
events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 6000 + rand() % 6000);
|
|
events.ScheduleEvent(EVENT_STATIC_CHARGE, 24000);
|
|
events.ScheduleEvent(EVENT_LIGHTNING_RING, 25000 + rand() % 6000);
|
|
events.ScheduleEvent(EVENT_SUMMON, 20000);
|
|
events.ScheduleEvent(EVENT_SUMMON, 21500);
|
|
events.ScheduleEvent(EVENT_SUMMON_SPEACH, 20000);
|
|
|
|
if (pInstance)
|
|
{
|
|
pInstance->SetData(BOSS_SJONNIR, IN_PROGRESS);
|
|
|
|
if (GameObject* doors = me->GetMap()->GetGameObject(pInstance->GetGuidData(GO_SJONNIR_DOOR)))
|
|
doors->SetGoState(GO_STATE_READY);
|
|
|
|
if (pInstance->GetData(BOSS_TRIBUNAL_OF_AGES) == DONE)
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
brann->AI()->DoAction(3);
|
|
}
|
|
}
|
|
|
|
void DoAction(int32 param) override
|
|
{
|
|
if (param == ACTION_SLUG_KILLED)
|
|
{
|
|
SlugeCount++;
|
|
if (SlugeCount >= 5 && pInstance)
|
|
pInstance->SetData(DATA_SJONNIR_ACHIEVEMENT, true);
|
|
}
|
|
}
|
|
|
|
void UpdateAI(uint32 diff) override
|
|
{
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
events.Update(diff);
|
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
return;
|
|
|
|
switch (events.ExecuteEvent())
|
|
{
|
|
case EVENT_CHECK_HEALTH:
|
|
{
|
|
if (SummonPhase == PHASE_SUMMON_UNFRIENDLY_DWARFES && HealthBelowPct(50))
|
|
{
|
|
SummonPhase = PHASE_SUMMON_OOZE;
|
|
events.CancelEvent(EVENT_SUMMON);
|
|
events.ScheduleEvent(EVENT_SUMMON, 0);
|
|
events.ScheduleEvent(EVENT_SUMMON, 1500);
|
|
|
|
if (pInstance)
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
{
|
|
brann->Yell("What in the name o' Madoran did THAT do? Oh! Wait: I just about got it...", LANG_UNIVERSAL);
|
|
brann->PlayDirectSound(14276);
|
|
}
|
|
}
|
|
|
|
if (HealthBelowPct(20))
|
|
{
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
{
|
|
brann->Yell("Ha, that did it! Help's a-comin'! Take this, ya glowin' iron brute!", LANG_UNIVERSAL);
|
|
brann->PlayDirectSound(14277);
|
|
}
|
|
SummonPhase = PHASE_SUMMON_FRIENDLY_DWARFES;
|
|
me->CastSpell(me, SPELL_FRENZY, false);
|
|
|
|
events.CancelEvent(EVENT_SUMMON);
|
|
events.ScheduleEvent(EVENT_SUMMON, 0);
|
|
break;
|
|
}
|
|
|
|
events.RepeatEvent(1000);
|
|
break;
|
|
}
|
|
case EVENT_SHIELD:
|
|
{
|
|
me->CastSpell(me, DUNGEON_MODE(SPELL_LIGHTNING_SHIELD, SPELL_LIGHTNING_SHIELD_H), false);
|
|
events.RepeatEvent(14000 + rand() % 5000);
|
|
break;
|
|
}
|
|
case EVENT_CHAIN_LIGHTNING:
|
|
{
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true, 0))
|
|
me->CastSpell(target, DUNGEON_MODE(SPELL_CHAIN_LIGHTNING, SPELL_CHAIN_LIGHTNING_H), false);
|
|
|
|
events.RepeatEvent(6000 + rand() % 6000);
|
|
break;
|
|
}
|
|
case EVENT_STATIC_CHARGE:
|
|
{
|
|
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true, 0))
|
|
me->CastSpell(target, DUNGEON_MODE(SPELL_STATIC_CHARGE, SPELL_STATIC_CHARGE_H), false);
|
|
|
|
events.RepeatEvent(20000);
|
|
break;
|
|
}
|
|
case EVENT_LIGHTNING_RING:
|
|
{
|
|
me->CastSpell(me, DUNGEON_MODE(SPELL_LIGHTNING_RING, SPELL_LIGHTNING_RING_H), false);
|
|
events.RepeatEvent(25000 + rand() % 6000);
|
|
events.DelayEvents(10000); // Channel duration
|
|
break;
|
|
}
|
|
case EVENT_SUMMON_SPEACH:
|
|
{
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
{
|
|
brann->Yell("This is a wee bit trickier that before... Oh, bloody--incomin'!", LANG_UNIVERSAL);
|
|
brann->PlayDirectSound(14275);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case EVENT_SUMMON:
|
|
{
|
|
switch (SummonPhase)
|
|
{
|
|
case PHASE_SUMMON_UNFRIENDLY_DWARFES:
|
|
{
|
|
SummonDwarfes(false);
|
|
events.RepeatEvent(20000);
|
|
break;
|
|
}
|
|
case PHASE_SUMMON_OOZE:
|
|
{
|
|
for (uint8 i = POS_GEN_RIGHT; i <= POS_GEN_LEFT; i++)
|
|
{
|
|
if (Creature* ooze = me->SummonCreature(NPC_OOZE, RoomPosition[i].GetPositionX(), RoomPosition[i].GetPositionY(), RoomPosition[i].GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
|
|
{
|
|
ActivatePipe(i);
|
|
ooze->GetMotionMaster()->MovePoint(0, RoomPosition[POS_ROOM_CENTER].GetPositionX(), RoomPosition[POS_ROOM_CENTER].GetPositionY(), RoomPosition[POS_ROOM_CENTER].GetPositionZ());
|
|
summons.Summon(ooze);
|
|
}
|
|
}
|
|
events.RepeatEvent(10000);
|
|
break;
|
|
}
|
|
case PHASE_SUMMON_FRIENDLY_DWARFES:
|
|
{
|
|
SummonDwarfes(true);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
|
|
void JustDied(Unit* /*killer*/) override
|
|
{
|
|
Talk(SAY_DEATH);
|
|
|
|
summons.DespawnAll();
|
|
if (pInstance)
|
|
{
|
|
pInstance->SetData(BOSS_SJONNIR, DONE);
|
|
if (GameObject* sd = me->GetMap()->GetGameObject(pInstance->GetGuidData(GO_SJONNIR_DOOR)))
|
|
sd->SetGoState(GO_STATE_ACTIVE);
|
|
|
|
if (Creature* brann = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_BRANN)))
|
|
brann->AI()->DoAction(4);
|
|
}
|
|
}
|
|
|
|
void KilledUnit(Unit* /*victim*/) override
|
|
{
|
|
if (urand(0, 1))
|
|
return;
|
|
|
|
Talk(SAY_SLAY);
|
|
}
|
|
|
|
void ActivatePipe(uint8 side)
|
|
{
|
|
if (pInstance)
|
|
if (GameObject* pipe = me->GetMap()->GetGameObject(pInstance->GetGuidData(side == POS_GEN_RIGHT ? GO_RIGHT_PIPE : GO_LEFT_PIPE)))
|
|
pipe->SendCustomAnim(0);
|
|
}
|
|
|
|
void SummonDwarfes(bool friendly)
|
|
{
|
|
if (friendly)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
uint8 Pos = urand(POS_GEN_RIGHT, POS_GEN_LEFT);
|
|
if (Creature* dwarf = me->SummonCreature(NPC_DWARFES_FRIENDLY, RoomPosition[Pos].GetPositionX(), RoomPosition[Pos].GetPositionY(), RoomPosition[Pos].GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
|
|
{
|
|
if (Player* plr = SelectTargetFromPlayerList(100.0f))
|
|
dwarf->setFaction(plr->getFaction());
|
|
|
|
ActivatePipe(Pos);
|
|
dwarf->AI()->AttackStart(me);
|
|
summons.Summon(dwarf);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
uint8 Pos = urand(POS_GEN_RIGHT, POS_GEN_LEFT);
|
|
if (Creature* dwarf = me->SummonCreature(urand(0, 1) ? NPC_FORGED_IRON_TROGG : NPC_FORGED_IRON_DWARF, RoomPosition[Pos].GetPositionX(), RoomPosition[Pos].GetPositionY(), RoomPosition[Pos].GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
|
|
{
|
|
ActivatePipe(Pos);
|
|
dwarf->SetInCombatWithZone();
|
|
summons.Summon(dwarf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
class boss_sjonnir_dwarf : public CreatureScript
|
|
{
|
|
public:
|
|
boss_sjonnir_dwarf() : CreatureScript("boss_sjonnir_dwarf") { }
|
|
|
|
CreatureAI* GetAI(Creature* pCreature) const override
|
|
{
|
|
return GetHallsOfStoneAI<boss_sjonnir_dwarfAI>(pCreature);
|
|
}
|
|
|
|
struct boss_sjonnir_dwarfAI : public ScriptedAI
|
|
{
|
|
boss_sjonnir_dwarfAI(Creature* c) : ScriptedAI(c) { }
|
|
|
|
void UpdateAI(uint32 /*diff*/) override
|
|
{
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
DoSpellAttackIfReady((me->GetEntry() == NPC_FORGED_IRON_DWARF) ? DUNGEON_MODE(SPELL_LIGHTNING_TETHER, SPELL_LIGHTNING_TETHER_H) : DUNGEON_MODE(SPELL_LIGHTNING_SHOCK, SPELL_LIGHTNING_SHOCK_H));
|
|
}
|
|
};
|
|
};
|
|
|
|
class boss_sjonnir_iron_sludge : public CreatureScript
|
|
{
|
|
public:
|
|
boss_sjonnir_iron_sludge() : CreatureScript("boss_sjonnir_iron_sludge") { }
|
|
|
|
CreatureAI* GetAI(Creature* pCreature) const override
|
|
{
|
|
return GetHallsOfStoneAI<boss_sjonnir_iron_sludgeAI>(pCreature);
|
|
}
|
|
|
|
struct boss_sjonnir_iron_sludgeAI : public ScriptedAI
|
|
{
|
|
boss_sjonnir_iron_sludgeAI(Creature* c) : ScriptedAI(c) { }
|
|
|
|
EventMap events;
|
|
void Reset() override
|
|
{
|
|
events.Reset();
|
|
}
|
|
|
|
void EnterCombat(Unit*) override
|
|
{
|
|
events.ScheduleEvent(EVENT_TOXIC_VOLLEY, 5000);
|
|
}
|
|
void JustDied(Unit* /*killer*/) override
|
|
{
|
|
if (InstanceScript* pInstance = me->GetInstanceScript())
|
|
if (Creature* sjonnir = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(NPC_SJONNIR)))
|
|
sjonnir->AI()->DoAction(ACTION_SLUG_KILLED);
|
|
}
|
|
void UpdateAI(uint32 diff) override
|
|
{
|
|
if (!UpdateVictim())
|
|
return;
|
|
|
|
events.Update(diff);
|
|
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
return;
|
|
|
|
switch (events.ExecuteEvent())
|
|
{
|
|
// Every 5 seconds
|
|
case EVENT_TOXIC_VOLLEY:
|
|
{
|
|
me->CastSpell(me, DUNGEON_MODE(SPELL_TOXIC_VOLLEY, SPELL_TOXIC_VOLLEY_H), false);
|
|
events.RepeatEvent(5000);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DoMeleeAttackIfReady();
|
|
}
|
|
};
|
|
};
|
|
|
|
//OOZE
|
|
class boss_sjonnir_malformed_ooze : public CreatureScript
|
|
{
|
|
public:
|
|
boss_sjonnir_malformed_ooze() : CreatureScript("boss_sjonnir_malformed_ooze") { }
|
|
|
|
CreatureAI* GetAI(Creature* pCreature) const override
|
|
{
|
|
return GetHallsOfStoneAI<boss_sjonnir_malformed_oozeAI>(pCreature);
|
|
}
|
|
|
|
struct boss_sjonnir_malformed_oozeAI : public ScriptedAI
|
|
{
|
|
boss_sjonnir_malformed_oozeAI(Creature* c) : ScriptedAI(c) { }
|
|
|
|
EventMap events;
|
|
void MovementInform(uint32 type, uint32 point) override
|
|
{
|
|
if (type == POINT_MOTION_TYPE && point == 0)
|
|
events.RescheduleEvent(EVENT_MALFORMED_OOZE_CHECK, 1000);
|
|
}
|
|
|
|
void EnterCombat(Unit*) override { }
|
|
void MoveInLineOfSight(Unit*) override { }
|
|
|
|
void UpdateAI(uint32 diff) override
|
|
{
|
|
events.Update(diff);
|
|
switch (events.ExecuteEvent())
|
|
{
|
|
case EVENT_MALFORMED_OOZE_CHECK:
|
|
{
|
|
std::list<Creature*> oozeList;
|
|
me->GetCreaturesWithEntryInRange(oozeList, 5.0f, NPC_OOZE);
|
|
for (std::list<Creature*>::const_iterator itr = oozeList.begin(); itr != oozeList.end(); ++itr)
|
|
if ((*itr)->GetGUID() != me->GetGUID() && (*itr)->IsAlive() && me->IsAlive())
|
|
if (Creature* is = me->SummonCreature(NPC_IRON_SLUDGE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000))
|
|
{
|
|
Unit::Kill(me, me);
|
|
Unit::Kill(*itr, *itr);
|
|
is->SetInCombatWithZone();
|
|
break;
|
|
}
|
|
|
|
events.RepeatEvent(1000);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
void AddSC_boss_sjonnir()
|
|
{
|
|
new boss_sjonnir();
|
|
new boss_sjonnir_dwarf();
|
|
new boss_sjonnir_malformed_ooze();
|
|
new boss_sjonnir_iron_sludge();
|
|
}
|