mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-24 14:16:31 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -140,7 +140,7 @@ public:
|
||||
uint8 oldLevel = playerTarget->GetLevel();
|
||||
|
||||
// set starting level
|
||||
uint32 startLevel = playerTarget->getClass() != CLASS_DEATH_KNIGHT
|
||||
uint32 startLevel = !playerTarget->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
||||
|
||||
|
||||
@@ -1029,7 +1029,7 @@ class spell_class_call_handler : public SpellScript
|
||||
targets.remove_if([spellInfo](WorldObject const* target) -> bool
|
||||
{
|
||||
Player const* player = target->ToPlayer();
|
||||
if (!player || player->getClass() == CLASS_DEATH_KNIGHT) // ignore all death knights from whatever spell, for some reason the condition below is not working x.x
|
||||
if (!player || player->IsClass(CLASS_DEATH_KNIGHT)) // ignore all death knights from whatever spell, for some reason the condition below is not working x.x
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,13 @@ enum Spells
|
||||
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
|
||||
};
|
||||
|
||||
enum UniqueEvents
|
||||
{
|
||||
EVENT_BERSERK = 0
|
||||
};
|
||||
|
||||
enum Hal_CreatureIds
|
||||
{
|
||||
NPC_SPIRIT_LYNX = 24143,
|
||||
NPC_TOTEM = 24224
|
||||
};
|
||||
|
||||
@@ -63,326 +67,274 @@ enum Yells
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
class boss_halazzi : public CreatureScript
|
||||
enum Groups
|
||||
{
|
||||
public:
|
||||
boss_halazzi() : CreatureScript("boss_halazzi") { }
|
||||
GROUP_LYNX = 0,
|
||||
GROUP_HUMAN = 1,
|
||||
GROUP_MERGE = 2
|
||||
};
|
||||
|
||||
struct boss_halazziAI : public ScriptedAI
|
||||
struct boss_halazzi : public BossAI
|
||||
{
|
||||
boss_halazzi(Creature* creature) : BossAI(creature, DATA_HALAZZIEVENT)
|
||||
{
|
||||
boss_halazziAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_transformCount = 0;
|
||||
_healthCheckPercentage = 0;
|
||||
_phase = PHASE_NONE;
|
||||
_lynxFormHealth = me->GetMaxHealth();
|
||||
_healthPortion = _lynxFormHealth/4;
|
||||
_humanFormHealth = (me->GetMaxHealth())/0.66666666;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
DoCastSelf(SPELL_DUAL_WIELD, true);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
BossAI::JustSummoned(summon);
|
||||
summon->Attack(me->GetVictim(), false);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
ScheduleUniqueTimedEvent(10min, [&]
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
}, EVENT_BERSERK);
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && _phase != PHASE_ENRAGE)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
PhaseHalazzi Phase;
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 SaberlashTimer;
|
||||
uint32 ShockTimer;
|
||||
uint32 TotemTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 BerserkTimer;
|
||||
uint32 TransformCount;
|
||||
|
||||
ObjectGuid LynxGUID;
|
||||
|
||||
void Reset() override
|
||||
else
|
||||
{
|
||||
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
|
||||
summons.DespawnAll();
|
||||
|
||||
LynxGUID.Clear();
|
||||
TransformCount = 0;
|
||||
BerserkTimer = 600000;
|
||||
CheckTimer = 1000;
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
Phase = PHASE_NONE;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
instance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
|
||||
Talk(SAY_AGGRO);
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summon->AI()->AttackStart(me->GetVictim());
|
||||
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
|
||||
LynxGUID = summon->GetGUID();
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void SpellHit(Unit*, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (Phase != PHASE_MERGE)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseHalazzi NextPhase)
|
||||
{
|
||||
switch (NextPhase)
|
||||
if (_phase == PHASE_LYNX || _phase == PHASE_ENRAGE)
|
||||
{
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
DoCast(me, SPELL_TRANSFORM_MERGE, true);
|
||||
me->Attack(me->GetVictim(), true);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
if (Creature* Lynx = ObjectAccessor::GetCreature(*me, LynxGUID))
|
||||
Lynx->DisappearAndDie();
|
||||
me->SetMaxHealth(600000);
|
||||
me->SetHealth(600000 - 150000 * TransformCount);
|
||||
FrenzyTimer = 16000;
|
||||
SaberlashTimer = 20000;
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_SPLIT:
|
||||
Talk(SAY_SPLIT);
|
||||
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
case PHASE_HUMAN:
|
||||
//DoCast(me, SPELL_SUMMON_LYNX, true);
|
||||
DoSpawnCreature(NPC_SPIRIT_LYNX, 5, 5, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
me->SetMaxHealth(400000);
|
||||
me->SetHealth(400000);
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_MERGE:
|
||||
if (Unit* pLynx = ObjectAccessor::GetUnit(*me, LynxGUID))
|
||||
{
|
||||
Talk(SAY_MERGE);
|
||||
pLynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
pLynx->GetMotionMaster()->Clear();
|
||||
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
|
||||
++TransformCount;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
_healthCheckPercentage = 25 * (3 - _transformCount);
|
||||
if (!HealthAbovePct(_healthCheckPercentage))
|
||||
{
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
}
|
||||
}
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (BerserkTimer <= diff)
|
||||
else if (_phase == PHASE_HUMAN)
|
||||
{
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
BerserkTimer = 60000;
|
||||
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||
{
|
||||
if (!HealthAbovePct(20) || !lynx->HealthAbovePct(20))
|
||||
{
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//should not really happen
|
||||
EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
else BerserkTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (SaberlashTimer <= diff)
|
||||
void SpellHit(Unit*, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
{
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (_phase != PHASE_MERGE)
|
||||
{
|
||||
BossAI::AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseHalazzi nextPhase)
|
||||
{
|
||||
switch (nextPhase)
|
||||
{
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (_phase == PHASE_MERGE)
|
||||
{
|
||||
DoCastSelf(SPELL_TRANSFORM_MERGE, true);
|
||||
me->RemoveAurasDueToSpell(SPELL_TRANSFORM_SPLIT2);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
summons.DespawnAll();
|
||||
me->SetMaxHealth(_lynxFormHealth);
|
||||
me->SetHealth(_lynxFormHealth - _healthPortion * _transformCount);
|
||||
scheduler.CancelGroup(GROUP_MERGE);
|
||||
scheduler.Schedule(16s, GROUP_LYNX, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_FRENZY);
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(20s, GROUP_LYNX, [this](TaskContext context)
|
||||
{
|
||||
Talk(SAY_SABER);
|
||||
// A tank with more than 490 defense skills should receive no critical hit
|
||||
//DoCast(me, 41296, true);
|
||||
DoCastVictim(SPELL_SABER_LASH, true);
|
||||
//me->RemoveAurasDueToSpell(41296);
|
||||
SaberlashTimer = 30000;
|
||||
}
|
||||
else SaberlashTimer -= diff;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
FrenzyTimer = urand(10000, 15000);
|
||||
}
|
||||
else FrenzyTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (HealthBelowPct(25 * (3 - TransformCount)))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
CheckTimer = 1000;
|
||||
}
|
||||
else CheckTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (TotemTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_TOTEM);
|
||||
TotemTimer = 20000;
|
||||
}
|
||||
else TotemTimer -= diff;
|
||||
|
||||
if (ShockTimer <= diff)
|
||||
context.Repeat(30s);
|
||||
});
|
||||
break;
|
||||
case PHASE_SPLIT:
|
||||
Talk(SAY_SPLIT);
|
||||
DoCastSelf(SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
case PHASE_HUMAN:
|
||||
scheduler.CancelGroup(GROUP_MERGE);
|
||||
DoCastSelf(SPELL_SUMMON_LYNX, true);
|
||||
me->SetMaxHealth(_humanFormHealth);
|
||||
me->SetHealth(_humanFormHealth);
|
||||
scheduler.CancelGroup(GROUP_LYNX);
|
||||
scheduler.Schedule(10s, GROUP_HUMAN, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
if (target->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
DoCast(target, SPELL_EARTHSHOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCast(target, SPELL_FLAMESHOCK);
|
||||
ShockTimer = urand(10000, 15000);
|
||||
}
|
||||
}
|
||||
else ShockTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_HUMAN)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (!HealthAbovePct(20) /*HealthBelowPct(10)*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
else
|
||||
{
|
||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
||||
if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
}
|
||||
else CheckTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
||||
if (Lynx)
|
||||
{
|
||||
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
|
||||
if (me->IsWithinDistInMap(Lynx, 6.0f))
|
||||
{
|
||||
if (TransformCount < 3)
|
||||
EnterPhase(PHASE_LYNX);
|
||||
else
|
||||
EnterPhase(PHASE_ENRAGE);
|
||||
}
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(12s, GROUP_HUMAN, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_TOTEM);
|
||||
context.Repeat(20s);
|
||||
});
|
||||
break;
|
||||
case PHASE_MERGE:
|
||||
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||
{
|
||||
Talk(SAY_MERGE);
|
||||
scheduler.CancelGroup(GROUP_HUMAN);
|
||||
lynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
lynx->GetMotionMaster()->Clear();
|
||||
lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveFollow(lynx, 0, 0);
|
||||
++_transformCount;
|
||||
scheduler.Schedule(2s, GROUP_MERGE, [this](TaskContext context)
|
||||
{
|
||||
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||
{
|
||||
if (me->IsWithinDistInMap(lynx, 6.0f))
|
||||
{
|
||||
if (_transformCount < 3)
|
||||
{
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterPhase(PHASE_ENRAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.Repeat(2s);
|
||||
});
|
||||
}
|
||||
else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_phase = nextPhase;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
BossAI::KilledUnit(victim);
|
||||
if (victim->IsPlayer())
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_HALAZZIEVENT, DONE);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetZulAmanAI<boss_halazziAI>(creature);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
private:
|
||||
uint32 _lynxFormHealth;
|
||||
uint32 _humanFormHealth;
|
||||
uint32 _healthPortion;
|
||||
uint8 _transformCount;
|
||||
uint32 _healthCheckPercentage;
|
||||
PhaseHalazzi _phase;
|
||||
};
|
||||
|
||||
// Spirits Lynx AI
|
||||
class npc_halazzi_lynx : public CreatureScript
|
||||
struct npc_halazzi_lynx : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
|
||||
npc_halazzi_lynx(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
struct npc_halazzi_lynxAI : public ScriptedAI
|
||||
void Reset() override
|
||||
{
|
||||
npc_halazzi_lynxAI(Creature* creature) : ScriptedAI(creature) { }
|
||||
scheduler.CancelAll();
|
||||
}
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 shredder_timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
||||
shredder_timer = 4000;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override {/*DoZoneInCombat();*/ }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_LYNX_FRENZY);
|
||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
||||
}
|
||||
else FrenzyTimer -= diff;
|
||||
|
||||
if (shredder_timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SHRED_ARMOR);
|
||||
shredder_timer = 4000;
|
||||
}
|
||||
else shredder_timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
return GetZulAmanAI<npc_halazzi_lynxAI>(creature);
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
||||
{
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
ScriptedAI::JustEngagedWith(who);
|
||||
|
||||
ScheduleTimedEvent(30s, 50s, [&]
|
||||
{
|
||||
DoCastSelf(SPELL_LYNX_FRENZY);
|
||||
}, 30s, 50s);
|
||||
ScheduleTimedEvent(4s, [&]{
|
||||
DoCastVictim(SPELL_SHRED_ARMOR);
|
||||
}, 4s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_halazzi()
|
||||
{
|
||||
new boss_halazzi();
|
||||
new npc_halazzi_lynx();
|
||||
RegisterZulAmanCreatureAI(boss_halazzi);
|
||||
RegisterZulAmanCreatureAI(npc_halazzi_lynx);
|
||||
}
|
||||
|
||||
@@ -447,9 +447,9 @@ public:
|
||||
PlayerAbility_Timer = urand(8000, 10000);
|
||||
PlayerClass = target->getClass() - 1;
|
||||
|
||||
if (PlayerClass == CLASS_DRUID - 1)
|
||||
if (target->IsClass(CLASS_DRUID))
|
||||
PlayerClass = CLASS_DRUID;
|
||||
else if (PlayerClass == CLASS_PRIEST - 1 && target->HasSpell(15473))
|
||||
else if (target->IsClass(CLASS_PRIEST) && target->HasSpell(15473))
|
||||
PlayerClass = CLASS_PRIEST; // shadow priest
|
||||
|
||||
SiphonSoul_Timer = 99999; // buff lasts 30 sec
|
||||
|
||||
@@ -55,6 +55,17 @@ static SHostageInfo HostageInfo[] =
|
||||
|
||||
Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const gameObjectData[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
class instance_zulaman : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -92,6 +103,7 @@ public:
|
||||
void Initialize() override
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
QuestTimer = 0;
|
||||
@@ -135,6 +147,7 @@ public:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
|
||||
@@ -32,9 +32,10 @@ enum DataTypes
|
||||
DATA_HALAZZIEVENT = 4,
|
||||
DATA_HEXLORDEVENT = 5,
|
||||
DATA_ZULJINEVENT = 6,
|
||||
DATA_CHESTLOOTED = 7,
|
||||
TYPE_RAND_VENDOR_1 = 8,
|
||||
TYPE_RAND_VENDOR_2 = 9
|
||||
DATA_SPIRIT_LYNX = 7,
|
||||
DATA_CHESTLOOTED = 8,
|
||||
TYPE_RAND_VENDOR_1 = 9,
|
||||
TYPE_RAND_VENDOR_2 = 10
|
||||
};
|
||||
|
||||
enum CreatureIds
|
||||
@@ -44,7 +45,8 @@ enum CreatureIds
|
||||
NPC_ZULJIN = 23863,
|
||||
NPC_HEXLORD = 24239,
|
||||
NPC_HALAZZI = 23577,
|
||||
NPC_NALORAKK = 23576
|
||||
NPC_NALORAKK = 23576,
|
||||
NPC_SPIRIT_LYNX = 24143
|
||||
};
|
||||
|
||||
enum GameobjectIds
|
||||
@@ -68,4 +70,6 @@ inline AI* GetZulAmanAI(T* obj)
|
||||
return GetInstanceAI<AI>(obj, ZulAmanScriptName);
|
||||
}
|
||||
|
||||
#define RegisterZulAmanCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetZulAmanAI)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,10 +53,10 @@ enum RizzleSprysprocketData
|
||||
SAY_RIZZLE_START = 0,
|
||||
SAY_RIZZLE_GRENADE = 1,
|
||||
SAY_RIZZLE_FINAL = 2,
|
||||
MSG_ESCAPE_NOTICE = 3
|
||||
};
|
||||
MSG_ESCAPE_NOTICE = 3,
|
||||
GOSSIP_GET_MOONSTONE = 21893
|
||||
|
||||
#define GOSSIP_GET_MOONSTONE "Hand over the Southfury moonstone and I'll let you go."
|
||||
};
|
||||
|
||||
Position const WPs[58] =
|
||||
{
|
||||
@@ -295,7 +295,7 @@ public:
|
||||
if (player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) != QUEST_STATUS_INCOMPLETE)
|
||||
return true;
|
||||
|
||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_GET_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
AddGossipItemFor(player, GOSSIP_GET_MOONSTONE, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, 10811, creature->GetGUID());
|
||||
|
||||
return true;
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||
CloseGossipMenuFor(player);
|
||||
if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI) && player->GetTeamId() == TEAM_HORDE)
|
||||
player->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE);
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF + 2:
|
||||
@@ -80,29 +80,42 @@ public:
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->getClass() != CLASS_DRUID)
|
||||
if (player->GetTeamId() != TEAM_HORDE)
|
||||
{
|
||||
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
||||
}
|
||||
else if (player->GetTeamId() != TEAM_HORDE)
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
AddGossipItemFor(player, 4042, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
}
|
||||
|
||||
SendGossipMenuFor(player, 4917, creature->GetGUID());
|
||||
if (player->IsClass(CLASS_DRUID))
|
||||
{
|
||||
SendGossipMenuFor(player, 4917, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
|
||||
else if (player->GetTeamId() == TEAM_HORDE)
|
||||
{
|
||||
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
|
||||
{
|
||||
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
AddGossipItemFor(player, 4042, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
}
|
||||
|
||||
SendGossipMenuFor(player, 4918, creature->GetGUID());
|
||||
if (player->IsClass(CLASS_DRUID))
|
||||
{
|
||||
SendGossipMenuFor(player, 4918, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -176,7 +189,7 @@ public:
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||
CloseGossipMenuFor(player);
|
||||
if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI) && player->GetTeamId() == TEAM_ALLIANCE)
|
||||
player->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY);
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF + 2:
|
||||
@@ -191,29 +204,41 @@ public:
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->getClass() != CLASS_DRUID)
|
||||
if (player->GetTeamId() != TEAM_ALLIANCE)
|
||||
{
|
||||
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
||||
}
|
||||
else if (player->GetTeamId() != TEAM_ALLIANCE)
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
AddGossipItemFor(player, 4041, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
}
|
||||
|
||||
SendGossipMenuFor(player, 4915, creature->GetGUID());
|
||||
if (player->IsClass(CLASS_DRUID))
|
||||
{
|
||||
SendGossipMenuFor(player, 4915, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
|
||||
else if (player->GetTeamId() == TEAM_ALLIANCE)
|
||||
{
|
||||
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
|
||||
{
|
||||
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
AddGossipItemFor(player, 4041, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
}
|
||||
|
||||
SendGossipMenuFor(player, 4914, creature->GetGUID());
|
||||
if (player->IsClass(CLASS_DRUID))
|
||||
{
|
||||
SendGossipMenuFor(player, 4914, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -853,12 +853,12 @@ public:
|
||||
{
|
||||
if (p->getPowerType() != POWER_MANA)
|
||||
return true;
|
||||
if (p->getClass() == CLASS_HUNTER)
|
||||
if (p->IsClass(CLASS_HUNTER))
|
||||
return true;
|
||||
uint8 maxIndex = p->GetMostPointsTalentTree();
|
||||
if ((p->getClass() == CLASS_PALADIN && maxIndex >= 1) || (p->getClass() == CLASS_SHAMAN && maxIndex == 1) || (p->getClass() == CLASS_DRUID && maxIndex == 1))
|
||||
if ((p->IsClass(CLASS_PALADIN) && maxIndex >= 1) || (p->IsClass(CLASS_SHAMAN) && maxIndex == 1) || (p->IsClass(CLASS_DRUID) && maxIndex == 1))
|
||||
return true;
|
||||
if (_removeHealers == ((p->getClass() == CLASS_DRUID && maxIndex == 2) || (p->getClass() == CLASS_PALADIN && maxIndex == 0) || (p->getClass() == CLASS_PRIEST && maxIndex <= 1) || (p->getClass() == CLASS_SHAMAN && maxIndex == 2)))
|
||||
if (_removeHealers == ((p->IsClass(CLASS_DRUID) && maxIndex == 2) || (p->IsClass(CLASS_PALADIN) && maxIndex == 0) || (p->IsClass(CLASS_PRIEST) && maxIndex <= 1) || (p->IsClass(CLASS_SHAMAN) && maxIndex == 2)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -2856,8 +2856,7 @@ public:
|
||||
{
|
||||
c->AI()->AttackStart(target);
|
||||
DoZoneInCombat(c);
|
||||
uint8 Class = target->getClass();
|
||||
if (Class != CLASS_DRUID)
|
||||
if (!target->IsClass(CLASS_DRUID))
|
||||
if (Player* p = target->ToPlayer())
|
||||
{
|
||||
if (Item* i = p->GetWeaponForAttack(BASE_ATTACK))
|
||||
@@ -2869,7 +2868,7 @@ public:
|
||||
|
||||
target->CastSpell(c, 60352, true); // Mirror Image, clone visual appearance
|
||||
}
|
||||
c->AI()->DoAction(Class);
|
||||
c->AI()->DoAction(target->getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@ enum Spells
|
||||
SPELL_SUMMON_SPOREBAT2 = 38490,
|
||||
SPELL_SUMMON_SPOREBAT3 = 38492,
|
||||
SPELL_SUMMON_SPOREBAT4 = 38493,
|
||||
SPELL_TOXIC_SPORES = 38574
|
||||
SPELL_TOXIC_SPORES = 38574,
|
||||
|
||||
SPELL_POISON_BOLT = 38253
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -91,6 +93,8 @@ struct boss_lady_vashj : public BossAI
|
||||
|
||||
ScheduleHealthCheckEvent(70, [&]{
|
||||
Talk(SAY_PHASE2);
|
||||
scheduler.CancelAll();
|
||||
me->CastStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MovePoint(POINT_HOME, me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ(), true, true);
|
||||
});
|
||||
@@ -178,7 +182,6 @@ struct boss_lady_vashj : public BossAI
|
||||
me->AddUnitState(UNIT_STATE_ROOT);
|
||||
me->SetFacingTo(me->GetHomePosition().GetOrientation());
|
||||
instance->SetData(DATA_ACTIVATE_SHIELD, 0);
|
||||
scheduler.CancelAll();
|
||||
scheduler.Schedule(2400ms, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
@@ -271,6 +274,42 @@ private:
|
||||
std::chrono::seconds _batTimer;
|
||||
};
|
||||
|
||||
struct npc_tainted_elemental : public ScriptedAI
|
||||
{
|
||||
npc_tainted_elemental(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
scheduler.CancelAll();
|
||||
me->SetInCombatWithZone();
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
{
|
||||
me->AddThreat(target, 1000.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
scheduler.Schedule(100ms, 500ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_POISON_BOLT);
|
||||
context.Repeat(2350ms, 2650ms);
|
||||
}).Schedule(15s, [this](TaskContext)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class spell_lady_vashj_magic_barrier : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_lady_vashj_magic_barrier);
|
||||
@@ -410,6 +449,7 @@ class spell_lady_vashj_summons : public SpellScript
|
||||
void AddSC_boss_lady_vashj()
|
||||
{
|
||||
RegisterSerpentShrineAI(boss_lady_vashj);
|
||||
RegisterSerpentShrineAI(npc_tainted_elemental);
|
||||
RegisterSpellScript(spell_lady_vashj_magic_barrier);
|
||||
RegisterSpellScript(spell_lady_vashj_remove_tainted_cores);
|
||||
RegisterSpellScript(spell_lady_vashj_summon_sporebat);
|
||||
|
||||
@@ -28,6 +28,7 @@ enum Spells
|
||||
SPELL_FLAME_QUILLS = 34229,
|
||||
SPELL_QUILL_MISSILE_1 = 34269, // 21
|
||||
SPELL_QUILL_MISSILE_2 = 34314, // 3
|
||||
SPELL_CLEAR_ALL_DEBUFFS = 34098,
|
||||
SPELL_FLAME_BUFFET = 34121,
|
||||
SPELL_EMBER_BLAST = 34341,
|
||||
SPELL_REBIRTH_PHASE2 = 34342,
|
||||
@@ -38,15 +39,18 @@ enum Spells
|
||||
SPELL_DIVE_BOMB = 35181
|
||||
};
|
||||
|
||||
const Position alarPoints[7] =
|
||||
// @todo: Alar doesnt seem to move to waypoints but instead to the triggers in p1
|
||||
const Position alarPoints[9] =
|
||||
{
|
||||
{340.15f, 58.65f, 17.71f, 4.60f},
|
||||
{388.09f, 31.54f, 20.18f, 1.61f},
|
||||
{388.18f, -32.85f, 20.18f, 0.52f},
|
||||
{340.29f, -60.19f, 17.72f, 5.71f},
|
||||
{332.0f, 0.01f, 43.0f, 0.0f},
|
||||
{331.0f, 0.01f, -2.38f, 0.0f},
|
||||
{332.0f, 0.01f, 43.0f, 0.0f}
|
||||
{335.638f, 59.4879f, 17.9319f, 4.60f}, //first platform
|
||||
{388.751007f, 31.731199f, 20.263599f, 1.61f},
|
||||
{388.790985f, -33.105900f, 20.263599f, 0.52f},
|
||||
{332.722992f, -61.159f, 17.979099f, 5.71f},
|
||||
{258.959015f, -38.687099f, 20.262899f, 5.21f},
|
||||
{259.2277997, 35.879002f, 20.263f, 4.81f}, //sixth platform
|
||||
{332.0f, 0.01f, 43.0f, 0.0f}, //quill
|
||||
{331.0f, 0.01f, -2.38f, 0.0f}, //middle (p2)
|
||||
{332.0f, 0.01f, 43.0f, 0.0f} // dive
|
||||
};
|
||||
|
||||
enum Misc
|
||||
@@ -56,26 +60,28 @@ enum Misc
|
||||
NPC_FLAME_PATCH = 20602,
|
||||
|
||||
POINT_PLATFORM = 0,
|
||||
POINT_QUILL = 4,
|
||||
POINT_MIDDLE = 5,
|
||||
POINT_DIVE = 6,
|
||||
POINT_QUILL = 6,
|
||||
POINT_MIDDLE = 7,
|
||||
POINT_DIVE = 8,
|
||||
|
||||
EVENT_SWITCH_PLATFORM = 1,
|
||||
EVENT_START_QUILLS = 2,
|
||||
EVENT_RELOCATE_MIDDLE = 3,
|
||||
EVENT_REBIRTH = 4,
|
||||
EVENT_SPELL_MELT_ARMOR = 5,
|
||||
EVENT_SPELL_FLAME_PATCH = 6,
|
||||
EVENT_SPELL_CHARGE = 7,
|
||||
EVENT_SPELL_DIVE_BOMB = 8,
|
||||
EVENT_START_DIVE = 9,
|
||||
EVENT_CAST_DIVE_BOMB = 10,
|
||||
EVENT_SUMMON_DIVE_PHOENIX = 11,
|
||||
EVENT_REBIRTH_DIVE = 12,
|
||||
EVENT_SPELL_BERSERK = 13,
|
||||
EVENT_RELOCATE_MIDDLE = 1,
|
||||
EVENT_REBIRTH = 2,
|
||||
EVENT_SPELL_BERSERK = 3,
|
||||
|
||||
EVENT_MOVE_TO_PHASE_2 = 20,
|
||||
EVENT_FINISH_DIVE = 21
|
||||
EVENT_MOVE_TO_PHASE_2 = 4,
|
||||
EVENT_FINISH_DIVE = 5
|
||||
};
|
||||
|
||||
enum PlatformMoveDirections
|
||||
{
|
||||
DIRECTION_ANTI_CLOCKWISE = 0,
|
||||
DIRECTION_CLOCKWISE = 1,
|
||||
DIRECTION_ACROSS = 2
|
||||
};
|
||||
|
||||
enum GroupAlar
|
||||
{
|
||||
GROUP_FLAME_BUFFET = 1
|
||||
};
|
||||
|
||||
// Xinef: Ruse of the Ashtongue (10946)
|
||||
@@ -85,279 +91,284 @@ enum qruseoftheAshtongue
|
||||
QUEST_RUSE_OF_THE_ASHTONGUE = 10946,
|
||||
};
|
||||
|
||||
class boss_alar : public CreatureScript
|
||||
struct boss_alar : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_alar() : CreatureScript("boss_alar") { }
|
||||
|
||||
struct boss_alarAI : public BossAI
|
||||
boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR)
|
||||
{
|
||||
boss_alarAI(Creature* creature) : BossAI(creature, DATA_ALAR)
|
||||
{
|
||||
startPath = true;
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
uint8 platform;
|
||||
uint8 noQuillTimes;
|
||||
bool startPath;
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
startPath = true;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
platform = 0;
|
||||
noQuillTimes = 0;
|
||||
me->SetModelVisible(true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 0);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
me->SetModelVisible(true);
|
||||
BossAI::JustDied(killer);
|
||||
|
||||
// Xinef: Ruse of the Ashtongue (10946)
|
||||
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
||||
{
|
||||
Player* player = itr->GetSource();
|
||||
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
|
||||
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
|
||||
player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE);
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (summon->GetEntry() == NPC_EMBER_OF_ALAR)
|
||||
summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && platform < POINT_MIDDLE)
|
||||
{
|
||||
damage = 0;
|
||||
if (events.GetNextEventTime(EVENT_REBIRTH) == 0)
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CastSpell(me, SPELL_EMBER_BLAST, true);
|
||||
|
||||
me->setAttackTimer(BASE_ATTACK, 16000);
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_RELOCATE_MIDDLE, 8000);
|
||||
events.ScheduleEvent(EVENT_MOVE_TO_PHASE_2, 12000);
|
||||
events.ScheduleEvent(EVENT_REBIRTH, 16001);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
{
|
||||
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
|
||||
startPath = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == POINT_PLATFORM)
|
||||
me->setAttackTimer(BASE_ATTACK, 1000);
|
||||
else if (id == POINT_QUILL)
|
||||
events.ScheduleEvent(EVENT_START_QUILLS, 1000);
|
||||
else if (id == POINT_DIVE)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_START_DIVE, 1000);
|
||||
events.ScheduleEvent(EVENT_CAST_DIVE_BOMB, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (startPath)
|
||||
{
|
||||
me->StopMoving();
|
||||
startPath = false;
|
||||
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
|
||||
{
|
||||
Movement::PointsArray pathPoints;
|
||||
pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
|
||||
for (uint8 i = 0; i < i_path->size(); ++i)
|
||||
{
|
||||
WaypointData const* node = i_path->at(i);
|
||||
pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z));
|
||||
}
|
||||
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SWITCH_PLATFORM:
|
||||
if (roll_chance_i(20 * noQuillTimes))
|
||||
{
|
||||
noQuillTimes = 0;
|
||||
platform = RAND(0, 3);
|
||||
me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true);
|
||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 16000);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (noQuillTimes++ > 0)
|
||||
{
|
||||
me->SetOrientation(alarPoints[platform].GetOrientation());
|
||||
me->SummonCreature(NPC_EMBER_OF_ALAR, *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[platform], false, true);
|
||||
platform = (platform + 1) % 4;
|
||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 30000);
|
||||
}
|
||||
me->setAttackTimer(BASE_ATTACK, 20000);
|
||||
break;
|
||||
case EVENT_START_QUILLS:
|
||||
me->CastSpell(me, SPELL_FLAME_QUILLS, false);
|
||||
break;
|
||||
case EVENT_RELOCATE_MIDDLE:
|
||||
me->SetPosition(alarPoints[POINT_MIDDLE]);
|
||||
break;
|
||||
case EVENT_MOVE_TO_PHASE_2:
|
||||
me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST);
|
||||
me->CastSpell(me, SPELL_REBIRTH_PHASE2, false);
|
||||
break;
|
||||
case EVENT_REBIRTH:
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
platform = POINT_MIDDLE;
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 67000);
|
||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 10000);
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 20000);
|
||||
events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000);
|
||||
break;
|
||||
case EVENT_SPELL_MELT_ARMOR:
|
||||
me->CastSpell(me->GetVictim(), SPELL_MELT_ARMOR, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 60000);
|
||||
break;
|
||||
case EVENT_SPELL_CHARGE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
me->CastSpell(target, SPELL_CHARGE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 30000);
|
||||
break;
|
||||
case EVENT_SPELL_FLAME_PATCH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 30000);
|
||||
break;
|
||||
case EVENT_SPELL_DIVE_BOMB:
|
||||
me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000);
|
||||
events.DelayEvents(15000);
|
||||
me->setAttackTimer(BASE_ATTACK, 20000);
|
||||
break;
|
||||
case EVENT_START_DIVE:
|
||||
me->CastSpell(me, SPELL_DIVE_BOMB_VISUAL, false);
|
||||
break;
|
||||
case EVENT_CAST_DIVE_BOMB:
|
||||
events.ScheduleEvent(EVENT_SUMMON_DIVE_PHOENIX, 2000);
|
||||
events.ScheduleEvent(EVENT_REBIRTH_DIVE, 6000);
|
||||
events.ScheduleEvent(EVENT_FINISH_DIVE, 10000);
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
||||
{
|
||||
me->CastSpell(target, SPELL_DIVE_BOMB, false);
|
||||
me->SetPosition(*target);
|
||||
me->StopMovingOnCurrentPos();
|
||||
}
|
||||
|
||||
me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
|
||||
break;
|
||||
case EVENT_SUMMON_DIVE_PHOENIX:
|
||||
{
|
||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true);
|
||||
me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
||||
me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
||||
break;
|
||||
}
|
||||
case EVENT_REBIRTH_DIVE:
|
||||
me->SetModelVisible(true);
|
||||
me->CastSpell(me, SPELL_REBIRTH_DIVE, false);
|
||||
break;
|
||||
case EVENT_FINISH_DIVE:
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
break;
|
||||
case EVENT_SPELL_BERSERK:
|
||||
me->CastSpell(me, SPELL_BERSERK, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->isAttackReady())
|
||||
{
|
||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
||||
{
|
||||
me->AttackerStateUpdate(me->GetVictim());
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
me->resetAttackTimer();
|
||||
ThreatContainer::StorageType const& threatList = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
|
||||
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
||||
if (me->IsWithinMeleeRange(unit))
|
||||
{
|
||||
me->AttackerStateUpdate(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
me->CastSpell(me, SPELL_FLAME_BUFFET, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetTheEyeAI<boss_alarAI>(creature);
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
BossAI::JustReachedHome();
|
||||
if (me->IsEngaged())
|
||||
{
|
||||
ConstructWaypointsAndMove();
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_canAttackCooldown = true;
|
||||
_baseAttackOverride = false;
|
||||
_spawnPhoenixes = false;
|
||||
_platform = 0;
|
||||
_platformRoll = 0;
|
||||
_noQuillTimes = 0;
|
||||
_platformMoveRepeatTimer = 16s;
|
||||
me->SetModelVisible(true);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
ConstructWaypointsAndMove();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
ScheduleTimedEvent(0s, [&]
|
||||
{
|
||||
if (roll_chance_i(20 * _noQuillTimes))
|
||||
{
|
||||
_noQuillTimes = 0;
|
||||
_platform = RAND(0, 5);
|
||||
me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true);
|
||||
_platformMoveRepeatTimer = 16s;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_noQuillTimes++ > 0)
|
||||
{
|
||||
me->SetOrientation(alarPoints[_platform].GetOrientation());
|
||||
if (_spawnPhoenixes)
|
||||
{
|
||||
SpawnPhoenixes(3, me);
|
||||
}
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[_platform], false, true);
|
||||
_platformRoll = RAND(0, 2);
|
||||
switch(_platformRoll)
|
||||
{
|
||||
case DIRECTION_ANTI_CLOCKWISE:
|
||||
_platform = (_platform+5)%6;
|
||||
_spawnPhoenixes = false;
|
||||
break;
|
||||
case DIRECTION_CLOCKWISE:
|
||||
_platform = (_platform+1)%6;
|
||||
_spawnPhoenixes = false;
|
||||
break;
|
||||
case DIRECTION_ACROSS:
|
||||
_platform = (_platform+3)%6;
|
||||
_spawnPhoenixes = true;
|
||||
break;
|
||||
}
|
||||
_platformMoveRepeatTimer = 30s;
|
||||
}
|
||||
}, _platformMoveRepeatTimer);
|
||||
ScheduleMainSpellAttack(0s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
me->SetModelVisible(true);
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
map->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
|
||||
{
|
||||
player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
{
|
||||
if (damage >= me->GetHealth() && _platform < POINT_MIDDLE)
|
||||
{
|
||||
damage = 0;
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS);
|
||||
DoCastSelf(SPELL_EMBER_BLAST, true);
|
||||
scheduler.CancelAll();
|
||||
ScheduleUniqueTimedEvent(8s, [&]{
|
||||
me->SetPosition(alarPoints[POINT_MIDDLE]);
|
||||
}, EVENT_RELOCATE_MIDDLE);
|
||||
ScheduleUniqueTimedEvent(12s, [&]
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST);
|
||||
DoCastSelf(SPELL_REBIRTH_PHASE2);
|
||||
}, EVENT_MOVE_TO_PHASE_2);
|
||||
ScheduleUniqueTimedEvent(16001ms, [&]{
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
_platform = POINT_MIDDLE;
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
ScheduleAbilities();
|
||||
}, EVENT_REBIRTH);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleAbilities()
|
||||
{
|
||||
ScheduleTimedEvent(57s, [&]
|
||||
{
|
||||
DoCastVictim(SPELL_MELT_ARMOR);
|
||||
}, 60s);
|
||||
ScheduleTimedEvent(10s, [&]
|
||||
{
|
||||
DoCastRandomTarget(SPELL_CHARGE, 0, 50.0f);
|
||||
}, 30s);
|
||||
ScheduleTimedEvent(20s, [&]
|
||||
{
|
||||
// find spell from sniffs?
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||
{
|
||||
me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
|
||||
}
|
||||
}, 30s);
|
||||
ScheduleTimedEvent(30s, [&]
|
||||
{
|
||||
me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true);
|
||||
scheduler.DelayAll(15s);
|
||||
}, 30s);
|
||||
ScheduleUniqueTimedEvent(10min, [&]
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK);
|
||||
}, EVENT_SPELL_BERSERK);
|
||||
ScheduleMainSpellAttack(0s);
|
||||
}
|
||||
|
||||
void SpawnPhoenixes(uint8 count, Unit* targetToSpawnAt)
|
||||
{
|
||||
if (targetToSpawnAt)
|
||||
{
|
||||
for (uint8 i = 0; i < count; ++i)
|
||||
{
|
||||
me->SummonCreature(NPC_EMBER_OF_ALAR, *targetToSpawnAt, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoDiveBomb()
|
||||
{
|
||||
scheduler.Schedule(2s, [this](TaskContext)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
|
||||
{
|
||||
SpawnPhoenixes(2, target);
|
||||
}
|
||||
}).Schedule(6s, [this](TaskContext)
|
||||
{
|
||||
me->SetModelVisible(true);
|
||||
DoCastSelf(SPELL_REBIRTH_DIVE);
|
||||
}).Schedule(10s, [this](TaskContext)
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
});
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_DIVE_BOMB);
|
||||
me->SetPosition(*target);
|
||||
me->StopMovingOnCurrentPos();
|
||||
}
|
||||
me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
|
||||
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
{
|
||||
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
|
||||
{
|
||||
ConstructWaypointsAndMove();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case POINT_QUILL:
|
||||
scheduler.CancelGroup(GROUP_FLAME_BUFFET);
|
||||
scheduler.Schedule(1s, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_FLAME_QUILLS);
|
||||
});
|
||||
ScheduleMainSpellAttack(13s);
|
||||
break;
|
||||
case POINT_DIVE:
|
||||
scheduler.Schedule(1s, [this](TaskContext)
|
||||
{
|
||||
DoCastSelf(SPELL_DIVE_BOMB_VISUAL);
|
||||
}).Schedule(5s, [this](TaskContext)
|
||||
{
|
||||
DoDiveBomb();
|
||||
});
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScheduleMainSpellAttack(std::chrono::seconds timer)
|
||||
{
|
||||
scheduler.Schedule(timer, GROUP_FLAME_BUFFET, [this](TaskContext context)
|
||||
{
|
||||
if (!me->IsWithinMeleeRange(me->GetVictim()) && !me->isMoving())
|
||||
{
|
||||
DoCastVictim(SPELL_FLAME_BUFFET);
|
||||
}
|
||||
context.Repeat(2s);
|
||||
});
|
||||
}
|
||||
|
||||
void ConstructWaypointsAndMove()
|
||||
{
|
||||
me->StopMoving();
|
||||
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
|
||||
{
|
||||
Movement::PointsArray pathPoints;
|
||||
pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
|
||||
for (uint8 i = 0; i < i_path->size(); ++i)
|
||||
{
|
||||
WaypointData const* node = i_path->at(i);
|
||||
pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z));
|
||||
}
|
||||
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _canAttackCooldown;
|
||||
bool _baseAttackOverride;
|
||||
bool _spawnPhoenixes;
|
||||
uint8 _platform;
|
||||
uint8 _platformRoll;
|
||||
uint8 _noQuillTimes;
|
||||
std::chrono::seconds _platformMoveRepeatTimer;
|
||||
};
|
||||
|
||||
class CastQuill : public BasicEvent
|
||||
{
|
||||
public:
|
||||
CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId)
|
||||
{
|
||||
}
|
||||
CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId){ }
|
||||
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
_caster->CastSpell(_caster, _spellId, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
Unit* _caster;
|
||||
uint32 _spellId;
|
||||
@@ -496,7 +507,7 @@ public:
|
||||
|
||||
void AddSC_boss_alar()
|
||||
{
|
||||
new boss_alar();
|
||||
RegisterTheEyeAI(boss_alar);
|
||||
new spell_alar_flame_quills();
|
||||
new spell_alar_ember_blast();
|
||||
new spell_alar_ember_blast_death();
|
||||
|
||||
@@ -68,6 +68,7 @@ struct boss_high_astromancer_solarian : public BossAI
|
||||
|
||||
ScheduleHealthCheckEvent(20, [&]{
|
||||
scheduler.CancelAll();
|
||||
me->ResumeChasingVictim();
|
||||
scheduler.Schedule(3s, [this](TaskContext context)
|
||||
{
|
||||
DoCastVictim(SPELL_VOID_BOLT);
|
||||
@@ -109,10 +110,21 @@ struct boss_high_astromancer_solarian : public BossAI
|
||||
Talk(SAY_AGGRO);
|
||||
BossAI::JustEngagedWith(who);
|
||||
me->CallForHelp(105.0f);
|
||||
me->GetMotionMaster()->Clear();
|
||||
|
||||
scheduler.Schedule(3650ms, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_ARCANE_MISSILES, 0, 40.0f);
|
||||
me->GetMotionMaster()->Clear();
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||
{
|
||||
DoCast(target, SPELL_ARCANE_MISSILES);
|
||||
}
|
||||
else
|
||||
{
|
||||
//no targets in required range
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 30.0f);
|
||||
me->CastStop();
|
||||
}
|
||||
context.Repeat(800ms, 7300ms);
|
||||
}).Schedule(21800ms, [this](TaskContext context)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,21 @@
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "the_eye.h"
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_KAELTHAS, DATA_KAELTHAS },
|
||||
{ NPC_THALADRED, DATA_THALADRED },
|
||||
{ NPC_LORD_SANGUINAR, DATA_LORD_SANGUINAR },
|
||||
{ NPC_CAPERNIAN, DATA_CAPERNIAN },
|
||||
{ NPC_TELONICUS, DATA_TELONICUS },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const gameObjectData[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
class instance_the_eye : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
@@ -30,6 +45,7 @@ public:
|
||||
instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
SetHeaders(DataHeader);
|
||||
LoadObjectData(creatureData, gameObjectData);
|
||||
SetBossNumber(MAX_ENCOUNTER);
|
||||
}
|
||||
|
||||
@@ -66,6 +82,7 @@ public:
|
||||
LordSanguinarGUID = creature->GetGUID();
|
||||
break;
|
||||
}
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* gobject) override
|
||||
@@ -98,14 +115,6 @@ public:
|
||||
return AlarGUID;
|
||||
case NPC_KAELTHAS:
|
||||
return KaelthasGUID;
|
||||
case DATA_KAEL_ADVISOR1:
|
||||
return ThaladredTheDarkenerGUID;
|
||||
case DATA_KAEL_ADVISOR2:
|
||||
return LordSanguinarGUID;
|
||||
case DATA_KAEL_ADVISOR3:
|
||||
return GrandAstromancerCapernianGUID;
|
||||
case DATA_KAEL_ADVISOR4:
|
||||
return MasterEngineerTelonicusGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
|
||||
@@ -36,10 +36,10 @@ enum EyeData
|
||||
DATA_KAELTHAS = 3,
|
||||
MAX_ENCOUNTER = 4,
|
||||
|
||||
DATA_KAEL_ADVISOR1 = 10,
|
||||
DATA_KAEL_ADVISOR2 = 11,
|
||||
DATA_KAEL_ADVISOR3 = 12,
|
||||
DATA_KAEL_ADVISOR4 = 13
|
||||
DATA_THALADRED = 10,
|
||||
DATA_LORD_SANGUINAR = 11,
|
||||
DATA_CAPERNIAN = 12,
|
||||
DATA_TELONICUS = 13
|
||||
};
|
||||
|
||||
enum EyeNPCs
|
||||
|
||||
@@ -1014,7 +1014,7 @@ class spell_dk_blood_boil : public SpellScript
|
||||
bool Load() override
|
||||
{
|
||||
_executed = false;
|
||||
return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCaster()->getClass() == CLASS_DEATH_KNIGHT;
|
||||
return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY);
|
||||
}
|
||||
|
||||
void HandleAfterHit()
|
||||
@@ -1258,7 +1258,7 @@ class spell_dk_death_gate : public SpellScript
|
||||
|
||||
SpellCastResult CheckClass()
|
||||
{
|
||||
if (GetCaster()->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!GetCaster()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
{
|
||||
SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT);
|
||||
return SPELL_FAILED_CUSTOM_ERROR;
|
||||
|
||||
@@ -446,7 +446,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
||||
{
|
||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||
{
|
||||
if (modOwner->getClass() == CLASS_HUNTER)
|
||||
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 8.0f);
|
||||
else if (modOwner->getPowerType() == POWER_MANA)
|
||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 8.0f);
|
||||
@@ -459,7 +459,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
||||
{
|
||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||
{
|
||||
if (modOwner->getClass() == CLASS_HUNTER)
|
||||
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 17.0f);
|
||||
else if (modOwner->getPowerType() == POWER_MANA)
|
||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 17.0f);
|
||||
@@ -472,7 +472,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
||||
{
|
||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||
{
|
||||
if (modOwner->getClass() == CLASS_HUNTER)
|
||||
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 26.0f);
|
||||
else if (modOwner->getPowerType() == POWER_MANA)
|
||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 26.0f);
|
||||
@@ -1673,7 +1673,7 @@ class spell_gen_pet_summoned : public SpellScript
|
||||
Player* player = GetCaster()->ToPlayer();
|
||||
if (player->GetLastPetNumber() && player->CanResummonPet(player->GetLastPetSpell()))
|
||||
{
|
||||
PetType newPetType = (player->getClass() == CLASS_HUNTER) ? HUNTER_PET : SUMMON_PET;
|
||||
PetType newPetType = (player->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET)) ? HUNTER_PET : SUMMON_PET;
|
||||
Pet* newPet = new Pet(player, newPetType);
|
||||
if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true, 100))
|
||||
{
|
||||
@@ -3545,11 +3545,11 @@ class spell_gen_on_tournament_mount : public AuraScript
|
||||
case NPC_ARGENT_WARHORSE:
|
||||
{
|
||||
if (player->HasAchieved(ACHIEVEMENT_CHAMPION_ALLIANCE) || player->HasAchieved(ACHIEVEMENT_CHAMPION_HORDE))
|
||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_CHAMPION : SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION;
|
||||
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_CHAMPION : SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION;
|
||||
else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR))
|
||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_VALIANT : SPELL_PENNANT_ARGENT_CRUSADE_VALIANT;
|
||||
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_VALIANT : SPELL_PENNANT_ARGENT_CRUSADE_VALIANT;
|
||||
else
|
||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_ASPIRANT : SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT;
|
||||
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_ASPIRANT : SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
|
||||
@@ -576,7 +576,7 @@ class spell_item_skull_of_impeding_doom : public AuraScript
|
||||
|
||||
void CalculateManaLeechAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
if (!GetCaster() || GetCaster()->getPowerType() != POWER_MANA)
|
||||
if (!GetCaster() || !GetCaster()->HasActivePowerType(POWER_MANA))
|
||||
return;
|
||||
|
||||
amount = GetCaster()->GetMaxPower(POWER_MANA) * 0.12f; // 5 ticks which reduce health by 60%
|
||||
@@ -3469,7 +3469,7 @@ class spell_item_refocus : public SpellScript
|
||||
{
|
||||
Player* caster = GetCaster()->ToPlayer();
|
||||
|
||||
if (!caster || caster->getClass() != CLASS_HUNTER)
|
||||
if (!caster || !caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
caster->RemoveCategoryCooldown(SPELL_CATEGORY_AIMED_MULTI);
|
||||
|
||||
@@ -483,7 +483,7 @@ class spell_pal_blessing_of_sanctuary : public AuraScript
|
||||
|
||||
bool CheckProc(ProcEventInfo& /*eventInfo*/)
|
||||
{
|
||||
return GetTarget()->getPowerType() == POWER_MANA;
|
||||
return GetTarget()->HasActivePowerType(POWER_MANA);
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
|
||||
@@ -969,7 +969,7 @@ class spell_pal_lay_on_hands : public SpellScript
|
||||
|
||||
// Xinef: Glyph of Divinity
|
||||
if (Unit* target = GetExplTargetUnit())
|
||||
if (target->getPowerType() == POWER_MANA)
|
||||
if (target->HasActivePowerType(POWER_MANA))
|
||||
_manaAmount = target->GetPower(POWER_MANA);
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
@@ -992,7 +992,7 @@ class spell_sha_mana_spring_totem : public SpellScript
|
||||
int32 damage = GetEffectValue();
|
||||
if (Unit* target = GetHitUnit())
|
||||
if (Unit* caster = GetCaster())
|
||||
if (target->getPowerType() == POWER_MANA)
|
||||
if (target->HasActivePowerType(POWER_MANA))
|
||||
caster->CastCustomSpell(target, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
|
||||
}
|
||||
|
||||
@@ -1017,7 +1017,7 @@ class spell_sha_mana_tide_totem : public SpellScript
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* unitTarget = GetHitUnit())
|
||||
{
|
||||
if (unitTarget->getPowerType() == POWER_MANA)
|
||||
if (unitTarget->HasActivePowerType(POWER_MANA))
|
||||
{
|
||||
int32 effValue = GetEffectValue();
|
||||
// Glyph of Mana Tide
|
||||
|
||||
Reference in New Issue
Block a user