Scripts/ZG: reworked, fixed and finished Bloodlord Mandokir encounter

This commit is contained in:
Ovahlord committed 2018-09-16 20:55:56 +02:00
1 parent 8666fe27b5
commit 282d8c7001
5 files changed
+747 -775

No files matched your search

@@ -0,0 +1,29 @@
-- Template Updates
-- Bloodlord Mandokir
UPDATE `creature_template` SET `ScriptName`= 'boss_bloodlord_mandokir' WHERE `ScriptName`= 'boss_mandokir';
UPDATE `creature_template` SET `DamageModifier`= 60, `BaseVariance`= 0.5, `mechanic_immune_mask`= 617299839, `mingold`= 20000, `maxgold`= 21000, `lootid`= 52151 WHERE `entry`= 52151;
-- Ohgan
UPDATE `creature_template` SET `ScriptName`= 'npc_mandokir_ohgan' WHERE `ScriptName`= 'npc_ohgan';
UPDATE `creature_template` SET `DamageModifier`= 60, `BaseVariance`= 0.5, `mechanic_immune_mask`= 617299839 WHERE `entry`= 52157;
-- Chained Spirit
UPDATE `creature_template` SET `ScriptName`= 'npc_mandokir_chained_spirit' WHERE `ScriptName`= 'npc_chained_spirit';
-- Template Addons
UPDATE `creature_template_addon` SET `mount`= 34408 WHERE `entry`= 52151;
-- Loot
DELETE FROM `creature_onkill_reward` WHERE `creature_id`= 52151;
INSERT INTO `creature_onkill_reward` (`creature_id`, `CurrencyId1`, `CurrencyCount1`) VALUES
(52151, 395, 7000);
DELETE FROM `creature_loot_template` WHERE `Entry`= 52151;
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `Reference`, `MaxCount`) VALUES
(52151, 521510, 100, 1, 521510, 1);
DELETE FROM `reference_loot_template` WHERE `Entry`= 521510;
INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Chance`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
(521510, 69609, 0, 1, 1, 1, 1),
(521510, 69607, 0, 1, 1, 1, 1),
(521510, 69605, 0, 1, 1, 1, 1),
(521510, 69606, 0, 1, 1, 1, 1),
(521510, 69608, 0, 1, 1, 1, 1);
@@ -0,0 +1,705 @@
/*
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 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 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 "GridNotifiers.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "zulgurub.h"
enum Yells
{
SAY_AGGRO = 0,
SAY_PLAYER_KILL = 1,
SAY_SUMMON_OHGAN = 2,
EMOTE_DEVASTATING_SLAM = 3,
SAY_REANIMATE_OHGAN = 4,
EMOTE_FRENZY = 5,
SAY_FRENZY = 6,
SAY_DEATH = 7
};
enum Spells
{
// Bloodlord Mandokir
SPELL_BLOODLORD_AURA = 96480,
SPELL_SUMMON_OHGAN = 96717,
SPELL_REANIMATE_OHGAN = 96724,
SPELL_DECAPITATE = 96682,
SPELL_BLOODLETTING = 96776,
SPELL_BLOODLETTING_DAMAGE = 96777,
SPELL_BLOODLETTING_HEAL = 96778,
SPELL_FRENZY = 96800,
SPELL_LEVEL_UP = 96662,
SPELL_DEVASTATING_SLAM = 96740,
SPELL_DEVASTATING_SLAM_TRIGGER = 96761,
SPELL_DEVASTATING_SLAM_DAMAGE = 97385,
SPELL_SPIRIT_VENGEANCE_CANCEL = 96821,
// Chained Spirit
SPELL_REVIVE = 96484,
// Ohgan
SPELL_OHGAN_HEART_VISUAL = 96727,
SPELL_PERMANENT_FEIGN_DEATH = 96733,
SPELL_CLEAR_ALL = 28471,
SPELL_OHGAN_ORDERS = 96721,
SPELL_OHGAN_ORDERS_TRIGGER = 96722
};
enum Events
{
// Bloodlord Mandokir
EVENT_SUMMON_OHGAN = 1,
EVENT_TALK_SUMMON_OHGAN,
EVENT_DECAPITATE,
EVENT_BLOODLETTING,
EVENT_REANIMATE_OHGAN,
EVENT_REANIMATE_OHGAN_COOLDOWN,
EVENT_DEVASTATING_SLAM,
// Ohgan
EVENT_OHGANS_ORDERS,
EVENT_ATTACK_PLAYERS,
};
enum Action
{
// Bloodlord Mandokir
ACTION_OHGAN_IS_DEATH = 1,
ACTION_START_REVIVE = 2,
// Chained Spirit
ACTION_REVIVE = 1
};
enum Misc
{
POINT_START_REVIVE = 1,
DATA_OHGANOT_SO_FAST = 5762,
FACTION_TEMPLATE_CHAINED_SPIRITS = 1665
};
enum SummonGroups
{
SUMMON_GROUP_CHAINED_SPIRIT = 0
};
struct boss_bloodlord_mandokir : public BossAI
{
boss_bloodlord_mandokir(Creature* creature) : BossAI(creature, DATA_BLOODLORD_MANDOKIR) { }
void Reset() override
{
_Reset();
me->SummonCreatureGroup(SUMMON_GROUP_CHAINED_SPIRIT);
_ohganotSoFast = true;
_reanimateOhganCooldown = false;
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
Talk(SAY_AGGRO);
instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me);
DoCastAOE(SPELL_BLOODLORD_AURA);
events.ScheduleEvent(EVENT_DECAPITATE, 10s);
events.ScheduleEvent(EVENT_BLOODLETTING, 15s);
events.ScheduleEvent(EVENT_SUMMON_OHGAN, 20s);
events.ScheduleEvent(EVENT_DEVASTATING_SLAM, 25s);
for (ObjectGuid guid : summons)
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
if (creature->GetEntry() == NPC_CHAINED_SPIRIT)
creature->SetFaction(FACTION_TEMPLATE_CHAINED_SPIRITS);
}
void JustDied(Unit* /*killer*/) override
{
DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL, true);
_JustDied();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOODLETTING);
Talk(SAY_DEATH);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
_EnterEvadeMode();
summons.DespawnAll();
instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOODLETTING);
DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL, true);
_DespawnAtEvade();
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_PLAYER_KILL);
DoCastSelf(SPELL_LEVEL_UP, true);
_reviveGUID = victim->GetGUID();
DoAction(ACTION_START_REVIVE);
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
if (summon->GetEntry() == NPC_DEVASTATING_SLAM)
{
DoCastSelf(SPELL_DEVASTATING_SLAM);
me->SetFacingToObject(summon);
float angle = me->GetAngle(summon);
// 31 casts in total - 11 in the center line and 10 on the outer lines
for (uint8 i = 1; i < 12; i++)
{
float angleOffset = i > 1 ? -0.3f : 0.0f;
for (uint8 j = 0; j < (i > 1 ? 3 : 1); j++)
{
float x = me->GetPositionX() + cos(angle + angleOffset) * (i * 6.0f);
float y = me->GetPositionY() + sin(angle + angleOffset) * (i * 6.0f);
float z = me->GetPositionZ();
angleOffset += 0.3f;
me->CastSpell(x, y, z, SPELL_DEVASTATING_SLAM_DAMAGE, true);
}
}
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthBelowPctDamaged(20, damage) && !me->HasAura(SPELL_FRENZY))
{
DoCast(me, SPELL_FRENZY, true);
Talk(SAY_FRENZY);
Talk(EMOTE_FRENZY);
}
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_OHGAN_IS_DEATH:
events.ScheduleEvent(EVENT_REANIMATE_OHGAN, 4s);
_ohganotSoFast = false;
break;
case ACTION_START_REVIVE:
{
std::list<Creature*> creatures;
GetCreatureListWithEntryInGrid(creatures, me, NPC_CHAINED_SPIRIT, 200.0f);
creatures.remove_if(Trinity::AnyDeadUnitCheck());
creatures.remove_if(Trinity::UnitAuraCheck(true, SPELL_OHGAN_ORDERS_TRIGGER));
Trinity::Containers::RandomResize(creatures, 1);
if (creatures.empty())
return;
for (Creature* chainedSpirit : creatures)
{
chainedSpirit->AI()->SetGUID(_reviveGUID);
chainedSpirit->AI()->DoAction(ACTION_REVIVE);
_reviveGUID.Clear();
}
break;
}
default:
break;
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_OHGANOT_SO_FAST)
return _ohganotSoFast;
return 0;
}
void SetGUID(ObjectGuid const& guid, int32 /*id = 0 **/) override
{
_reviveGUID = guid;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SUMMON_OHGAN:
me->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
DoCast(me, SPELL_SUMMON_OHGAN, true);
events.ScheduleEvent(EVENT_TALK_SUMMON_OHGAN, 2s + 400ms);
break;
case EVENT_TALK_SUMMON_OHGAN:
Talk(SAY_SUMMON_OHGAN);
if (Creature* ohgan = instance->GetCreature(DATA_OHGAN))
ohgan->HandleEmoteCommand(EMOTE_ONESHOT_MOUNT_SPECIAL);
break;
case EVENT_DECAPITATE:
DoCastAOE(SPELL_DECAPITATE);
events.Repeat(me->HasAura(SPELL_FRENZY) ? 17s + 500ms : 35s);
break;
case EVENT_BLOODLETTING:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me)))
DoCast(target, SPELL_BLOODLETTING, true);
events.Repeat(25s);
break;
case EVENT_REANIMATE_OHGAN:
if (_reanimateOhganCooldown)
events.Repeat(1s);
else
{
DoCastAOE(SPELL_REANIMATE_OHGAN);
Talk(SAY_REANIMATE_OHGAN);
// Cooldown
_reanimateOhganCooldown = true;
events.ScheduleEvent(EVENT_REANIMATE_OHGAN_COOLDOWN, 20s);
}
break;
case EVENT_REANIMATE_OHGAN_COOLDOWN:
_reanimateOhganCooldown = false;
break;
case EVENT_DEVASTATING_SLAM:
DoCastAOE(SPELL_DEVASTATING_SLAM_TRIGGER);
events.Repeat(30s);
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
bool _ohganotSoFast;
bool _reanimateOhganCooldown;
ObjectGuid _reviveGUID;
};
struct npc_mandokir_ohgan : public ScriptedAI
{
npc_mandokir_ohgan(Creature* creature) : ScriptedAI(creature), _instance(me->GetInstanceScript())
{
Initialize();
}
void Initialize()
{
_allowPlayerCombat = false;
me->SetReactState(REACT_PASSIVE);
}
void IsSummonedBy(Unit* /*summoner*/) override
{
_events.ScheduleEvent(EVENT_OHGANS_ORDERS, 4s + 500ms);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
damage = 0;
me->AttackStop();
me->SetHealth(0);
me->SetTarget(ObjectGuid::Empty);
DoCast(me, SPELL_CLEAR_ALL, true);
DoCast(me, SPELL_PERMANENT_FEIGN_DEATH);
if (Creature* mandokir = _instance->GetCreature(DATA_BLOODLORD_MANDOKIR))
mandokir->AI()->DoAction(ACTION_OHGAN_IS_DEATH);
}
}
void KilledUnit(Unit* victim) override
{
if (Creature* creature = victim->ToCreature())
{
if (creature->GetEntry() == NPC_CHAINED_SPIRIT)
{
_events.ScheduleEvent(EVENT_ATTACK_PLAYERS, 1s);
DoCastAOE(SPELL_OHGAN_ORDERS);
}
}
}
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
{
if (target && spell->Id == SPELL_OHGAN_ORDERS)
_events.CancelEvent(EVENT_ATTACK_PLAYERS);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() && _allowPlayerCombat)
return;
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_OHGANS_ORDERS:
DoCastAOE(SPELL_OHGAN_ORDERS);
break;
case EVENT_ATTACK_PLAYERS:
_allowPlayerCombat = true;
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat();
break;
default:
break;
}
}
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
EventMap _events;
bool _allowPlayerCombat;
};
struct npc_mandokir_chained_spirit : public PassiveAI
{
npc_mandokir_chained_spirit(Creature* creature) : PassiveAI(creature), _instance(me->GetInstanceScript()) { }
void Reset() override
{
me->AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
_revivePlayerGUID.Clear();
}
void SetGUID(ObjectGuid const& guid, int32 /*id = 0 */) override
{
_revivePlayerGUID = guid;
}
void DoAction(int32 action) override
{
if (action == ACTION_REVIVE)
{
Position pos;
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
{
target->GetNearPoint(me, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 5.0f, target->GetAngle(me));
me->GetMotionMaster()->MovePoint(POINT_START_REVIVE, pos);
}
}
}
void MovementInform(uint32 type, uint32 pointId) override
{
if (type != POINT_MOTION_TYPE || !_revivePlayerGUID)
return;
if (pointId == POINT_START_REVIVE)
{
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
DoCast(target, SPELL_REVIVE);
me->DespawnOrUnsummon(2s);
}
}
void JustDied(Unit* /*killer*/) override
{
// We died before we could revive our player, so let another spirit do the job
if (!_revivePlayerGUID.IsEmpty())
{
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
{
if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BLOODLORD_MANDOKIR)))
{
mandokir->GetAI()->SetGUID(target->GetGUID());
mandokir->GetAI()->DoAction(ACTION_START_REVIVE);
}
}
}
me->DespawnOrUnsummon(4s);
}
void UpdateAI(uint32 /*diff*/) override { }
private:
InstanceScript * _instance;
ObjectGuid _revivePlayerGUID;
};
class NonVictimTargetSelector
{
public:
NonVictimTargetSelector(Creature* me) : _me(me) { }
bool operator() (WorldObject* target)
{
if (Unit* victim = _me->GetVictim())
return victim == target;
return true;
}
Creature* _me;
};
class spell_mandokir_decapitate : public SpellScript
{
PrepareSpellScript(spell_mandokir_decapitate);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
targets.remove_if(NonVictimTargetSelector(GetCaster()->ToCreature()));
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Player* target = GetHitPlayer())
caster->CastSpell(target, uint32(GetEffectValue()), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_decapitate::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_decapitate::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
class spell_mandokir_bloodletting : public AuraScript
{
PrepareAuraScript(spell_mandokir_bloodletting);
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo(
{
SPELL_BLOODLETTING_DAMAGE,
SPELL_BLOODLETTING_HEAL
});
}
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
Unit* caster = GetCaster();
if (!caster)
return;
int32 damage = std::max<int32>(7500, target->CountPctFromCurHealth(aurEff->GetAmount()));
caster->CastCustomSpell(target, SPELL_BLOODLETTING_DAMAGE, &damage, 0, 0, true);
target->CastCustomSpell(caster, SPELL_BLOODLETTING_HEAL, &damage, 0, 0, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mandokir_bloodletting::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
class spell_mandokir_spirit_vengeance_cancel : public SpellScript
{
PrepareSpellScript(spell_mandokir_spirit_vengeance_cancel);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Player* target = GetHitPlayer())
target->RemoveAura(uint32(GetEffectValue()));
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel::HandleScript, EFFECT_1, SPELL_EFFECT_DUMMY);
}
};
class spell_mandokir_devastating_slam : public SpellScript
{
PrepareSpellScript(spell_mandokir_devastating_slam);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
targets.remove_if(NonVictimTargetSelector(GetCaster()->ToCreature()));
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void HandleSummon(SpellEffIndex effIndex)
{
PreventHitDefaultEffect(effIndex);
GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_devastating_slam::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_devastating_slam::HandleSummon, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
}
};
class spell_mandokir_ohgan_orders : public SpellScript
{
PrepareSpellScript(spell_mandokir_ohgan_orders);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
Trinity::Containers::RandomResize(targets, 1);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
caster->CastSpell(target, uint32(GetEffectValue()), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_ohgan_orders::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_ohgan_orders::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
class spell_mandokir_ohgan_orders_trigger : public SpellScript
{
PrepareSpellScript(spell_mandokir_ohgan_orders_trigger);
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
// Enabling melee attacks to kill the spirits
caster->ClearUnitState(UNIT_STATE_CASTING);
if (Creature* creature = caster->ToCreature())
if (creature->IsAIEnabled)
creature->AI()->AttackStart(GetHitUnit());
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_mandokir_ohgan_orders_trigger::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_mandokir_reanimate_ohgan : public SpellScript
{
PrepareSpellScript(spell_mandokir_reanimate_ohgan);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
{
target->RemoveAura(SPELL_PERMANENT_FEIGN_DEATH);
target->CastSpell(target, SPELL_OHGAN_HEART_VISUAL, true);
target->CastSpell(target, SPELL_OHGAN_ORDERS, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_mandokir_reanimate_ohgan::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class spell_clear_all : public SpellScript
{
PrepareSpellScript(spell_clear_all);
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
caster->RemoveAllAurasOnDeath();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_clear_all::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class achievement_ohganot_so_fast : public AchievementCriteriaScript
{
public:
achievement_ohganot_so_fast() : AchievementCriteriaScript("achievement_ohganot_so_fast") { }
bool OnCheck(Player* /*player*/, Unit* target)
{
return target && target->GetAI()->GetData(DATA_OHGANOT_SO_FAST);
}
};
void AddSC_boss_mandokir()
{
RegisterZulGurubCreatureAI(boss_bloodlord_mandokir);
RegisterZulGurubCreatureAI(npc_mandokir_ohgan);
RegisterZulGurubCreatureAI(npc_mandokir_chained_spirit);
RegisterSpellScript(spell_mandokir_decapitate);
RegisterAuraScript(spell_mandokir_bloodletting);
RegisterSpellScript(spell_mandokir_spirit_vengeance_cancel);
RegisterSpellScript(spell_mandokir_devastating_slam);
RegisterSpellScript(spell_mandokir_ohgan_orders);
RegisterSpellScript(spell_mandokir_ohgan_orders_trigger);
RegisterSpellScript(spell_mandokir_reanimate_ohgan);
RegisterSpellScript(spell_clear_all);
new achievement_ohganot_so_fast();
}
@@ -1,773 +0,0 @@
/*
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 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 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 "GridNotifiers.h"
#include "InstanceScript.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "zulgurub.h"
enum Yells
{
SAY_AGGRO = 0,
SAY_PLAYER_KILL = 1,
SAY_DISMOUNT_OHGAN = 2,
EMOTE_DEVASTATING_SLAM = 3,
SAY_REANIMATE_OHGAN = 4,
EMOTE_FRENZY = 5,
SAY_FRENZY = 6,
SAY_DEATH = 7
};
enum Spells
{
// Bloodlord Mandokir
SPELL_BLOODLORD_AURA = 96480,
SPELL_SUMMON_OHGAN = 96717,
SPELL_REANIMATE_OHGAN = 96724,
SPELL_DECAPITATE = 96682,
SPELL_BLOODLETTING = 96776,
SPELL_BLOODLETTING_DAMAGE = 96777,
SPELL_BLOODLETTING_HEAL = 96778,
SPELL_FRENZY = 96800,
SPELL_LEVEL_UP = 96662,
SPELL_DEVASTATING_SLAM = 96740,
SPELL_DEVASTATING_SLAM_TRIGGER = 96761,
SPELL_DEVASTATING_SLAM_DAMAGE = 97385,
SPELL_SPIRIT_VENGEANCE_CANCEL = 96821,
// Chained Spirit
SPELL_REVIVE = 96484,
// Ohgan
SPELL_OHGAN_HEART_VISUAL = 96727,
SPELL_PERMANENT_FEIGN_DEATH = 96733,
SPELL_CLEAR_ALL = 28471,
SPELL_OHGAN_ORDERS = 96721,
SPELL_OHGAN_ORDERS_TRIGGER = 96722
};
enum Events
{
// Bloodlord Mandokir
EVENT_SUMMON_OHGAN = 1,
EVENT_DECAPITATE = 2,
EVENT_BLOODLETTING = 3,
EVENT_REANIMATE_OHGAN = 4,
EVENT_REANIMATE_OHGAN_COOLDOWN = 5,
EVENT_DEVASTATING_SLAM = 6
};
enum Action
{
// Bloodlord Mandokir
ACTION_OHGAN_IS_DEATH = 1,
ACTION_START_REVIVE = 2,
// Chained Spirit
ACTION_REVIVE = 1
};
enum Misc
{
POINT_START_REVIVE = 1,
DATA_OHGANOT_SO_FAST = 5762
};
enum SummonGroups
{
SUMMON_GROUP_CHAINED_SPIRIT = 0
};
class boss_mandokir : public CreatureScript
{
public:
boss_mandokir() : CreatureScript("boss_mandokir") { }
struct boss_mandokirAI : public BossAI
{
boss_mandokirAI(Creature* creature) : BossAI(creature, DATA_BLOODLORD_MANDOKIR) { }
void Reset() override
{
DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL);
_Reset();
me->SummonCreatureGroup(SUMMON_GROUP_CHAINED_SPIRIT);
_ohganotSoFast = true;
_reanimateOhganCooldown = false;
_reviveGUID.Clear();
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
Talk(SAY_AGGRO);
DoCastAOE(SPELL_BLOODLORD_AURA);
if (!summons.empty())
{
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{
if (Creature* chainedSpirit = ObjectAccessor::GetCreature(*me, *itr))
if (chainedSpirit->GetEntry() == NPC_CHAINED_SPIRIT && chainedSpirit->AI())
chainedSpirit->SetFaction(FACTION_NONE);
}
}
events.ScheduleEvent(EVENT_DECAPITATE, 10000);
events.ScheduleEvent(EVENT_BLOODLETTING, 15000);
events.ScheduleEvent(EVENT_SUMMON_OHGAN, 20000);
events.ScheduleEvent(EVENT_DEVASTATING_SLAM, 25000);
}
void JustDied(Unit* /*killer*/) override
{
DoCastAOE(SPELL_SPIRIT_VENGEANCE_CANCEL);
_JustDied();
Talk(SAY_DEATH);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_PLAYER_KILL);
DoCast(SPELL_LEVEL_UP);
_reviveGUID = victim->GetGUID();
DoAction(ACTION_START_REVIVE);
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthBelowPctDamaged(20, damage) && !me->HasAura(SPELL_FRENZY))
{
DoCast(me, SPELL_FRENZY, true);
Talk(SAY_FRENZY);
Talk(EMOTE_FRENZY);
}
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_OHGAN_IS_DEATH:
events.ScheduleEvent(EVENT_REANIMATE_OHGAN, 4000);
_ohganotSoFast = false;
break;
case ACTION_START_REVIVE:
{
std::list<Creature*> creatures;
GetCreatureListWithEntryInGrid(creatures, me, NPC_CHAINED_SPIRIT, 200.0f);
creatures.remove_if(Trinity::AnyDeadUnitCheck());
creatures.remove_if(Trinity::UnitAuraCheck(true, SPELL_OHGAN_ORDERS_TRIGGER));
Trinity::Containers::RandomResize(creatures, 1);
if (creatures.empty())
return;
for (Creature* chainedSpirit : creatures)
{
chainedSpirit->AI()->SetGUID(_reviveGUID);
chainedSpirit->AI()->DoAction(ACTION_REVIVE);
_reviveGUID.Clear();
}
break;
}
default:
break;
}
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_OHGANOT_SO_FAST)
return _ohganotSoFast;
return 0;
}
void SetGUID(ObjectGuid const& guid, int32 /*id = 0 **/) override
{
_reviveGUID = guid;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SUMMON_OHGAN:
me->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
DoCast(me, SPELL_SUMMON_OHGAN, true);
break;
case EVENT_DECAPITATE:
DoCastAOE(SPELL_DECAPITATE);
events.ScheduleEvent(EVENT_DECAPITATE, me->HasAura(SPELL_FRENZY) ? 17500 : 35000);
break;
case EVENT_BLOODLETTING:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
{
DoCast(target, SPELL_BLOODLETTING, true);
me->ClearUnitState(UNIT_STATE_CASTING);
}
events.ScheduleEvent(EVENT_BLOODLETTING, 25000);
break;
case EVENT_REANIMATE_OHGAN:
if (_reanimateOhganCooldown)
events.ScheduleEvent(EVENT_REANIMATE_OHGAN, 1000);
else
{
DoCastAOE(SPELL_REANIMATE_OHGAN);
Talk(SAY_REANIMATE_OHGAN);
// Cooldown
_reanimateOhganCooldown = true;
events.ScheduleEvent(EVENT_REANIMATE_OHGAN_COOLDOWN, 20000);
}
break;
case EVENT_REANIMATE_OHGAN_COOLDOWN:
_reanimateOhganCooldown = false;
break;
case EVENT_DEVASTATING_SLAM:
DoCastAOE(SPELL_DEVASTATING_SLAM_TRIGGER);
events.ScheduleEvent(EVENT_DEVASTATING_SLAM, 30000);
break;
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
bool _ohganotSoFast;
bool _reanimateOhganCooldown;
ObjectGuid _reviveGUID;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_mandokirAI>(creature);
}
};
class npc_ohgan : public CreatureScript
{
public:
npc_ohgan() : CreatureScript("npc_ohgan") { }
struct npc_ohganAI : public ScriptedAI
{
npc_ohganAI(Creature* creature) : ScriptedAI(creature)
{
_instance = me->GetInstanceScript();
}
void JustEngagedWith(Unit* /*who*/) override
{
DoCastAOE(SPELL_OHGAN_ORDERS, true);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
damage = 0;
me->AttackStop();
me->SetHealth(0);
me->SetTarget(ObjectGuid::Empty);
DoCast(me, SPELL_CLEAR_ALL, true);
DoCast(me, SPELL_PERMANENT_FEIGN_DEATH);
if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BLOODLORD_MANDOKIR)))
mandokir->AI()->DoAction(ACTION_OHGAN_IS_DEATH);
}
}
void KilledUnit(Unit* victim) override
{
if (Creature* creature = victim->ToCreature())
{
if (creature->GetEntry() == NPC_CHAINED_SPIRIT)
DoCastAOE(SPELL_OHGAN_ORDERS, true);
}
}
void UpdateAI(uint32 /*diff*/) override
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_ohganAI>(creature);
}
};
class npc_chained_spirit : public CreatureScript
{
public:
npc_chained_spirit() : CreatureScript("npc_chained_spirit") { }
struct npc_chained_spiritAI : public ScriptedAI
{
npc_chained_spiritAI(Creature* creature) : ScriptedAI(creature)
{
_instance = me->GetInstanceScript();
me->AddUnitMovementFlag(MOVEMENTFLAG_HOVER);
me->SetReactState(REACT_PASSIVE); // correct?
}
void Reset() override
{
_revivePlayerGUID.Clear();
}
void SetGUID(ObjectGuid const& guid, int32 /*id = 0 */) override
{
_revivePlayerGUID = guid;
}
void DoAction(int32 action) override
{
if (action == ACTION_REVIVE)
{
Position pos;
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
{
target->GetNearPoint(me, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, 5.0f, target->GetAngle(me));
me->GetMotionMaster()->MovePoint(POINT_START_REVIVE, pos);
}
}
}
void MovementInform(uint32 type, uint32 pointId) override
{
if (type != POINT_MOTION_TYPE || !_revivePlayerGUID)
return;
if (pointId == POINT_START_REVIVE)
{
if (Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID))
DoCast(target, SPELL_REVIVE);
me->DespawnOrUnsummon(2000);
}
}
void JustDied(Unit* /*killer*/) override
{
Player* target = ObjectAccessor::GetPlayer(*me, _revivePlayerGUID);
if (!target || target->IsAlive())
return;
if (Creature* mandokir = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BLOODLORD_MANDOKIR)))
{
mandokir->GetAI()->SetGUID(target->GetGUID());
mandokir->GetAI()->DoAction(ACTION_START_REVIVE);
}
me->DespawnOrUnsummon();
}
void UpdateAI(uint32 /*diff*/) override { }
private:
InstanceScript* _instance;
ObjectGuid _revivePlayerGUID;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_chained_spiritAI>(creature);
}
};
class spell_mandokir_decapitate : public SpellScriptLoader
{
public:
spell_mandokir_decapitate() : SpellScriptLoader("spell_mandokir_decapitate") { }
class spell_mandokir_decapitate_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mandokir_decapitate_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Player* target = GetHitPlayer())
caster->CastSpell(target, uint32(GetEffectValue()), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_decapitate_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_decapitate_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mandokir_decapitate_SpellScript();
}
};
class spell_mandokir_bloodletting : public SpellScriptLoader
{
public:
spell_mandokir_bloodletting() : SpellScriptLoader("spell_mandokir_bloodletting") { }
class spell_mandokir_bloodletting_AuraScript : public AuraScript
{
PrepareAuraScript(spell_mandokir_bloodletting_AuraScript);
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_BLOODLETTING_DAMAGE, SPELL_BLOODLETTING_HEAL });
}
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
Unit* caster = GetCaster();
if (!caster)
return;
int32 damage = std::max<int32>(7500, target->CountPctFromCurHealth(aurEff->GetAmount()));
caster->CastCustomSpell(target, SPELL_BLOODLETTING_DAMAGE, &damage, 0, 0, true);
target->CastCustomSpell(caster, SPELL_BLOODLETTING_HEAL, &damage, 0, 0, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mandokir_bloodletting_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_mandokir_bloodletting_AuraScript();
}
};
class spell_mandokir_spirit_vengeance_cancel : public SpellScriptLoader
{
public:
spell_mandokir_spirit_vengeance_cancel() : SpellScriptLoader("spell_mandokir_spirit_vengeance_cancel") { }
class spell_mandokir_spirit_vengeance_cancel_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mandokir_spirit_vengeance_cancel_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Player* target = GetHitPlayer())
target->RemoveAura(uint32(GetEffectValue()));
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_spirit_vengeance_cancel_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mandokir_spirit_vengeance_cancel_SpellScript();
}
};
class DevastatingSlamTargetSelector
{
public:
DevastatingSlamTargetSelector(Creature* me, const Unit* victim) : _me(me), _victim(victim) {}
bool operator() (WorldObject* target)
{
if (target == _victim && _me->getThreatManager().getThreatList().size() > 1)
return true;
if (target->GetTypeId() != TYPEID_PLAYER)
return true;
return false;
}
Creature* _me;
Unit const* _victim;
};
class spell_mandokir_devastating_slam : public SpellScriptLoader
{
public:
spell_mandokir_devastating_slam() : SpellScriptLoader("spell_mandokir_devastating_slam") { }
class spell_mandokir_devastating_slam_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mandokir_devastating_slam_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
targets.remove_if(DevastatingSlamTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
if (targets.empty())
return;
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
float angle = 0.0f;
float x, y, z;
if (Player* target = GetHitPlayer())
{
caster->AttackStop();
caster->SetOrientation(caster->GetAngle(target));
caster->SetFacingTo(caster->GetAngle(target));
caster->CastSpell(caster, SPELL_DEVASTATING_SLAM, false);
// HACK: Need better way for pos calculation
for (uint8 i = 0; i <= 50; ++i)
{
angle = float(rand_norm()) * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
caster->GetClosePoint(x, y, z, 4.0f, frand(-2.5f, 50.0f), angle);
caster->CastSpell(x, y, z, SPELL_DEVASTATING_SLAM_DAMAGE, true);
}
}
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_devastating_slam_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_devastating_slam_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_FORCE_CAST);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mandokir_devastating_slam_SpellScript();
}
};
class spell_mandokir_ohgan_orders : public SpellScriptLoader
{
public:
spell_mandokir_ohgan_orders() : SpellScriptLoader("spell_mandokir_ohgan_orders") { }
class spell_mandokir_ohgan_orders_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mandokir_ohgan_orders_SpellScript);
void FilterTargets(std::list<WorldObject*>& targets)
{
if (targets.empty())
return;
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Unit* target = GetHitUnit())
caster->CastSpell(target, uint32(GetEffectValue()), true);
}
void Register() override
{
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mandokir_ohgan_orders_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
OnEffectHitTarget += SpellEffectFn(spell_mandokir_ohgan_orders_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mandokir_ohgan_orders_SpellScript();
}
};
class spell_mandokir_ohgan_orders_trigger : public SpellScriptLoader
{
public:
spell_mandokir_ohgan_orders_trigger() : SpellScriptLoader("spell_mandokir_ohgan_orders_trigger") { }
class spell_mandokir_ohgan_orders_trigger_AuraScript : public AuraScript
{
PrepareAuraScript(spell_mandokir_ohgan_orders_trigger_AuraScript);
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (Unit* caster = GetCaster())
{
// HACK: research better way
caster->ClearUnitState(UNIT_STATE_CASTING);
caster->GetMotionMaster()->Clear();
caster->DeleteThreatList();
caster->AddThreat(target, 50000000.0f);
caster->TauntApply(target);
}
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_mandokir_ohgan_orders_trigger_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_mandokir_ohgan_orders_trigger_AuraScript();
}
};
class spell_mandokir_reanimate_ohgan : public SpellScriptLoader
{
public:
spell_mandokir_reanimate_ohgan() : SpellScriptLoader("spell_mandokir_reanimate_ohgan") { }
class spell_mandokir_reanimate_ohgan_SpellScript : public SpellScript
{
PrepareSpellScript(spell_mandokir_reanimate_ohgan_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
{
target->RemoveAura(SPELL_PERMANENT_FEIGN_DEATH);
target->CastSpell(target, SPELL_OHGAN_HEART_VISUAL, true);
target->CastSpell((Unit*)nullptr, SPELL_OHGAN_ORDERS, true);
}
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_mandokir_reanimate_ohgan_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_mandokir_reanimate_ohgan_SpellScript();
}
};
class spell_clear_all : public SpellScriptLoader
{
public:
spell_clear_all() : SpellScriptLoader("spell_clear_all") { }
class spell_clear_all_SpellScript : public SpellScript
{
PrepareSpellScript(spell_clear_all_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
caster->RemoveAllAurasOnDeath();
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_clear_all_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_clear_all_SpellScript();
}
};
class achievement_ohganot_so_fast : public AchievementCriteriaScript
{
public:
achievement_ohganot_so_fast() : AchievementCriteriaScript("achievement_ohganot_so_fast") { }
bool OnCheck(Player* /*player*/, Unit* target)
{
return target && target->GetAI()->GetData(DATA_OHGANOT_SO_FAST);
}
};
void AddSC_boss_mandokir()
{
new boss_mandokir();
new npc_ohgan();
new npc_chained_spirit();
new spell_mandokir_decapitate();
new spell_mandokir_bloodletting();
new spell_mandokir_spirit_vengeance_cancel();
new spell_mandokir_devastating_slam();
new spell_mandokir_ohgan_orders();
new spell_mandokir_ohgan_orders_trigger();
new spell_mandokir_reanimate_ohgan();
new spell_clear_all();
new achievement_ohganot_so_fast();
}
@@ -28,7 +28,8 @@ ObjectData const creatureData[] =
{ BOSS_BLOODLORD_MANDOKIR, DATA_BLOODLORD_MANDOKIR },
{ BOSS_KILNARA, DATA_KILNARA },
{ BOSS_ZANZIL, DATA_ZANZIL },
{ BOSS_JINDO_THE_GODBREAKER, DATA_JINDO_THE_GODBREAKER }
{ BOSS_JINDO_THE_GODBREAKER, DATA_JINDO_THE_GODBREAKER },
{ NPC_OHGAN, DATA_OHGAN }
};
DoorData const doorData[] =
@@ -67,6 +68,10 @@ class instance_zulgurub : public InstanceMapScript
if (Creature* venoxis = GetCreature(DATA_HIGH_PRIEST_VENOXIS))
venoxis->AI()->JustSummoned(creature);
break;
case NPC_DEVASTATING_SLAM:
if (Creature* mandokir = GetCreature(DATA_BLOODLORD_MANDOKIR))
mandokir->AI()->JustSummoned(creature);
break;
default:
break;
}
@@ -28,6 +28,7 @@ uint32 const EncounterCount = 5;
enum ZGDataTypes
{
// Bosses
DATA_HIGH_PRIEST_VENOXIS = 0,
DATA_BLOODLORD_MANDOKIR = 1,
DATA_KILNARA = 2,
@@ -40,12 +41,16 @@ enum ZGDataTypes
DATA_WUSHOOLAY = 7,
DATA_GRILEK = 8,
// Bloodlord Mandokir
DATA_OHGAN = 9,
// Jin'do the Godbreaker
DATA_JINDOR_TRIGGER,
DATA_JINDOR_TRIGGER
};
enum ZGCreatureIds
{
// Bosses
BOSS_HIGH_PRIEST_VENOXIS = 52155,
BOSS_BLOODLORD_MANDOKIR = 52151,
BOSS_KILNARA = 52059,
@@ -68,6 +73,7 @@ enum ZGCreatureIds
// Bloodlord Mandokir
NPC_CHAINED_SPIRIT = 52156,
NPC_OHGAN = 52157,
NPC_DEVASTATING_SLAM = 52324,
// Jin'do the Godbreaker
NPC_JINDO_TRIGGER = 52150,