Files
azerothcore-wotlk/src/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
talamortis 251adf115f boss_mandokir.cpp
Boss will no longer despawn after he has done his lap and should return to the correct position when Speaker is dead (at the bottom of the stairs)
2016-10-25 19:41:23 +01:00

423 lines
15 KiB
C++

/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*/
/* ScriptData
SDName: Boss_Mandokir
SD%Complete: 90
SDComment: Ohgan function needs improvements.
SDCategory: Zul'Gurub
EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "zulgurub.h"
enum Says
{
SAY_AGGRO = 0,
SAY_DING_KILL = 1,
SAY_WATCH = 2,
SAY_WATCH_WHISPER = 3,
SAY_OHGAN_DEAD = 4,
SAY_GRATS_JINDO = 0,
};
enum Spells
{
SPELL_CHARGE = 24408, // seen
SPELL_OVERPOWER = 24407, // Seen
SPELL_FEAR = 29321,
SPELL_WHIRLWIND = 13736, // Triggers 15589
SPELL_MORTAL_STRIKE = 16856, // Seen
SPELL_FRENZY = 24318, // seen
SPELL_WATCH = 24314, // seen 24315, 24316
SPELL_WATCH_CHARGE = 24315, // Triggers 24316
SPELL_LEVEL_UP = 24312 //
};
enum Events
{
EVENT_CHECK_SPEAKER = 1,
EVENT_CHECK_START = 2,
EVENT_STARTED = 3,
EVENT_OVERPOWER = 4,
EVENT_MORTAL_STRIKE = 5,
EVENT_WHIRLWIND = 6,
EVENT_CHECK_OHGAN = 7,
EVENT_WATCH_PLAYER = 8,
EVENT_CHARGE_PLAYER = 9
};
enum Misc
{
MODEL_OHGAN_MOUNT = 15271,
PATH_MANDOKIR = 492861,
POINT_MANDOKIR_END = 24,
CHAINED_SPIRT_COUNT = 20
};
Position const PosSummonChainedSpirits[CHAINED_SPIRT_COUNT] =
{
{ -12167.17f, -1979.330f, 133.0992f, 2.268928f },
{ -12262.74f, -1953.394f, 133.5496f, 0.593412f },
{ -12176.89f, -1983.068f, 133.7841f, 2.129302f },
{ -12226.45f, -1977.933f, 132.7982f, 1.466077f },
{ -12204.74f, -1890.431f, 135.7569f, 4.415683f },
{ -12216.70f, -1891.806f, 136.3496f, 4.677482f },
{ -12236.19f, -1892.034f, 134.1041f, 5.044002f },
{ -12248.24f, -1893.424f, 134.1182f, 5.270895f },
{ -12257.36f, -1897.663f, 133.1484f, 5.462881f },
{ -12265.84f, -1903.077f, 133.1649f, 5.654867f },
{ -12158.69f, -1972.707f, 133.8751f, 2.408554f },
{ -12178.82f, -1891.974f, 134.1786f, 3.944444f },
{ -12193.36f, -1890.039f, 135.1441f, 4.188790f },
{ -12275.59f, -1932.845f, 134.9017f, 0.174533f },
{ -12273.51f, -1941.539f, 136.1262f, 0.314159f },
{ -12247.02f, -1963.497f, 133.9476f, 0.872665f },
{ -12238.68f, -1969.574f, 133.6273f, 1.134464f },
{ -12192.78f, -1982.116f, 132.6966f, 1.919862f },
{ -12210.81f, -1979.316f, 133.8700f, 1.797689f },
{ -12283.51f, -1924.839f, 133.5170f, 0.069813f }
};
Position const PosMandokir[2] =
{
{ -12167.8f, -1927.25f, 153.73f, 3.76991f },
{ -12197.86f, -1949.392f, 130.2745f, 0.0f }
};
class boss_mandokir : public CreatureScript
{
public: boss_mandokir() : CreatureScript("boss_mandokir") { }
struct boss_mandokirAI : public BossAI
{
boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_MANDOKIR) { }
void Reset()
{
if (me->GetPositionZ() > 140.0f)
{
killCount = 0;
events.ScheduleEvent(EVENT_CHECK_START, 1000);
if (Creature* speaker = ObjectAccessor::GetCreature(*me, instance->GetData64(NPC_VILEBRANCH_SPEAKER)))
if (!speaker->IsAlive())
speaker->Respawn(true);
}
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
summons.DespawnAll();
me->Mount(MODEL_OHGAN_MOUNT);
}
void JustDied(Unit* /*killer*/)
{
// Do not want to unsummon Ohgan
for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
if (Creature* unsummon = ObjectAccessor::GetCreature(*me, chainedSpirtGUIDs[i]))
unsummon->DespawnOrUnsummon();
instance->SetBossState(DATA_MANDOKIR, DONE);
instance->SaveToDB();
}
void EnterCombat(Unit* /*who*/)
{
_EnterCombat();
events.ScheduleEvent(EVENT_OVERPOWER, urand(7000, 9000));
events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
events.ScheduleEvent(EVENT_WHIRLWIND, urand(24000, 30000));
events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(13000, 15000));
events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(33000, 38000));
me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
Talk(SAY_AGGRO);
me->Dismount();
// Summon Ohgan (Spell missing) TEMP HACK
me->SummonCreature(NPC_OHGAN, me->GetPositionX()-3, me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
// Summon Chained Spirits
for (int i = 0; i < CHAINED_SPIRT_COUNT; ++i)
{
Creature* chainedSpirt = me->SummonCreature(NPC_CHAINED_SPIRT, PosSummonChainedSpirits[i], TEMPSUMMON_CORPSE_DESPAWN);
chainedSpirtGUIDs[i] = chainedSpirt->GetGUID();
}
DoZoneInCombat();
}
void KilledUnit(Unit* victim)
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
if (++killCount == 3)
{
Talk(SAY_DING_KILL);
if (Creature* jindo = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_JINDO)))
if (jindo->IsAlive())
jindo->AI()->Talk(SAY_GRATS_JINDO);
DoCast(me, SPELL_LEVEL_UP, true);
killCount = 0;
}
}
void MovementInform(uint32 type, uint32 id)
{
if (type == WAYPOINT_MOTION_TYPE)
{
me->SetWalk(false);
if (id == POINT_MANDOKIR_END)
{
me->SetHomePosition(PosMandokir[0]);
instance->SetBossState(DATA_MANDOKIR, NOT_STARTED);
}
}
}
void UpdateAI(uint32 diff)
{
events.Update(diff);
if (!UpdateVictim())
{
if (instance->GetBossState(DATA_MANDOKIR) == NOT_STARTED || instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
{
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_CHECK_START:
if (instance->GetBossState(DATA_MANDOKIR) == SPECIAL)
{
me->GetMotionMaster()->MovePoint(0, PosMandokir[1].m_positionX, PosMandokir[1].m_positionY, PosMandokir[1].m_positionZ);
events.ScheduleEvent(EVENT_STARTED, 6000);
}
else
events.ScheduleEvent(EVENT_CHECK_START, 1000);
break;
case EVENT_STARTED:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC);
break;
default:
break;
}
}
}
return;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_OVERPOWER:
DoCastVictim(SPELL_OVERPOWER, true);
events.ScheduleEvent(EVENT_OVERPOWER, urand(6000, 12000));
break;
case EVENT_MORTAL_STRIKE:
if (me->GetVictim() && me->GetVictim()->HealthBelowPct(50))
DoCastVictim(SPELL_MORTAL_STRIKE, true);
events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(12000, 18000));
break;
case EVENT_WHIRLWIND:
DoCast(me, SPELL_WHIRLWIND);
events.ScheduleEvent(EVENT_WHIRLWIND, urand(22000, 26000));
break;
case EVENT_CHECK_OHGAN:
if (instance->GetBossState(DATA_OHGAN) == DONE)
{
DoCast(me, SPELL_FRENZY);
Talk(SAY_OHGAN_DEAD);
}
else
events.ScheduleEvent(EVENT_CHECK_OHGAN, 1000);
break;
case EVENT_WATCH_PLAYER:
if (Unit* player = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
{
DoCast(player, SPELL_WATCH);
Talk(SAY_WATCH, player);
}
events.ScheduleEvent(EVENT_WATCH_PLAYER, urand(12000, 15000));
break;
case EVENT_CHARGE_PLAYER:
DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true), SPELL_CHARGE);
events.ScheduleEvent(EVENT_CHARGE_PLAYER, urand(22000, 30000));
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint8 killCount;
uint64 chainedSpirtGUIDs[CHAINED_SPIRT_COUNT];
};
CreatureAI* GetAI(Creature* creature) const
{
return GetZulGurubAI<boss_mandokirAI>(creature);
}
};
// Ohgan
enum OhganSpells
{
SPELL_SUNDERARMOR = 24317
};
class npc_ohgan : public CreatureScript
{
public: npc_ohgan() : CreatureScript("npc_ohgan") { }
struct npc_ohganAI : public ScriptedAI
{
npc_ohganAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
void Reset()
{
SunderArmor_Timer = 5000;
}
void EnterCombat(Unit* /*who*/) { }
void JustDied(Unit* /*killer*/)
{
instance->SetBossState(DATA_OHGAN, DONE);
}
void UpdateAI(uint32 diff)
{
// Return since we have no target
if (!UpdateVictim())
return;
if (SunderArmor_Timer <= diff)
{
DoCastVictim(SPELL_SUNDERARMOR, true);
SunderArmor_Timer = urand(10000, 15000);
} else SunderArmor_Timer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 SunderArmor_Timer;
InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetZulGurubAI<npc_ohganAI>(creature);
}
};
enum VilebranchSpells
{
SPELL_DEMORALIZING_SHOUT = 13730,
SPELL_CLEAVE = 15284
};
class npc_vilebranch_speaker : public CreatureScript
{
public: npc_vilebranch_speaker() : CreatureScript("npc_vilebranch_speaker") { }
struct npc_vilebranch_speakerAI : public ScriptedAI
{
npc_vilebranch_speakerAI(Creature* creature) : ScriptedAI(creature), instance(creature->GetInstanceScript()) { }
void Reset()
{
demoralizing_Shout_Timer = urand(2000, 4000);
cleave_Timer = urand(5000, 8000);
}
void EnterCombat(Unit* /*who*/) { }
void JustDied(Unit* /*killer*/)
{
instance->SetBossState(DATA_MANDOKIR, SPECIAL);
}
void UpdateAI(uint32 diff)
{
// Return since we have no target
if (!UpdateVictim())
return;
if (demoralizing_Shout_Timer <= diff)
{
DoCast(me, SPELL_DEMORALIZING_SHOUT);
demoralizing_Shout_Timer = urand(22000, 30000);
} else demoralizing_Shout_Timer -= diff;
if (cleave_Timer <= diff)
{
DoCastVictim(SPELL_CLEAVE, true);
cleave_Timer = urand(6000, 9000);
} else cleave_Timer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 demoralizing_Shout_Timer;
uint32 cleave_Timer;
InstanceScript* instance;
};
CreatureAI* GetAI(Creature* creature) const
{
return GetInstanceAI<npc_vilebranch_speakerAI>(creature);
}
};
class spell_threatening_gaze : public SpellScriptLoader
{
public:
spell_threatening_gaze() : SpellScriptLoader("spell_threatening_gaze") { }
class spell_threatening_gaze_AuraScript : public AuraScript
{
PrepareAuraScript(spell_threatening_gaze_AuraScript);
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
if (Unit* target = GetTarget())
if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
caster->CastSpell(target, SPELL_WATCH_CHARGE);
}
void Register()
{
OnEffectRemove += AuraEffectRemoveFn(spell_threatening_gaze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const
{
return new spell_threatening_gaze_AuraScript();
}
};
void AddSC_boss_mandokir()
{
new boss_mandokir();
new npc_ohgan();
new npc_vilebranch_speaker();
new spell_threatening_gaze();
}