diff options
Diffstat (limited to 'src')
3 files changed, 575 insertions, 630 deletions
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp index 1994c204fbe..7e180e9496e 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -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") { } - - struct boss_thekalAI : public BossAI + boss_thekal(Creature* creature) : BossAI(creature, DATA_THEKAL) + { + Initialize(); + } + + 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; + events.Reset(); + events.ScheduleEvent(EVENT_CHANGE_PHASE_1, 3s); } - - void EnterEvadeMode(EvadeReason why) override + else { - if (!_EnterEvadeMode(why)) - return; - me->AddUnitState(UNIT_STATE_EVADE); - me->GetMotionMaster()->MoveTargetedHome(); - Reset(); + // Start resurrection timer if not already started, otherwise ignore + if (!_isResurrectTimerActive) + { + events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10s); + _isResurrectTimerActive = true; + } } - - void Reset() override + } + 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) { - 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); + creature->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); + creature->SetFullHealth(); + creature->SetImmuneToPC(false, true); + creature->SetImmuneToNPC(false, true); } + } + } - 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 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 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 UpdateAI(uint32 diff) override + { + events.Update(diff); - void SetData(uint32 type, uint32 data) override + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - if (type == DATA_FAKE_DEATH) + 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: { - // 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 only one or two of the three mobs were killed, resurrect them + _isResurrectTimerActive = false; - if (_isThekalDead && _isLorkhanDead && _isZathDead) + if (_isThekalDead) { - _isResurrectTimerActive = false; - events.Reset(); - events.ScheduleEvent(EVENT_CHANGE_PHASE_1, 3s); + DoCastSelf(SPELL_RESURRECT_VISUAL); + SetData(DATA_RESURRECTED, me->GetEntry()); + _isThekalDead = false; } - else + + if (_isLorkhanDead) { - // Start resurrection timer if not already started, otherwise ignore - if (!_isResurrectTimerActive) + if (Creature* lorkhan = instance->GetCreature(DATA_LORKHAN)) { - events.ScheduleEvent(EVENT_RESURRECT_TIMER, 10s); - _isResurrectTimerActive = true; + lorkhan->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL); + SetData(DATA_RESURRECTED, lorkhan->GetEntry()); } + _isLorkhanDead = false; } - } - 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) + + if (_isZathDead) { - creature->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH); - creature->SetFullHealth(); - creature->SetImmuneToPC(false, true); - creature->SetImmuneToNPC(false, true); + if (Creature* zath = instance->GetCreature(DATA_ZATH)) + { + zath->AI()->DoCastSelf(SPELL_RESURRECT_VISUAL); + SetData(DATA_RESURRECTED, zath->GetEntry()); + } + _isZathDead = false; } + break; } - } - - 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)) + 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: { - DoCastSelf(SPELL_FRENZY); - Talk(TALK_FRENZY); - _enraged = true; + // 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; } - } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + 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)) { - 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; + ResetThreatList(); + AttackStart(target); + DoCast(target, SPELL_CHARGE); } - } - - if (_isChangingPhase) - return; + 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 (!UpdateVictim()) - return; + if (_isChangingPhase) + return; - DoMeleeAttackIfReady(); - } + if (!UpdateVictim()) + return; - private: - bool _enraged; - bool _isThekalDead; - bool _isLorkhanDead; - bool _isZathDead; - bool _isResurrectTimerActive; - bool _isChangingPhase; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetZulGurubAI<boss_thekalAI>(creature); - } +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") { } - - struct npc_zealot_lorkhanAI : public ScriptedAI + npc_zealot_lorkhan(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()) { - npc_zealot_lorkhanAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { } + 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 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 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 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 UpdateAI(uint32 diff) override + { + _events.Update(diff); - 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); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void UpdateAI(uint32 diff) override + if (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - _events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - if (uint32 eventId = _events.ExecuteEvent()) + 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: { - 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); + 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); + 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; - } + _events.ScheduleEvent(EVENT_GREATER_HEAL, 15s, 20s); + break; } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); + case EVENT_DISARM: + DoCastVictim(SPELL_DISARM); + _events.ScheduleEvent(EVENT_DISARM, 15s, 25s); + break; + default: + break; } + } - private: - EventMap _events; - InstanceScript* _instance; - }; + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const override - { - return GetZulGurubAI<npc_zealot_lorkhanAI>(creature); - } + 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") { } - - struct npc_zealot_zathAI : public ScriptedAI + npc_zealot_zath(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()) { - 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 + 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) { - _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); + 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; } + } - 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(); - } + if (!UpdateVictim()) + return; - private: - EventMap _events; - InstanceScript* _instance; - }; + DoMeleeAttackIfReady(); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetZulGurubAI<npc_zealot_zathAI>(creature); - } +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); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp index 7ad9dae85d1..aed3be5f1f7 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp @@ -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") { } - - struct boss_venoxisAI : public BossAI + boss_venoxis(Creature* creature) : BossAI(creature, DATA_VENOXIS) + { + Initialize(); + } + + 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) - { - Initialize(); - } + _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 Initialize() - { - _inMeleeRange = 0; - _transformed = false; - _frenzied = false; - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - 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); - } + events.Update(diff); - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_VENOXIS_DEATH); - me->RemoveAllAuras(); - } + // return back to main code if we're still casting + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - 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 + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - 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) + // 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) { - // 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; - } - - DoMeleeAttackIfReady(); + // 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; } - 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); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp index 70e1bdabb1a..f5fe35d1707 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_wushoolay.cpp @@ -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 - { - boss_wushoolayAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) { } - - 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; + void JustEngagedWith(Unit* who) override + { + BossAI::JustEngagedWith(who); + events.ScheduleEvent(EVENT_LIGHTNINGCLOUD, 5s, 10s); + events.ScheduleEvent(EVENT_LIGHTNINGWAVE, 8s, 16s); + } - events.Update(diff); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.Update(diff); - 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; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - } - - DoMeleeAttackIfReady(); + 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; } - }; - 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); } |
