mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 15:58:04 +00:00
fix(Scripts/Karazhan): Rework Attumen & Midnight (#14756)
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
--
|
||||||
|
SET @ATTUMEN_UNMOUNTED := 15550;
|
||||||
|
SET @ATTUMEN_MOUNTED := 16152;
|
||||||
|
SET @MIDNIGHT := 16151;
|
||||||
|
SET @GMIDNIGHT := 135159;
|
||||||
|
|
||||||
|
DELETE FROM `creature_text` WHERE `CreatureID` IN (@MIDNIGHT, @ATTUMEN_UNMOUNTED, @ATTUMEN_MOUNTED);
|
||||||
|
INSERT INTO `creature_text` (`CreatureID`, `GroupId`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||||
|
(@ATTUMEN_UNMOUNTED, 0, 0, 'It was... inevitable.', 14, 0, 100, 0, 0, 9169, 13460, 0, 'attumen SAY_KILL1'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 0, 1, 'Another trophy to add to my collection!', 14, 0, 100, 0, 0, 9300, 15333, 0,'attumen SAY_KILL2'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 1, 0, 'Such easy sport.', 14, 0, 100, 0, 0, 9170, 0, 0,'attumen SAY_RANDOM1'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 1, 1, 'Amateurs! Do not think you can best me! I kill for a living.', 14, 0, 100, 0, 0, 9304, 0, 0, 'attumen SAY_RANDOM2'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 2, 0, 'Weapons are merely a convenience for a warrior of my skill!', 14, 0, 100, 0, 0, 9166, 13490, 0, 'attumen SAY_DISARMED'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 3, 0, 'Well done, Midnight!', 14, 0, 100, 0, 0, 9173, 15334, 0, 'attumen SAY_MIDNIGHT_KILL'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 4, 0, 'Cowards! Wretches!', 14, 0, 100, 0, 0, 9167, 13459, 0, 'attumen SAY_APPEAR1'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 4, 1, 'Who dares attack the steed of the Huntsman?', 14, 0, 100, 0, 0, 9298, 15378, 0, 'attumen SAY_APPEAR2'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 4, 2, 'Perhaps you would rather test yourselves against a more formidable opponent?!', 14, 0, 100, 0, 0, 9299, 15379, 0, 'attumen SAY_APPEAR3'),
|
||||||
|
(@ATTUMEN_UNMOUNTED, 5, 0, 'Come Midnight, let\'s disperse this petty rabble!', 14, 0, 100, 0, 0, 9168, 13456, 0, 'attumen SAY_MOUNT'),
|
||||||
|
|
||||||
|
(@ATTUMEN_MOUNTED, 0, 0, 'It was... inevitable.', 14, 0, 100, 0, 0, 9169, 13460, 0, 'attumen SAY_KILL1'),
|
||||||
|
(@ATTUMEN_MOUNTED, 0, 1, 'Another trophy to add to my collection!', 14, 0, 100, 0, 0, 9300, 15333, 0,'attumen SAY_KILL2'),
|
||||||
|
(@ATTUMEN_MOUNTED, 1, 0, 'Such easy sport.', 14, 0, 100, 0, 0, 9170, 0, 0,'attumen SAY_RANDOM1'),
|
||||||
|
(@ATTUMEN_MOUNTED, 1, 1, 'Amateurs! Do not think you can best me! I kill for a living.', 14, 0, 100, 0, 0, 9304, 0, 0, 'attumen SAY_RANDOM2'),
|
||||||
|
(@ATTUMEN_MOUNTED, 2, 0, 'Weapons are merely a convenience for a warrior of my skill!', 14, 0, 100, 0, 0, 9166, 13490, 0, 'attumen SAY_DISARMED'),
|
||||||
|
(@ATTUMEN_MOUNTED, 3, 0, 'Always knew... someday I would become... the hunted.', 14, 0, 100, 0, 0, 9165, 13462, 0, 'attumen SAY_DEATH'),
|
||||||
|
|
||||||
|
(@MIDNIGHT, 0, 0, '%s calls for her master!', 16, 0, 100, 0, 0, 0, 13439, 0, 'midnight EMOTE_CALL_ATTUMEN'),
|
||||||
|
(@MIDNIGHT, 1, 0, '%s rushes to her master\'s aid.', 16, 0, 100, 0, 0, 0, 13455, 0, 'midnight EMOTE_MOUNT_UP');
|
||||||
|
|
||||||
|
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` = 29770;
|
||||||
|
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||||
|
(13, 1, 29770, 0, 0, 31, 0, 3, 15550, 0, 0, 0, 0, '', 'Mount spell only hit Attumen the Huntsmen');
|
||||||
|
|
||||||
|
DELETE FROM `creature_formations` WHERE `leaderGUID` = 135159;
|
||||||
|
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
|
||||||
|
(@GMIDNIGHT, @GMIDNIGHT, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135828, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135836, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135829, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135839, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135833, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135840, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135834, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135830, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135841, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135842, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135831, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135837, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135838, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135832, 0, 0, 1, 0, 0),
|
||||||
|
(@GMIDNIGHT, 135835, 0, 0, 1, 0, 0);
|
||||||
|
|
||||||
|
UPDATE `creature_template` SET `ScriptName` = 'boss_attumen', `lootid` = @ATTUMEN_MOUNTED WHERE `entry` = @ATTUMEN_MOUNTED;
|
||||||
|
UPDATE `creature_loot_template` SET `entry` = @ATTUMEN_MOUNTED WHERE `entry` = @ATTUMEN_UNMOUNTED;
|
||||||
|
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|2097152 WHERE `entry` = 16152;
|
||||||
@@ -19,64 +19,290 @@
|
|||||||
#include "ScriptedCreature.h"
|
#include "ScriptedCreature.h"
|
||||||
#include "SpellInfo.h"
|
#include "SpellInfo.h"
|
||||||
#include "SpellScript.h"
|
#include "SpellScript.h"
|
||||||
|
#include "Unit.h"
|
||||||
#include "karazhan.h"
|
#include "karazhan.h"
|
||||||
|
|
||||||
enum eSay
|
enum Texts
|
||||||
{
|
{
|
||||||
SAY_ATTUMEN1_APPEAR = 0,
|
SAY_KILL = 0,
|
||||||
SAY_ATTUMEN1_MOUNT = 2,
|
SAY_RANDOM = 1,
|
||||||
|
SAY_DISARMED = 2,
|
||||||
|
SAY_MIDNIGHT_KILL = 3,
|
||||||
|
SAY_APPEAR = 4,
|
||||||
|
SAY_MOUNT = 5,
|
||||||
|
|
||||||
SAY_ATTUMEN2_DEATH = 0,
|
SAY_DEATH = 3,
|
||||||
|
|
||||||
SAY_ATTUMEN_KILL = 1,
|
|
||||||
SAY_ATTUMEN_DISARM = 3,
|
|
||||||
SAY_ATTUMEN_RANDOM = 4,
|
|
||||||
SAY_ATTUMEN_MIDNIGHT_KILL = 5,
|
|
||||||
|
|
||||||
SAY_MIDNIGHT_EMOTE = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eSpells
|
|
||||||
{
|
|
||||||
// Midnight
|
// Midnight
|
||||||
SPELL_KNOCKDOWN = 29711,
|
EMOTE_CALL_ATTUMEN = 0,
|
||||||
SPELL_SUMMON_ATTUMEN = 29714,
|
EMOTE_MOUNT_UP = 1
|
||||||
SPELL_SUMMON_ATTUMEN_MOUNTED = 29799,
|
};
|
||||||
|
|
||||||
|
enum Spells
|
||||||
|
{
|
||||||
// Attumen
|
// Attumen
|
||||||
SPELL_SHADOW_CLEAVE = 29832,
|
SPELL_SHADOWCLEAVE = 29832,
|
||||||
SPELL_INTANGIBLE_PRESENCE = 29833,
|
SPELL_INTANGIBLE_PRESENCE = 29833,
|
||||||
SPELL_SPAWN_SMOKE1 = 29802,
|
SPELL_SPAWN_SMOKE = 10389,
|
||||||
|
SPELL_CHARGE = 29847,
|
||||||
|
|
||||||
// Attumen 2
|
// Midnight
|
||||||
SPELL_CHARGE_MIDNIGHT = 29847,
|
SPELL_KNOCKDOWN = 29711,
|
||||||
SPELL_SPAWN_SMOKE2 = 10389,
|
SPELL_SUMMON_ATTUMEN = 29714,
|
||||||
|
SPELL_MOUNT = 29770,
|
||||||
// Generic
|
SPELL_SUMMON_ATTUMEN_MOUNTED = 29799
|
||||||
SPELL_MOUNT_TARGET_ATTUMEN = 29769,
|
|
||||||
SPELL_MOUNT_TARGET_MIDNIGHT = 29770
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eEvents
|
enum Phases
|
||||||
{
|
{
|
||||||
EVENT_CHECK_HEALTH_95 = 1,
|
PHASE_NONE,
|
||||||
EVENT_CHECK_HEALTH_25 = 2,
|
PHASE_ATTUMEN_ENGAGES,
|
||||||
EVENT_SPELL_KNOCKDOWN = 3,
|
PHASE_MOUNTED
|
||||||
EVENT_SUMMON_ATTUMEN_MOUNTED = 4,
|
|
||||||
|
|
||||||
EVENT_SPELL_SHADOW_CLEAVE = 10,
|
|
||||||
EVENT_SPELL_INTANGIBLE_PRESENCE = 11,
|
|
||||||
EVENT_RANDOM_YELL = 12,
|
|
||||||
|
|
||||||
EVENT_SPELL_CHARGE = 20,
|
|
||||||
|
|
||||||
EVENT_KILL_TALK = 30
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eMisc
|
enum Actions
|
||||||
{
|
{
|
||||||
POINT_MOVE_TO_MIDNIGHT = 1,
|
ACTION_SET_MIDNIGHT_PHASE,
|
||||||
DATA_ATTUMEN_READY = 1
|
};
|
||||||
|
|
||||||
|
class boss_attumen : public CreatureScript
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
boss_attumen() : CreatureScript("boss_attumen") { }
|
||||||
|
|
||||||
|
struct boss_attumenAI : public BossAI
|
||||||
|
{
|
||||||
|
boss_attumenAI(Creature* creature) : BossAI(creature, DATA_ATTUMEN)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize()
|
||||||
|
{
|
||||||
|
_phase = PHASE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanMeleeHit()
|
||||||
|
{
|
||||||
|
return me->GetVictim() && (me->GetVictim()->GetPositionZ() < 53.0f || me->GetVictim()->GetDistance(me->GetHomePosition()) < 50.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason why) override
|
||||||
|
{
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
midnight->AI()->EnterEvadeMode(why);
|
||||||
|
}
|
||||||
|
|
||||||
|
me->DespawnOrUnsummon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScheduleTasks() override
|
||||||
|
{
|
||||||
|
scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_SHADOWCLEAVE);
|
||||||
|
task.Repeat(Seconds(15), Seconds(25));
|
||||||
|
});
|
||||||
|
|
||||||
|
scheduler.Schedule(Seconds(25), Seconds(45), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_INTANGIBLE_PRESENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
task.Repeat(Seconds(25), Seconds(45));
|
||||||
|
});
|
||||||
|
|
||||||
|
scheduler.Schedule(Seconds(30), Seconds(60), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
Talk(SAY_RANDOM);
|
||||||
|
task.Repeat(Seconds(30), Seconds(60));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
|
{
|
||||||
|
// Attumen does not die until he mounts Midnight, let health fall to 1 and prevent further damage.
|
||||||
|
if (damage >= me->GetHealth() && _phase != PHASE_MOUNTED)
|
||||||
|
{
|
||||||
|
damage = me->GetHealth() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase == PHASE_ATTUMEN_ENGAGES && me->HealthBelowPctDamaged(25, damage))
|
||||||
|
{
|
||||||
|
_phase = PHASE_NONE;
|
||||||
|
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
midnight->AI()->DoCastAOE(SPELL_MOUNT, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KilledUnit(Unit* /*victim*/) override
|
||||||
|
{
|
||||||
|
Talk(SAY_KILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* summon) override
|
||||||
|
{
|
||||||
|
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED)
|
||||||
|
{
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
if (midnight->GetHealth() > me->GetHealth())
|
||||||
|
{
|
||||||
|
summon->SetHealth(midnight->GetHealth());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
summon->SetHealth(me->GetHealth());
|
||||||
|
}
|
||||||
|
|
||||||
|
summon->AI()->DoZoneInCombat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BossAI::JustSummoned(summon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsSummonedBy(WorldObject* summoner) override
|
||||||
|
{
|
||||||
|
if (summoner->GetEntry() == NPC_MIDNIGHT)
|
||||||
|
{
|
||||||
|
_phase = PHASE_ATTUMEN_ENGAGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (summoner->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN)
|
||||||
|
{
|
||||||
|
_phase = PHASE_MOUNTED;
|
||||||
|
DoCastSelf(SPELL_SPAWN_SMOKE);
|
||||||
|
|
||||||
|
scheduler.Schedule(Seconds(10), Seconds(25), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
Unit* target = nullptr;
|
||||||
|
std::vector<Unit*> target_list;
|
||||||
|
|
||||||
|
for (auto* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||||
|
{
|
||||||
|
target = ref->GetVictim();
|
||||||
|
if (target && !target->IsWithinDist(me, 8.00f, false) && target->IsWithinDist(me, 25.0f, false))
|
||||||
|
target_list.push_back(target);
|
||||||
|
|
||||||
|
target = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target_list.empty())
|
||||||
|
{
|
||||||
|
target = Acore::Containers::SelectRandomContainerElement(target_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
DoCast(target, SPELL_CHARGE);
|
||||||
|
task.Repeat(Seconds(10), Seconds(25));
|
||||||
|
});
|
||||||
|
|
||||||
|
scheduler.Schedule(Seconds(25), Seconds(35), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_KNOCKDOWN);
|
||||||
|
task.Repeat(Seconds(25), Seconds(35));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustDied(Unit* /*killer*/) override
|
||||||
|
{
|
||||||
|
Talk(SAY_DEATH);
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
midnight->KillSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
_JustDied();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (_phase != PHASE_NONE)
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CanMeleeHit())
|
||||||
|
{
|
||||||
|
BossAI::EnterEvadeMode(EvadeReason::EVADE_REASON_BOUNDARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.Update(diff,
|
||||||
|
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
||||||
|
{
|
||||||
|
if (spellInfo->Mechanic == MECHANIC_DISARM)
|
||||||
|
{
|
||||||
|
Talk(SAY_DISARMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellInfo->Id == SPELL_MOUNT)
|
||||||
|
{
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
_phase = PHASE_NONE;
|
||||||
|
scheduler.CancelAll();
|
||||||
|
|
||||||
|
midnight->AI()->DoAction(ACTION_SET_MIDNIGHT_PHASE);
|
||||||
|
midnight->AttackStop();
|
||||||
|
midnight->RemoveAllAttackers();
|
||||||
|
midnight->SetReactState(REACT_PASSIVE);
|
||||||
|
midnight->GetMotionMaster()->MoveFollow(me, 2.0f, 0.0f);
|
||||||
|
midnight->AI()->Talk(EMOTE_MOUNT_UP);
|
||||||
|
|
||||||
|
me->AttackStop();
|
||||||
|
me->RemoveAllAttackers();
|
||||||
|
me->SetReactState(REACT_PASSIVE);
|
||||||
|
me->GetMotionMaster()->MoveFollow(midnight, 2.0f, 0.0f);
|
||||||
|
Talk(SAY_MOUNT);
|
||||||
|
|
||||||
|
scheduler.Schedule(Seconds(1), [this](TaskContext task)
|
||||||
|
{
|
||||||
|
if (Creature* midnight = instance->GetCreature(DATA_MIDNIGHT))
|
||||||
|
{
|
||||||
|
if (me->IsWithinDist2d(midnight, 5.0f))
|
||||||
|
{
|
||||||
|
DoCastAOE(SPELL_SUMMON_ATTUMEN_MOUNTED);
|
||||||
|
me->DespawnOrUnsummon(1s, 0s);
|
||||||
|
midnight->SetVisible(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
midnight->GetMotionMaster()->MoveFollow(me, 2.0f, 0.0f);
|
||||||
|
me->GetMotionMaster()->MoveFollow(midnight, 2.0f, 0.0f);
|
||||||
|
task.Repeat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 _phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
CreatureAI* GetAI(Creature* creature) const override
|
||||||
|
{
|
||||||
|
return GetKarazhanAI<boss_attumenAI>(creature);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_midnight : public CreatureScript
|
class boss_midnight : public CreatureScript
|
||||||
@@ -86,114 +312,109 @@ public:
|
|||||||
|
|
||||||
struct boss_midnightAI : public BossAI
|
struct boss_midnightAI : public BossAI
|
||||||
{
|
{
|
||||||
boss_midnightAI(Creature* creature) : BossAI(creature, DATA_ATTUMEN) { }
|
boss_midnightAI(Creature* creature) : BossAI(creature, DATA_ATTUMEN), _phase(PHASE_NONE) { }
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
me->SetVisible(true);
|
me->SetVisible(true);
|
||||||
_healthPct = 100.0f;
|
me->SetReactState(REACT_DEFENSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanMeleeHit()
|
||||||
|
{
|
||||||
|
return me->GetVictim() && (me->GetVictim()->GetPositionZ() < 53.0f || me->GetVictim()->GetDistance(me->GetHomePosition()) < 50.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
|
{
|
||||||
|
// Midnight never dies, let health fall to 1 and prevent further damage.
|
||||||
|
if (damage >= me->GetHealth())
|
||||||
|
{
|
||||||
|
damage = me->GetHealth() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase == PHASE_NONE && me->HealthBelowPctDamaged(95, damage))
|
||||||
|
{
|
||||||
|
_phase = PHASE_ATTUMEN_ENGAGES;
|
||||||
|
Talk(EMOTE_CALL_ATTUMEN);
|
||||||
|
DoCastAOE(SPELL_SUMMON_ATTUMEN);
|
||||||
|
}
|
||||||
|
else if (_phase == PHASE_ATTUMEN_ENGAGES && me->HealthBelowPctDamaged(25, damage))
|
||||||
|
{
|
||||||
|
_phase = PHASE_MOUNTED;
|
||||||
|
DoCastAOE(SPELL_MOUNT, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustSummoned(Creature* summon) override
|
||||||
|
{
|
||||||
|
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN)
|
||||||
|
{
|
||||||
|
summon->AI()->AttackStart(me->GetVictim());
|
||||||
|
summon->AI()->Talk(SAY_APPEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
BossAI::JustSummoned(summon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoAction(int32 actionId) override
|
||||||
|
{
|
||||||
|
if (actionId == ACTION_SET_MIDNIGHT_PHASE)
|
||||||
|
{
|
||||||
|
_phase = PHASE_MOUNTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterCombat(Unit* who) override
|
void EnterCombat(Unit* who) override
|
||||||
{
|
{
|
||||||
BossAI::EnterCombat(who);
|
BossAI::EnterCombat(who);
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_95, 0);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 6000);
|
scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext task)
|
||||||
DoZoneInCombat();
|
{
|
||||||
|
DoCastVictim(SPELL_KNOCKDOWN);
|
||||||
|
task.Repeat(Seconds(15), Seconds(25));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnterEvadeMode(EvadeReason /*why*/) override
|
||||||
|
{
|
||||||
|
me->DespawnOnEvade(10s);
|
||||||
|
_phase = PHASE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KilledUnit(Unit* /*victim*/) override
|
void KilledUnit(Unit* /*victim*/) override
|
||||||
{
|
{
|
||||||
if (Creature* attumen = summons.GetCreatureWithEntry(NPC_ATTUMEN_THE_HUNTSMAN))
|
if (_phase == PHASE_ATTUMEN_ENGAGES)
|
||||||
attumen->AI()->Talk(SAY_ATTUMEN_MIDNIGHT_KILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
|
||||||
{
|
|
||||||
summons.Summon(summon);
|
|
||||||
summon->SetInCombatWithZone();
|
|
||||||
|
|
||||||
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED)
|
|
||||||
{
|
{
|
||||||
summon->SetHealth(summon->CountPctFromMaxHealth(_healthPct));
|
if (Creature* attumen = instance->GetCreature(DATA_ATTUMEN))
|
||||||
summon->CastSpell(summon, SPELL_SPAWN_SMOKE2, true);
|
{
|
||||||
}
|
Talk(SAY_MIDNIGHT_KILL, attumen);
|
||||||
else
|
}
|
||||||
summon->CastSpell(summon, SPELL_SPAWN_SMOKE1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetData(uint32 type, uint32 /*data*/) override
|
|
||||||
{
|
|
||||||
if (type == DATA_ATTUMEN_READY)
|
|
||||||
events.ScheduleEvent(EVENT_SUMMON_ATTUMEN_MOUNTED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
if (summon->GetEntry() == NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED)
|
|
||||||
{
|
|
||||||
summons.clear();
|
|
||||||
me->KillSelf();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (_phase != PHASE_MOUNTED)
|
||||||
return;
|
|
||||||
|
|
||||||
events.Update(diff);
|
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (events.ExecuteEvent())
|
|
||||||
{
|
{
|
||||||
case EVENT_CHECK_HEALTH_95:
|
if (!UpdateVictim())
|
||||||
if (me->HealthBelowPct(96))
|
{
|
||||||
{
|
return;
|
||||||
me->CastSpell(me, SPELL_SUMMON_ATTUMEN, true);
|
}
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_95, 500);
|
|
||||||
break;
|
|
||||||
case EVENT_CHECK_HEALTH_25:
|
|
||||||
if (me->HealthBelowPct(25))
|
|
||||||
{
|
|
||||||
Talk(SAY_MIDNIGHT_EMOTE);
|
|
||||||
me->CastSpell(me, SPELL_MOUNT_TARGET_ATTUMEN, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 500);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_KNOCKDOWN:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_KNOCKDOWN, false);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 20000);
|
|
||||||
break;
|
|
||||||
case EVENT_SUMMON_ATTUMEN_MOUNTED:
|
|
||||||
if (Creature* attumen = summons.GetCreatureWithEntry(NPC_ATTUMEN_THE_HUNTSMAN))
|
|
||||||
{
|
|
||||||
_healthPct = std::max<float>(me->GetHealthPct(), attumen->GetHealthPct());
|
|
||||||
attumen->DespawnOrUnsummon();
|
|
||||||
}
|
|
||||||
|
|
||||||
me->CastSpell(me, SPELL_SUMMON_ATTUMEN_MOUNTED, true);
|
if (!CanMeleeHit())
|
||||||
me->SetVisible(false);
|
{
|
||||||
break;
|
BossAI::EnterEvadeMode(EvadeReason::EVADE_REASON_BOUNDARY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me->IsVisible())
|
scheduler.Update(diff,
|
||||||
DoMeleeAttackIfReady();
|
std::bind(&BossAI::DoMeleeAttackIfReady, this));
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckEvadeIfOutOfCombatArea() const override
|
|
||||||
{
|
|
||||||
return me->GetHomePosition().GetExactDist2d(me) > 50.0f || me->GetPositionZ() > 60.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _healthPct;
|
uint8 _phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
CreatureAI* GetAI(Creature* creature) const override
|
||||||
@@ -202,224 +423,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_attumen : public CreatureScript
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
boss_attumen() : CreatureScript("boss_attumen") { }
|
|
||||||
|
|
||||||
struct boss_attumenAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
boss_attumenAI(Creature* creature) : ScriptedAI(creature)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
_events.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_ATTUMEN1_APPEAR);
|
|
||||||
_events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 0);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, 6000);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 15000);
|
|
||||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(25000, 45000));
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* /*victim*/) override
|
|
||||||
{
|
|
||||||
if (_events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
|
||||||
{
|
|
||||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
|
||||||
Talk(SAY_ATTUMEN_KILL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
|
||||||
{
|
|
||||||
if (spellInfo->Mechanic == MECHANIC_DISARM && _events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
|
||||||
{
|
|
||||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
|
||||||
Talk(SAY_ATTUMEN_DISARM);
|
|
||||||
}
|
|
||||||
else if (spellInfo->Id == SPELL_MOUNT_TARGET_ATTUMEN)
|
|
||||||
{
|
|
||||||
me->CastSpell(me, SPELL_MOUNT_TARGET_MIDNIGHT, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpellHitTarget(Unit* target, SpellInfo const* spellInfo) override
|
|
||||||
{
|
|
||||||
if (spellInfo->Id == SPELL_MOUNT_TARGET_MIDNIGHT)
|
|
||||||
{
|
|
||||||
Talk(SAY_ATTUMEN1_MOUNT);
|
|
||||||
_events.Reset();
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_MOVE_TO_MIDNIGHT, target->GetPositionX() + 2.0f * cos(target->GetAngle(me)), target->GetPositionY() + 2.0f * std::sin(target->GetAngle(me)), target->GetPositionZ() + 0.2f, true, true, MOTION_SLOT_CONTROLLED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 point) override
|
|
||||||
{
|
|
||||||
if (type == POINT_MOTION_TYPE && point == POINT_MOVE_TO_MIDNIGHT)
|
|
||||||
{
|
|
||||||
if (TempSummon* summon = me->ToTempSummon())
|
|
||||||
if (Unit* midnight = summon->GetSummonerUnit())
|
|
||||||
midnight->GetAI()->SetData(DATA_ATTUMEN_READY, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_CLEAVE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_CLEAVE, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, urand(9000, 14000));
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_INTANGIBLE_PRESENCE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_INTANGIBLE_PRESENCE, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 30000);
|
|
||||||
break;
|
|
||||||
case EVENT_RANDOM_YELL:
|
|
||||||
Talk(SAY_ATTUMEN_RANDOM);
|
|
||||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(30000, 70000));
|
|
||||||
break;
|
|
||||||
case EVENT_CHECK_HEALTH_25:
|
|
||||||
if (me->HealthBelowPct(25))
|
|
||||||
{
|
|
||||||
me->CastSpell(me, SPELL_MOUNT_TARGET_MIDNIGHT, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_events.ScheduleEvent(EVENT_CHECK_HEALTH_25, 500);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
EventMap _events;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetKarazhanAI<boss_attumenAI>(creature);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class boss_attumen_midnight : public CreatureScript
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
boss_attumen_midnight() : CreatureScript("boss_attumen_midnight") { }
|
|
||||||
|
|
||||||
struct boss_attumen_midnightAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
boss_attumen_midnightAI(Creature* creature) : ScriptedAI(creature)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset() override
|
|
||||||
{
|
|
||||||
_events.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnterCombat(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, 6000);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 15000);
|
|
||||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(25000, 45000));
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_CHARGE, 20000);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 11000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KilledUnit(Unit* /*victim*/) override
|
|
||||||
{
|
|
||||||
if (_events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
|
||||||
{
|
|
||||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
|
||||||
Talk(SAY_ATTUMEN_KILL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
|
||||||
{
|
|
||||||
Talk(SAY_ATTUMEN2_DEATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
|
|
||||||
{
|
|
||||||
if (spellInfo->Mechanic == MECHANIC_DISARM && _events.GetNextEventTime(EVENT_KILL_TALK) == 0)
|
|
||||||
{
|
|
||||||
_events.ScheduleEvent(EVENT_KILL_TALK, 5000);
|
|
||||||
Talk(SAY_ATTUMEN_DISARM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 point) override
|
|
||||||
{
|
|
||||||
if (type == POINT_MOTION_TYPE && point == POINT_MOVE_TO_MIDNIGHT)
|
|
||||||
{
|
|
||||||
if (TempSummon* summon = me->ToTempSummon())
|
|
||||||
if (Unit* midnight = summon->GetSummonerUnit())
|
|
||||||
midnight->GetAI()->SetData(DATA_ATTUMEN_READY, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_CLEAVE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_SHADOW_CLEAVE, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_SHADOW_CLEAVE, urand(9000, 14000));
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_INTANGIBLE_PRESENCE:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_INTANGIBLE_PRESENCE, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_INTANGIBLE_PRESENCE, 30000);
|
|
||||||
break;
|
|
||||||
case EVENT_RANDOM_YELL:
|
|
||||||
Talk(SAY_ATTUMEN_RANDOM);
|
|
||||||
_events.ScheduleEvent(EVENT_RANDOM_YELL, urand(30000, 70000));
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_CHARGE:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 24.0f, true))
|
|
||||||
me->CastSpell(target, SPELL_CHARGE_MIDNIGHT, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_CHARGE, 20000);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_KNOCKDOWN:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_KNOCKDOWN, false);
|
|
||||||
_events.ScheduleEvent(EVENT_SPELL_KNOCKDOWN, 20000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
EventMap _events;
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetKarazhanAI<boss_attumen_midnightAI>(creature);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class spell_midnight_fixate : public SpellScriptLoader
|
class spell_midnight_fixate : public SpellScriptLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -460,6 +463,5 @@ void AddSC_boss_attumen()
|
|||||||
{
|
{
|
||||||
new boss_midnight();
|
new boss_midnight();
|
||||||
new boss_attumen();
|
new boss_attumen();
|
||||||
new boss_attumen_midnight();
|
|
||||||
new spell_midnight_fixate();
|
new spell_midnight_fixate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ const Position OptionalSpawn[] =
|
|||||||
{ -10899.903320f, -2085.573730f, 49.474449f, 1.38f } // Rokad the Ravager
|
{ -10899.903320f, -2085.573730f, 49.474449f, 1.38f } // Rokad the Ravager
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ObjectData const creatureData[] =
|
||||||
|
{
|
||||||
|
{ NPC_ATTUMEN_THE_HUNTSMAN, DATA_ATTUMEN },
|
||||||
|
{ NPC_MIDNIGHT, DATA_MIDNIGHT }
|
||||||
|
};
|
||||||
|
|
||||||
class instance_karazhan : public InstanceMapScript
|
class instance_karazhan : public InstanceMapScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -48,6 +54,7 @@ public:
|
|||||||
{
|
{
|
||||||
SetHeaders(DataHeader);
|
SetHeaders(DataHeader);
|
||||||
SetBossNumber(EncounterCount);
|
SetBossNumber(EncounterCount);
|
||||||
|
LoadObjectData(creatureData, nullptr);
|
||||||
|
|
||||||
// 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
|
// 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
|
||||||
OperaEvent = urand(EVENT_OZ, EVENT_RAJ);
|
OperaEvent = urand(EVENT_OZ, EVENT_RAJ);
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ enum KZDataTypes
|
|||||||
DATA_MASTERS_TERRACE_DOOR_2 = 28,
|
DATA_MASTERS_TERRACE_DOOR_2 = 28,
|
||||||
DATA_GO_SIDE_ENTRANCE_DOOR = 29,
|
DATA_GO_SIDE_ENTRANCE_DOOR = 29,
|
||||||
DATA_PRINCE = 30,
|
DATA_PRINCE = 30,
|
||||||
DATA_SPAWN_OPERA_DECORATIONS = 31
|
DATA_SPAWN_OPERA_DECORATIONS = 31,
|
||||||
|
DATA_MIDNIGHT = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KZOperaEvents
|
enum KZOperaEvents
|
||||||
@@ -71,27 +72,28 @@ enum KZOperaEvents
|
|||||||
|
|
||||||
enum KZMiscCreatures
|
enum KZMiscCreatures
|
||||||
{
|
{
|
||||||
NPC_HYAKISS_THE_LURKER = 16179,
|
NPC_HYAKISS_THE_LURKER = 16179,
|
||||||
NPC_ROKAD_THE_RAVAGER = 16181,
|
NPC_ROKAD_THE_RAVAGER = 16181,
|
||||||
NPC_SHADIKITH_THE_GLIDER = 16180,
|
NPC_SHADIKITH_THE_GLIDER = 16180,
|
||||||
NPC_TERESTIAN_ILLHOOF = 15688,
|
NPC_TERESTIAN_ILLHOOF = 15688,
|
||||||
NPC_MOROES = 15687,
|
NPC_MOROES = 15687,
|
||||||
NPC_ATTUMEN_THE_HUNTSMAN = 15550,
|
NPC_ATTUMEN_THE_HUNTSMAN = 15550,
|
||||||
NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152,
|
NPC_ATTUMEN_THE_HUNTSMAN_MOUNTED = 16152,
|
||||||
NPC_NIGHTBANE = 17225,
|
NPC_MIDNIGHT = 16151,
|
||||||
|
NPC_NIGHTBANE = 17225,
|
||||||
|
|
||||||
// Trash
|
// Trash
|
||||||
NPC_COLDMIST_WIDOW = 16171,
|
NPC_COLDMIST_WIDOW = 16171,
|
||||||
NPC_COLDMIST_STALKER = 16170,
|
NPC_COLDMIST_STALKER = 16170,
|
||||||
NPC_SHADOWBAT = 16173,
|
NPC_SHADOWBAT = 16173,
|
||||||
NPC_VAMPIRIC_SHADOWBAT = 16175,
|
NPC_VAMPIRIC_SHADOWBAT = 16175,
|
||||||
NPC_GREATER_SHADOWBAT = 16174,
|
NPC_GREATER_SHADOWBAT = 16174,
|
||||||
NPC_PHASE_HOUND = 16178,
|
NPC_PHASE_HOUND = 16178,
|
||||||
NPC_DREADBEAST = 16177,
|
NPC_DREADBEAST = 16177,
|
||||||
NPC_SHADOWBEAST = 16176,
|
NPC_SHADOWBEAST = 16176,
|
||||||
NPC_KILREK = 17229,
|
NPC_KILREK = 17229,
|
||||||
NPC_RELAY = 17645,
|
NPC_RELAY = 17645,
|
||||||
NPC_BARNES = 16812
|
NPC_BARNES = 16812
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KZGameObjectIds
|
enum KZGameObjectIds
|
||||||
|
|||||||
Reference in New Issue
Block a user