Scripts/ZG: Update scripts to new register model (5/5) (#26695)

This commit is contained in:
offl
2021-07-14 22:24:36 +03:00
committed by GitHub
parent 8230f937f1
commit 7f853ea735
3 changed files with 611 additions and 666 deletions

View File

@@ -94,272 +94,261 @@ enum Data
float const DamageIncrease = 40.0f;
float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
class boss_thekal : public CreatureScript
struct boss_thekal : public BossAI
{
public:
boss_thekal() : CreatureScript("boss_thekal") { }
boss_thekal(Creature* creature) : BossAI(creature, DATA_THEKAL)
{
Initialize();
}
struct boss_thekalAI : public BossAI
void Initialize()
{
_enraged = false;
_isThekalDead = false;
_isLorkhanDead = false;
_isZathDead = false;
_isResurrectTimerActive = false;
_isChangingPhase = false;
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
void Reset() override
{
if (events.IsInPhase(PHASE_TWO))
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease);
me->SetControlled(false, UNIT_STATE_ROOT);
events.Reset();
_Reset();
Initialize();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(TALK_DEATH);
// Adds are still feign-deathing, so kill them when the encounter is over
if (Creature* creature = instance->GetCreature(DATA_LORKHAN))
creature->KillSelf();
if (Creature* creature = instance->GetCreature(DATA_ZATH))
creature->KillSelf();
instance->SetBossState(DATA_LORKHAN, DONE);
instance->SetBossState(DATA_ZATH, DONE);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.SetPhase(PHASE_ONE);
events.ScheduleEvent(EVENT_MORTALCLEAVE, 4s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_SILENCE, 9s, 0, PHASE_ONE);
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_FAKE_DEATH)
{
boss_thekalAI(Creature* creature) : BossAI(creature, DATA_THEKAL)
// A mob died
switch (data)
{
Initialize();
case NPC_HIGH_PRIEST_THEKAL:
_isThekalDead = true;
break;
case NPC_ZEALOT_LORKHAN:
_isLorkhanDead = true;
break;
case NPC_ZEALOT_ZATH:
_isZathDead = true;
break;
default:
return;
}
void Initialize()
if (_isThekalDead && _isLorkhanDead && _isZathDead)
{
_enraged = false;
_isThekalDead = false;
_isLorkhanDead = false;
_isZathDead = false;
_isResurrectTimerActive = false;
_isChangingPhase = false;
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
void Reset() override
{
if (events.IsInPhase(PHASE_TWO))
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease);
me->SetControlled(false, UNIT_STATE_ROOT);
events.Reset();
_Reset();
Initialize();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
events.ScheduleEvent(EVENT_CHANGE_PHASE_1, 3s);
}
void JustDied(Unit* /*killer*/) override
else
{
_JustDied();
Talk(TALK_DEATH);
// Adds are still feign-deathing, so kill them when the encounter is over
if (Creature* creature = instance->GetCreature(DATA_LORKHAN))
creature->KillSelf();
if (Creature* creature = instance->GetCreature(DATA_ZATH))
creature->KillSelf();
instance->SetBossState(DATA_LORKHAN, DONE);
instance->SetBossState(DATA_ZATH, DONE);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.SetPhase(PHASE_ONE);
events.ScheduleEvent(EVENT_MORTALCLEAVE, 4s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_SILENCE, 9s, 0, PHASE_ONE);
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_FAKE_DEATH)
// Start resurrection timer if not already started, otherwise ignore
if (!_isResurrectTimerActive)
{
// A mob died
switch (data)
{
case NPC_HIGH_PRIEST_THEKAL:
_isThekalDead = true;
break;
case NPC_ZEALOT_LORKHAN:
_isLorkhanDead = true;
break;
case NPC_ZEALOT_ZATH:
_isZathDead = true;
break;
default:
return;
}
if (_isThekalDead && _isLorkhanDead && _isZathDead)
{
_isResurrectTimerActive = false;
events.Reset();
events.ScheduleEvent(EVENT_CHANGE_PHASE_1, 3s);
}
else
{
// Start resurrection timer if not already started, otherwise ignore
if (!_isResurrectTimerActive)
{
events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10s);
_isResurrectTimerActive = true;
}
}
}
else if (type == DATA_RESURRECTED)
{
Creature* creature = nullptr;
if (data == NPC_HIGH_PRIEST_THEKAL)
creature = me;
else if (data == NPC_ZEALOT_LORKHAN)
creature = instance->GetCreature(DATA_LORKHAN);
else if (data == NPC_ZEALOT_ZATH)
creature = instance->GetCreature(DATA_ZATH);
// Resurrect
if (creature)
{
creature->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
creature->SetFullHealth();
creature->SetImmuneToPC(false, true);
creature->SetImmuneToNPC(false, true);
}
events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10s);
_isResurrectTimerActive = true;
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth() && events.IsInPhase(PHASE_ONE))
{
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
events.DelayEvents(10s);
SetData(DATA_FAKE_DEATH, me->GetEntry());
damage = 0;
}
else if (events.IsInPhase(PHASE_TWO) && !_enraged && me->HealthBelowPct(10))
{
DoCastSelf(SPELL_FRENZY);
Talk(TALK_FRENZY);
_enraged = true;
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MORTALCLEAVE:
DoCastVictim(SPELL_MORTALCLEAVE);
events.ScheduleEvent(EVENT_MORTALCLEAVE, 15s, 20s, 0, PHASE_ONE);
break;
case EVENT_SILENCE:
DoCastVictim(SPELL_SILENCE);
events.ScheduleEvent(EVENT_SILENCE, 20s, 25s, 0, PHASE_ONE);
break;
case EVENT_RESURRECT_TIMER:
{
// If only one or two of the three mobs were killed, resurrect them
_isResurrectTimerActive = false;
if (_isThekalDead)
{
DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, me->GetEntry());
_isThekalDead = false;
}
if (_isLorkhanDead)
{
if (Creature* lorkhan = instance->GetCreature(DATA_LORKHAN))
{
lorkhan->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, lorkhan->GetEntry());
}
_isLorkhanDead = false;
}
if (_isZathDead)
{
if (Creature* zath = instance->GetCreature(DATA_ZATH))
{
zath->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, zath->GetEntry());
}
_isZathDead = false;
}
break;
}
case EVENT_CHANGE_PHASE_1:
_isChangingPhase = true;
me->SetControlled(true, UNIT_STATE_ROOT);
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->SetFullHealth();
DoCastSelf(SPELL_RESURRECT_VISUAL);
events.ScheduleEvent(EVENT_CHANGE_PHASE_2, 1s);
break;
case EVENT_CHANGE_PHASE_2:
Talk(TALK_TIGER_PHASE);
events.ScheduleEvent(EVENT_CHANGE_PHASE_3, 1s);
break;
case EVENT_CHANGE_PHASE_3:
{
// Trigger phase change
_isChangingPhase = false;
DoCastSelf(SPELL_TIGER_FORM);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease);
ResetThreatList();
me->SetControlled(false, UNIT_STATE_ROOT);
events.ScheduleEvent(EVENT_FORCEPUNCH, 4s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_SPELL_CHARGE, 12s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_SUMMONTIGERS, 25s, 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
break;
}
case EVENT_FORCEPUNCH:
DoCastVictim(SPELL_FORCEPUNCH, true);
events.ScheduleEvent(EVENT_FORCEPUNCH, 16s, 21s, 0, PHASE_TWO);
break;
case EVENT_CHARGE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true))
{
ResetThreatList();
AttackStart(target);
DoCast(target, SPELL_CHARGE);
}
events.ScheduleEvent(EVENT_CHARGE, 15s, 22s, 0, PHASE_TWO);
break;
case EVENT_SUMMONTIGERS:
DoCastVictim(SPELL_SUMMONTIGERS, true);
events.ScheduleEvent(EVENT_SUMMONTIGERS, 10s, 14s, 0, PHASE_TWO);
break;
default:
break;
}
}
if (_isChangingPhase)
return;
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
bool _enraged;
bool _isThekalDead;
bool _isLorkhanDead;
bool _isZathDead;
bool _isResurrectTimerActive;
bool _isChangingPhase;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_thekalAI>(creature);
}
else if (type == DATA_RESURRECTED)
{
Creature* creature = nullptr;
if (data == NPC_HIGH_PRIEST_THEKAL)
creature = me;
else if (data == NPC_ZEALOT_LORKHAN)
creature = instance->GetCreature(DATA_LORKHAN);
else if (data == NPC_ZEALOT_ZATH)
creature = instance->GetCreature(DATA_ZATH);
// Resurrect
if (creature)
{
creature->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
creature->SetFullHealth();
creature->SetImmuneToPC(false, true);
creature->SetImmuneToNPC(false, true);
}
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth() && events.IsInPhase(PHASE_ONE))
{
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
events.DelayEvents(10s);
SetData(DATA_FAKE_DEATH, me->GetEntry());
damage = 0;
}
else if (events.IsInPhase(PHASE_TWO) && !_enraged && me->HealthBelowPct(10))
{
DoCastSelf(SPELL_FRENZY);
Talk(TALK_FRENZY);
_enraged = true;
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_MORTALCLEAVE:
DoCastVictim(SPELL_MORTALCLEAVE);
events.ScheduleEvent(EVENT_MORTALCLEAVE, 15s, 20s, 0, PHASE_ONE);
break;
case EVENT_SILENCE:
DoCastVictim(SPELL_SILENCE);
events.ScheduleEvent(EVENT_SILENCE, 20s, 25s, 0, PHASE_ONE);
break;
case EVENT_RESURRECT_TIMER:
{
// If only one or two of the three mobs were killed, resurrect them
_isResurrectTimerActive = false;
if (_isThekalDead)
{
DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, me->GetEntry());
_isThekalDead = false;
}
if (_isLorkhanDead)
{
if (Creature* lorkhan = instance->GetCreature(DATA_LORKHAN))
{
lorkhan->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, lorkhan->GetEntry());
}
_isLorkhanDead = false;
}
if (_isZathDead)
{
if (Creature* zath = instance->GetCreature(DATA_ZATH))
{
zath->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL);
SetData(DATA_RESURRECTED, zath->GetEntry());
}
_isZathDead = false;
}
break;
}
case EVENT_CHANGE_PHASE_1:
_isChangingPhase = true;
me->SetControlled(true, UNIT_STATE_ROOT);
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->SetFullHealth();
DoCastSelf(SPELL_RESURRECT_VISUAL);
events.ScheduleEvent(EVENT_CHANGE_PHASE_2, 1s);
break;
case EVENT_CHANGE_PHASE_2:
Talk(TALK_TIGER_PHASE);
events.ScheduleEvent(EVENT_CHANGE_PHASE_3, 1s);
break;
case EVENT_CHANGE_PHASE_3:
{
// Trigger phase change
_isChangingPhase = false;
DoCastSelf(SPELL_TIGER_FORM);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease);
ResetThreatList();
me->SetControlled(false, UNIT_STATE_ROOT);
events.ScheduleEvent(EVENT_FORCEPUNCH, 4s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_SPELL_CHARGE, 12s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_SUMMONTIGERS, 25s, 0, PHASE_TWO);
events.SetPhase(PHASE_TWO);
break;
}
case EVENT_FORCEPUNCH:
DoCastVictim(SPELL_FORCEPUNCH, true);
events.ScheduleEvent(EVENT_FORCEPUNCH, 16s, 21s, 0, PHASE_TWO);
break;
case EVENT_CHARGE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.f, true))
{
ResetThreatList();
AttackStart(target);
DoCast(target, SPELL_CHARGE);
}
events.ScheduleEvent(EVENT_CHARGE, 15s, 22s, 0, PHASE_TWO);
break;
case EVENT_SUMMONTIGERS:
DoCastVictim(SPELL_SUMMONTIGERS, true);
events.ScheduleEvent(EVENT_SUMMONTIGERS, 10s, 14s, 0, PHASE_TWO);
break;
default:
break;
}
}
if (_isChangingPhase)
return;
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
bool _enraged;
bool _isThekalDead;
bool _isLorkhanDead;
bool _isZathDead;
bool _isResurrectTimerActive;
bool _isChangingPhase;
};
enum LorkhanEvents
@@ -404,103 +393,92 @@ class LorKhanSelectTargetToHeal
};
// Zealot Lor'Khan
class npc_zealot_lorkhan : public CreatureScript
struct npc_zealot_lorkhan : public ScriptedAI
{
public:
npc_zealot_lorkhan() : CreatureScript("npc_zealot_lorkhan") { }
npc_zealot_lorkhan(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
struct npc_zealot_lorkhanAI : public ScriptedAI
void Reset() override
{
_events.Reset();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
npc_zealot_lorkhanAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void Reset() override
{
_events.Reset();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_IMMUNE_TO_PC);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
me->AttackStop();
if (Creature* thekal = _instance->GetCreature(DATA_THEKAL))
thekal->AI()->SetData(DATA_FAKE_DEATH, me->GetEntry());
_events.DelayEvents(10s);
damage = 0;
}
}
void JustEngagedWith(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_SHIELD, 1s);
_events.ScheduleEvent(EVENT_BLOODLUST, 16s);
_events.ScheduleEvent(EVENT_GREATER_HEAL, 32s);
_events.ScheduleEvent(EVENT_DISARM, 6s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SHIELD:
DoCastSelf(SPELL_SHIELD);
_events.ScheduleEvent(EVENT_SHIELD, 61s);
break;
case EVENT_BLOODLUST:
DoCastSelf(SPELL_BLOODLUST);
_events.ScheduleEvent(EVENT_BLOODLUST, 20s, 28s);
break;
case EVENT_GREATER_HEAL:
{
Unit* target = nullptr;
LorKhanSelectTargetToHeal check(me, 100.0f);
Trinity::UnitLastSearcher<LorKhanSelectTargetToHeal> searcher(me, target, check);
Cell::VisitAllObjects(me, searcher, 100.0f);
if (target)
DoCast(target, SPELL_GREATERHEAL);
_events.ScheduleEvent(EVENT_GREATER_HEAL, 15s, 20s);
break;
}
case EVENT_DISARM:
DoCastVictim(SPELL_DISARM);
_events.ScheduleEvent(EVENT_DISARM, 15s, 25s);
break;
default:
break;
}
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
EventMap _events;
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_zealot_lorkhanAI>(creature);
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
me->AttackStop();
if (Creature* thekal = _instance->GetCreature(DATA_THEKAL))
thekal->AI()->SetData(DATA_FAKE_DEATH, me->GetEntry());
_events.DelayEvents(10s);
damage = 0;
}
}
void JustEngagedWith(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_SHIELD, 1s);
_events.ScheduleEvent(EVENT_BLOODLUST, 16s);
_events.ScheduleEvent(EVENT_GREATER_HEAL, 32s);
_events.ScheduleEvent(EVENT_DISARM, 6s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SHIELD:
DoCastSelf(SPELL_SHIELD);
_events.ScheduleEvent(EVENT_SHIELD, 61s);
break;
case EVENT_BLOODLUST:
DoCastSelf(SPELL_BLOODLUST);
_events.ScheduleEvent(EVENT_BLOODLUST, 20s, 28s);
break;
case EVENT_GREATER_HEAL:
{
Unit* target = nullptr;
LorKhanSelectTargetToHeal check(me, 100.0f);
Trinity::UnitLastSearcher<LorKhanSelectTargetToHeal> searcher(me, target, check);
Cell::VisitAllObjects(me, searcher, 100.0f);
if (target)
DoCast(target, SPELL_GREATERHEAL);
_events.ScheduleEvent(EVENT_GREATER_HEAL, 15s, 20s);
break;
}
case EVENT_DISARM:
DoCastVictim(SPELL_DISARM);
_events.ScheduleEvent(EVENT_DISARM, 15s, 25s);
break;
default:
break;
}
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
EventMap _events;
InstanceScript* _instance;
};
enum ZathEvents
@@ -513,103 +491,92 @@ enum ZathEvents
};
// Zealot Zath
class npc_zealot_zath : public CreatureScript
struct npc_zealot_zath : public ScriptedAI
{
public:
npc_zealot_zath() : CreatureScript("npc_zealot_zath") { }
npc_zealot_zath(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
struct npc_zealot_zathAI : public ScriptedAI
void Reset() override
{
_events.Reset();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
npc_zealot_zathAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void Reset() override
{
_events.Reset();
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (damage >= me->GetHealth())
{
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
me->AttackStop();
if (Creature* thekal = _instance->GetCreature(DATA_THEKAL))
thekal->AI()->SetData(DATA_FAKE_DEATH, me->GetEntry());
_events.DelayEvents(10s);
damage = 0;
}
}
void JustEngagedWith(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 13s);
_events.ScheduleEvent(EVENT_SINISTER_STRIKE, 8s);
_events.ScheduleEvent(EVENT_GOUGE, 25s);
_events.ScheduleEvent(EVENT_KICK, 18s);
_events.ScheduleEvent(EVENT_BLIND, 5s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SWEEPING_STRIKES:
DoCastVictim(SPELL_SWEEPINGSTRIKES);
_events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 22s, 26s);
break;
case EVENT_SINISTER_STRIKE:
DoCastVictim(SPELL_SINISTERSTRIKE);
_events.ScheduleEvent(EVENT_SINISTER_STRIKE, 8s, 16s);
break;
case EVENT_GOUGE:
DoCastVictim(SPELL_GOUGE);
if (GetThreat(me->GetVictim()))
ModifyThreatByPercent(me->GetVictim(), -100);
_events.ScheduleEvent(EVENT_GOUGE, 17s, 27s);
break;
case EVENT_KICK:
DoCastVictim(SPELL_KICK);
_events.ScheduleEvent(EVENT_KICK, 15s, 25s);
break;
case EVENT_BLIND:
DoCastVictim(SPELL_BLIND);
_events.ScheduleEvent(EVENT_BLIND, 10s, 20s);
break;
default:
break;
}
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
EventMap _events;
InstanceScript* _instance;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<npc_zealot_zathAI>(creature);
Talk(TALK_FAKE_DEATH);
me->RemoveAllAuras();
me->SetImmuneToPC(true, true);
me->SetImmuneToNPC(true, true);
DoCastSelf(SPELL_PERMANENT_FEIGN_DEATH, true);
me->AttackStop();
if (Creature* thekal = _instance->GetCreature(DATA_THEKAL))
thekal->AI()->SetData(DATA_FAKE_DEATH, me->GetEntry());
_events.DelayEvents(10s);
damage = 0;
}
}
void JustEngagedWith(Unit* /*who*/) override
{
_events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 13s);
_events.ScheduleEvent(EVENT_SINISTER_STRIKE, 8s);
_events.ScheduleEvent(EVENT_GOUGE, 25s);
_events.ScheduleEvent(EVENT_KICK, 18s);
_events.ScheduleEvent(EVENT_BLIND, 5s);
}
void UpdateAI(uint32 diff) override
{
_events.Update(diff);
if (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SWEEPING_STRIKES:
DoCastVictim(SPELL_SWEEPINGSTRIKES);
_events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 22s, 26s);
break;
case EVENT_SINISTER_STRIKE:
DoCastVictim(SPELL_SINISTERSTRIKE);
_events.ScheduleEvent(EVENT_SINISTER_STRIKE, 8s, 16s);
break;
case EVENT_GOUGE:
DoCastVictim(SPELL_GOUGE);
if (GetThreat(me->GetVictim()))
ModifyThreatByPercent(me->GetVictim(), -100);
_events.ScheduleEvent(EVENT_GOUGE, 17s, 27s);
break;
case EVENT_KICK:
DoCastVictim(SPELL_KICK);
_events.ScheduleEvent(EVENT_KICK, 15s, 25s);
break;
case EVENT_BLIND:
DoCastVictim(SPELL_BLIND);
_events.ScheduleEvent(EVENT_BLIND, 10s, 20s);
break;
default:
break;
}
}
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
private:
EventMap _events;
InstanceScript* _instance;
};
void AddSC_boss_thekal()
{
new boss_thekal();
new npc_zealot_lorkhan();
new npc_zealot_zath();
RegisterZulGurubCreatureAI(boss_thekal);
RegisterZulGurubCreatureAI(npc_zealot_lorkhan);
RegisterZulGurubCreatureAI(npc_zealot_zath);
}

View File

@@ -85,203 +85,192 @@ enum NPCs
NPC_PARASITIC_SERPENT = 14884
};
class boss_venoxis : public CreatureScript
struct boss_venoxis : public BossAI
{
public:
boss_venoxis() : CreatureScript("boss_venoxis") { }
boss_venoxis(Creature* creature) : BossAI(creature, DATA_VENOXIS)
{
Initialize();
}
struct boss_venoxisAI : public BossAI
void Initialize()
{
_inMeleeRange = 0;
_transformed = false;
_frenzied = false;
}
void Reset() override
{
_Reset();
// remove all spells and auras from previous attempts
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
// set some internally used variables to their defaults
Initialize();
events.SetPhase(PHASE_ONE);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_VENOXIS_DEATH);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
me->SetReactState(REACT_AGGRESSIVE);
// Always running events
events.ScheduleEvent(EVENT_THRASH, 5s);
// Phase one events (regular form)
events.ScheduleEvent(EVENT_HOLY_NOVA, 5s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 35s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 10s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_RENEW, 30s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_WRATH, 1min, 0, PHASE_ONE);
events.SetPhase(PHASE_ONE);
// Set zone in combat
DoZoneInCombat();
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
// check if venoxis is ready to transform
if (!_transformed && !HealthAbovePct(50))
{
boss_venoxisAI(Creature* creature) : BossAI(creature, DATA_VENOXIS)
_transformed = true;
// schedule the event that changes our phase
events.ScheduleEvent(EVENT_TRANSFORM, 100ms);
}
// we're losing health, bad, go frenzy
else if (!_frenzied && !HealthAbovePct(20))
{
_frenzied = true;
events.ScheduleEvent(EVENT_FRENZY, 100ms);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
// return back to main code if we're still casting
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
Initialize();
}
// thrash is available in all phases
case EVENT_THRASH:
DoCast(me, SPELL_THRASH, true);
events.ScheduleEvent(EVENT_THRASH, 10s, 20s);
break;
// troll form spells and Actions (first part)
case EVENT_DISPEL_MAGIC:
DoCast(me, SPELL_DISPEL_MAGIC);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 15s, 20s, 0, PHASE_ONE);
break;
case EVENT_RENEW:
DoCast(me, SPELL_RENEW);
events.ScheduleEvent(EVENT_RENEW, 25s, 30s, 0, PHASE_ONE);
break;
case EVENT_HOLY_NOVA:
_inMeleeRange = 0;
void Initialize()
{
_inMeleeRange = 0;
_transformed = false;
_frenzied = false;
}
void Reset() override
{
_Reset();
// remove all spells and auras from previous attempts
me->RemoveAllAuras();
me->SetReactState(REACT_PASSIVE);
// set some internally used variables to their defaults
Initialize();
events.SetPhase(PHASE_ONE);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_VENOXIS_DEATH);
me->RemoveAllAuras();
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
me->SetReactState(REACT_AGGRESSIVE);
// Always running events
events.ScheduleEvent(EVENT_THRASH, 5s);
// Phase one events (regular form)
events.ScheduleEvent(EVENT_HOLY_NOVA, 5s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 35s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 10s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_RENEW, 30s, 0, PHASE_ONE);
events.ScheduleEvent(EVENT_HOLY_WRATH, 1min, 0, PHASE_ONE);
events.SetPhase(PHASE_ONE);
// Set zone in combat
DoZoneInCombat();
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
// check if venoxis is ready to transform
if (!_transformed && !HealthAbovePct(50))
{
_transformed = true;
// schedule the event that changes our phase
events.ScheduleEvent(EVENT_TRANSFORM, 100ms);
}
// we're losing health, bad, go frenzy
else if (!_frenzied && !HealthAbovePct(20))
{
_frenzied = true;
events.ScheduleEvent(EVENT_FRENZY, 100ms);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
// return back to main code if we're still casting
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
for (uint8 i = 0; i < 10; ++i)
{
// thrash is available in all phases
case EVENT_THRASH:
DoCast(me, SPELL_THRASH, true);
events.ScheduleEvent(EVENT_THRASH, 10s, 20s);
break;
// troll form spells and Actions (first part)
case EVENT_DISPEL_MAGIC:
DoCast(me, SPELL_DISPEL_MAGIC);
events.ScheduleEvent(EVENT_DISPEL_MAGIC, 15s, 20s, 0, PHASE_ONE);
break;
case EVENT_RENEW:
DoCast(me, SPELL_RENEW);
events.ScheduleEvent(EVENT_RENEW, 25s, 30s, 0, PHASE_ONE);
break;
case EVENT_HOLY_NOVA:
_inMeleeRange = 0;
for (uint8 i = 0; i < 10; ++i)
{
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, i))
// check if target is within melee-distance
if (me->IsWithinMeleeRange(target))
++_inMeleeRange;
}
// trigger spellcast only if we have 3 or more targets to affect
if (_inMeleeRange >= 3)
DoCastVictim(SPELL_HOLY_NOVA);
events.ScheduleEvent(EVENT_HOLY_NOVA, 45s, 75s, 0, PHASE_ONE);
break;
case EVENT_HOLY_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_HOLY_FIRE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 45s, 60s, 0, PHASE_ONE);
break;
case EVENT_HOLY_WRATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_HOLY_WRATH);
events.ScheduleEvent(EVENT_HOLY_WRATH, 45s, 60s, 0, PHASE_ONE);
break;
//
// snake form spells and Actions
//
case EVENT_VENOM_SPIT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_VENOM_SPIT);
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 15s, 0, PHASE_TWO);
break;
case EVENT_POISON_CLOUD:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_POISON_CLOUD, 15s, 20s, 0, PHASE_TWO);
break;
case EVENT_PARASITIC_SERPENT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_SUMMON_PARASITIC_SERPENT);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 15s, 0, PHASE_TWO);
break;
case EVENT_FRENZY:
// frenzy at 20% health
DoCast(me, SPELL_FRENZY, true);
break;
//
// shape and phase-changing
//
case EVENT_TRANSFORM:
// shapeshift at 50% health
DoCast(me, SPELL_VENOXIS_TRANSFORM);
Talk(SAY_VENOXIS_TRANSFORM);
ResetThreatList();
// phase two events (snakeform)
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_CLOUD, 10s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 30s, 0, PHASE_TWO);
// transformed, start phase two
events.SetPhase(PHASE_TWO);
break;
default:
break;
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, i))
// check if target is within melee-distance
if (me->IsWithinMeleeRange(target))
++_inMeleeRange;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
// trigger spellcast only if we have 3 or more targets to affect
if (_inMeleeRange >= 3)
DoCastVictim(SPELL_HOLY_NOVA);
DoMeleeAttackIfReady();
events.ScheduleEvent(EVENT_HOLY_NOVA, 45s, 75s, 0, PHASE_ONE);
break;
case EVENT_HOLY_FIRE:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_HOLY_FIRE);
events.ScheduleEvent(EVENT_HOLY_FIRE, 45s, 60s, 0, PHASE_ONE);
break;
case EVENT_HOLY_WRATH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_HOLY_WRATH);
events.ScheduleEvent(EVENT_HOLY_WRATH, 45s, 60s, 0, PHASE_ONE);
break;
//
// snake form spells and Actions
//
case EVENT_VENOM_SPIT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_VENOM_SPIT);
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 15s, 0, PHASE_TWO);
break;
case EVENT_POISON_CLOUD:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_POISON_CLOUD);
events.ScheduleEvent(EVENT_POISON_CLOUD, 15s, 20s, 0, PHASE_TWO);
break;
case EVENT_PARASITIC_SERPENT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
DoCast(target, SPELL_SUMMON_PARASITIC_SERPENT);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 15s, 0, PHASE_TWO);
break;
case EVENT_FRENZY:
// frenzy at 20% health
DoCast(me, SPELL_FRENZY, true);
break;
//
// shape and phase-changing
//
case EVENT_TRANSFORM:
// shapeshift at 50% health
DoCast(me, SPELL_VENOXIS_TRANSFORM);
Talk(SAY_VENOXIS_TRANSFORM);
ResetThreatList();
// phase two events (snakeform)
events.ScheduleEvent(EVENT_VENOM_SPIT, 5s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_POISON_CLOUD, 10s, 0, PHASE_TWO);
events.ScheduleEvent(EVENT_PARASITIC_SERPENT, 30s, 0, PHASE_TWO);
// transformed, start phase two
events.SetPhase(PHASE_TWO);
break;
default:
break;
}
private:
uint8 _inMeleeRange;
bool _transformed;
bool _frenzied;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_venoxisAI>(creature);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
private:
uint8 _inMeleeRange;
bool _transformed;
bool _frenzied;
};
void AddSC_boss_venoxis()
{
new boss_venoxis();
RegisterZulGurubCreatureAI(boss_venoxis);
}

View File

@@ -31,63 +31,52 @@ enum Events
EVENT_LIGHTNINGWAVE = 2
};
class boss_wushoolay : public CreatureScript
struct boss_wushoolay : public BossAI
{
public:
boss_wushoolay() : CreatureScript("boss_wushoolay") { }
boss_wushoolay(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) { }
struct boss_wushoolayAI : public BossAI
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, 5s, 10s);
events.ScheduleEvent(EVENT_LIGHTNINGWAVE, 8s, 16s);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
boss_wushoolayAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) { }
void JustEngagedWith(Unit* who) override
switch (eventId)
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, 5s, 10s);
events.ScheduleEvent(EVENT_LIGHTNINGWAVE, 8s, 16s);
case EVENT_LIGHTNINGCLOUD:
DoCastVictim(SPELL_LIGHTNINGCLOUD, true);
events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, 15s, 20s);
break;
case EVENT_LIGHTNINGWAVE:
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 100, true), SPELL_LIGHTNINGWAVE);
events.ScheduleEvent(EVENT_LIGHTNINGWAVE, 12s, 16s);
break;
default:
break;
}
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_LIGHTNINGCLOUD:
DoCastVictim(SPELL_LIGHTNINGCLOUD, true);
events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, 15s, 20s);
break;
case EVENT_LIGHTNINGWAVE:
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 100, true), SPELL_LIGHTNINGWAVE);
events.ScheduleEvent(EVENT_LIGHTNINGWAVE, 12s, 16s);
break;
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulGurubAI<boss_wushoolayAI>(creature);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
};
void AddSC_boss_wushoolay()
{
new boss_wushoolay();
RegisterZulGurubCreatureAI(boss_wushoolay);
}