diff options
Diffstat (limited to 'src')
6 files changed, 1534 insertions, 1904 deletions
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 41c3dfe18e2..fd31748ae86 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -20,195 +20,314 @@ enum Yells { - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, - - SAY_TYRANNUS_DEATH = -1659007, + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, + + SAY_TYRANNUS_DEATH = -1659007, }; +enum Spells +{ + SPELL_PERMAFROST = 70326, + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + SPELL_DEEP_FREEZE = 70381, + SPELL_FORGE_MACE = 68785, + SPELL_FORGE_BLADE = 68774, +}; + +#define SPELL_PERMAFROST_HELPER RAID_MODE<uint32>(68786, 70336) + enum eEvents { - EVENT_NONE, - EVENT_PERMAFROST, - EVENT_THROW_SARONITE, - EVENT_CHILLINGWAVE, - EVENT_DEEPFREEZE, + EVENT_THROW_SARONITE = 1, + EVENT_CHILLING_WAVE = 2, + EVENT_DEEP_FREEZE = 3, + EVENT_JUMP = 4, + EVENT_FORGING = 5, + EVENT_RESUME_ATTACK = 6, }; -enum Spells +enum ePhases { - SPELL_PERMAFROST = 70326, - SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - H_SPELL_CHILLING_WAVE = 70333, - SPELL_DEEP_FREEZE = 70381, - H_SPELL_DEEP_FREEZE = 72930, - SPELL_FORGE_MACE = 68785, - H_SPELL_FORGE_MACE = 70335, - SPELL_FORGE_BLADE = 68774, - H_SPELL_FORGE_BLADE = 70334, + PHASE_ONE = 1, + PHASE_TWO = 2, + PHASE_THREE = 3, + + PHASE_ONE_MASK = 1 << PHASE_ONE, + PHASE_TWO_MASK = 1 << PHASE_TWO, + PHASE_THREE_MASK = 1 << PHASE_THREE, }; -enum eEnums +enum eMiscData { - EQUIP_ID_SWORD = 49345, - EQUIP_ID_MACE = 49344, - ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 0, + POINT_FORGE = 0, }; +static const Position northForgePos = {722.5643f, -234.1615f, 527.182f, 2.16421f}; +static const Position southForgePos = {639.257f, -210.1198f, 529.015f, 0.523599f}; + class boss_garfrost : public CreatureScript { -public: - boss_garfrost() : CreatureScript("boss_garfrost") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_garfrostAI (pCreature); - } + public: + boss_garfrost() : CreatureScript("boss_garfrost") { } - struct boss_garfrostAI : public ScriptedAI - { - boss_garfrostAI(Creature *c) : ScriptedAI(c) + struct boss_garfrostAI : public BossAI { - pInstance = c->GetInstanceScript(); - } + boss_garfrostAI(Creature *creature) : BossAI(creature, DATA_GARFROST) + { + } - bool phase2; - bool phase3; - bool bAchievement; + void InitializeAI() + { + if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } - InstanceScript* pInstance; - EventMap events; + void Reset() + { + events.Reset(); + events.SetPhase(PHASE_ONE); + SetEquipmentSlots(true); + _permafrostStack = 0; - void Reset() - { - events.Reset(); + instance->SetBossState(DATA_GARFROST, NOT_STARTED); + } - phase2 = false; - phase3 = false; - bAchievement = true; + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_PERMAFROST); + events.ScheduleEvent(EVENT_THROW_SARONITE, 7000); - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); - } + instance->SetBossState(DATA_GARFROST, IN_PROGRESS); + } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_PERMAFROST); + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); + } - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS))) + DoScriptText(SAY_TYRANNUS_DEATH, tyrannus); - events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); - } + instance->SetBossState(DATA_GARFROST, DONE); + } - void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) - { - if (HealthBelowPct(66) && !phase2) + void DamageTaken(Unit* /*attacker*/, uint32& /*uiDamage*/) { - phase2 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_BLADE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); + if (events.GetPhaseMask() & PHASE_ONE_MASK && !HealthAbovePct(66)) + { + events.SetPhase(PHASE_TWO); + events.DelayEvents(8000); + DoCast(me, SPELL_THUNDERING_STOMP); + events.ScheduleEvent(EVENT_JUMP, 1500); + return; + } + + if (events.GetPhaseMask() & PHASE_TWO_MASK && !HealthAbovePct(33)) + { + events.SetPhase(PHASE_THREE); + events.DelayEvents(8000); + DoCast(me, SPELL_THUNDERING_STOMP); + events.ScheduleEvent(EVENT_JUMP, 1500); + return; + } } - if (HealthBelowPct(33) && !phase3) + void MovementInform(uint32 type, uint32 id) { - phase3 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_MACE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. - events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); + if (type != POINT_MOTION_TYPE || id != POINT_FORGE) + return; + + if (events.GetPhaseMask() & PHASE_TWO_MASK) + DoCast(me, SPELL_FORGE_BLADE); + if (events.GetPhaseMask() & PHASE_THREE_MASK) + DoCast(me, SPELL_FORGE_MACE); + events.ScheduleEvent(EVENT_RESUME_ATTACK, 5000); } - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; + void SpellHitTarget(Unit* target, const SpellEntry* spell) + { + if (spell->Id == SPELL_PERMAFROST_HELPER) + { + if (Aura *aura = target->GetAura(SPELL_PERMAFROST_HELPER)) + _permafrostStack = std::max<uint32>(_permafrostStack, aura->GetStackAmount()); + } + else if (spell->Id == SPELL_FORGE_BLADE) + SetEquipmentSlots(false, EQUIP_ID_SWORD); + else if (spell->Id == SPELL_FORGE_MACE) + SetEquipmentSlots(false, EQUIP_ID_MACE); + } - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } + uint32 GetData(uint32 type) + { + return _permafrostStack; + } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) + void UpdateAI(const uint32 diff) { - if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) - DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_THROW_SARONITE: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_THROW_SARONITE); + events.ScheduleEvent(EVENT_THROW_SARONITE, urand(12500, 20000)); + break; + case EVENT_CHILLING_WAVE: + DoCast(me, SPELL_CHILLING_WAVE); + events.ScheduleEvent(EVENT_CHILLING_WAVE, 40000, 0, PHASE_TWO); + break; + case EVENT_DEEP_FREEZE: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_DEEP_FREEZE); + events.ScheduleEvent(EVENT_DEEP_FREEZE, 35000, 0, PHASE_THREE); + break; + case EVENT_JUMP: + me->AttackStop(); + if (events.GetPhaseMask() & PHASE_TWO_MASK) + me->GetMotionMaster()->MoveJump(northForgePos.GetPositionX(), northForgePos.GetPositionY(), northForgePos.GetPositionZ(), 25.0f, 15.0f); + else if (events.GetPhaseMask() & PHASE_THREE_MASK) + me->GetMotionMaster()->MoveJump(southForgePos.GetPositionX(), southForgePos.GetPositionY(), southForgePos.GetPositionZ(), 25.0f, 15.0f); + break; + case EVENT_RESUME_ATTACK: + if (events.GetPhaseMask() & PHASE_TWO_MASK) + events.ScheduleEvent(EVENT_CHILLING_WAVE, 5000, 0, PHASE_TWO); + else if (events.GetPhaseMask() & PHASE_THREE_MASK) + events.ScheduleEvent(EVENT_DEEP_FREEZE, 10000, 0, PHASE_THREE); + AttackStart(me->getVictim()); + break; + default: + break; + } + } - pInstance->SetData(DATA_GARFROST_EVENT, DONE); - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); + DoMeleeAttackIfReady(); } - } - void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) + private: + uint32 _permafrostStack; + }; + + CreatureAI* GetAI(Creature* creature) const { - if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) - { - if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) - if (pAura->GetStackAmount() > 10) - bAchievement = false; - } + return new boss_garfrostAI(creature); } +}; + +class spell_garfrost_permafrost : public SpellScriptLoader +{ + public: + spell_garfrost_permafrost() : SpellScriptLoader("spell_garfrost_permafrost") { } - void UpdateAI(const uint32 diff) + class spell_garfrost_permafrost_SpellScript : public SpellScript { - //Return since we have no target - if (!UpdateVictim()) - return; + PrepareSpellScript(spell_garfrost_permafrost_SpellScript); - events.Update(diff); + bool Load() + { + prevented = false; + return true; + } - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + void PreventHitByLoS() + { + if (Unit* target = GetHitUnit()) + { + Unit* caster = GetCaster(); + //Temporary Line of Sight Check + std::list<GameObject*> blockList; + caster->GetGameObjectListWithEntryInGrid(blockList, GO_SARONITE_ROCK, 100.0f); + if (!blockList.empty()) + { + for (std::list<GameObject*>::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr) + { + if ((*itr)->isVisibleForInState(target)) + { + if ((*itr)->IsInBetween(caster, target, 4.0f)) + { + prevented = true; + target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, true); + PreventHitDefaultEffect(EFFECT_0); + PreventHitDefaultEffect(EFFECT_1); + PreventHitDefaultEffect(EFFECT_2); + PreventHitDamage(); + break; + } + } + } + } + } + } - while (uint32 eventId = events.ExecuteEvent()) + void RestoreImmunity() { - switch(eventId) + if (Unit* target = GetHitUnit()) { - case EVENT_THROW_SARONITE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_THROW_SARONITE); - events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); - return; - case EVENT_DEEPFREEZE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DEEP_FREEZE); - events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); - return; - case EVENT_CHILLINGWAVE: - DoCastAOE(SPELL_CHILLING_WAVE); - events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); - return; + target->ApplySpellImmune(GetSpellInfo()->Id, IMMUNITY_ID, GetSpellInfo()->Id, false); + if (prevented) + PreventHitAura(); } } - DoMeleeAttackIfReady(); - } - }; + void Register() + { + BeforeHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::PreventHitByLoS); + AfterHit += SpellHitFn(spell_garfrost_permafrost_SpellScript::RestoreImmunity); + } + bool prevented; + }; + + SpellScript* GetSpellScript() const + { + return new spell_garfrost_permafrost_SpellScript(); + } }; +class achievement_doesnt_go_to_eleven : public AchievementCriteriaScript +{ + public: + achievement_doesnt_go_to_eleven() : AchievementCriteriaScript("achievement_doesnt_go_to_eleven") { } + + bool OnCheck(Player* /*source*/, Unit* target) + { + if (target) + if (Creature* garfrost = target->ToCreature()) + if (garfrost->AI()->GetData(ACHIEV_DOESNT_GO_TO_ELEVEN) <= 10) + return true; + + return false; + } +}; void AddSC_boss_garfrost() { new boss_garfrost(); + new spell_garfrost_permafrost(); + new achievement_doesnt_go_to_eleven(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 4b64e27e80d..24831c97e9d 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -17,22 +17,28 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" - -/* - * SDComment: Spell Explosive barrage is not working. - */ +#include "Vehicle.h" enum Spells { - SPELL_PURSUED = 68987, - SPELL_CONFUSION = 69029, - SPELL_EXPLOSIVE_BARRAGE = 69263, - SPELL_MIGHTY_KICK = 69021, - SPELL_POISON_NOVA = 68989, - H_SPELL_POISON_NOVA = 70434, - SPELL_SHADOW_BOLT = 69028, - SPELL_TOXIC_WASTE = 69024, - H_SPELL_TOXIC_WASTE = 70436, + SPELL_MIGHTY_KICK = 69021, //ick's spell + SPELL_SHADOW_BOLT = 69028, //krick's spell + SPELL_TOXIC_WASTE = 69024, //krick's spell + SPELL_EXPLOSIVE_BARRAGE_KRICK = 69012, //special spell 1 + SPELL_EXPLOSIVE_BARRAGE_ICK = 69263, //special spell 1 + SPELL_POISON_NOVA = 68989, //special spell 2 + SPELL_PURSUIT = 68987, //special spell 3 + + SPELL_EXPLOSIVE_BARRAGE_SUMMON = 69015, + SPELL_EXPLODING_ORB = 69017, //visual on exploding orb + SPELL_AUTO_GROW = 69020, //grow effect on exploding orb + SPELL_HASTY_GROW = 44851, //need to check growing stacks + SPELL_EXPLOSIVE_BARRAGE_DAMAGE = 69019, //damage done by orb while exploding + + SPELL_STRANGULATING = 69413, //krick's selfcast in intro + SPELL_SUICIDE = 7, + SPELL_KRICK_KILL_CREDIT = 71308, + SPELL_NECROMANTIC_POWER = 69753, }; enum Yells @@ -69,423 +75,647 @@ enum Yells enum Events { - EVENT_NONE, - EVENT_PURSUE, - EVENT_MIGHTY_KICK, - EVENT_POISON_NOVA, - EVENT_EXPLOSIVE_BARRAGE, - EVENT_END_EXPLOSIVE_BARRAGE, - - // Krick - EVENT_SHADOW_BOLT, - EVENT_TOXIC_WASTE, + EVENT_MIGHTY_KICK = 1, + EVENT_SHADOW_BOLT = 2, + EVENT_TOXIC_WASTE = 3, + EVENT_SPECIAL = 4, //special spell selection (one of event 5, 6 or 7) + EVENT_PURSUIT = 5, + EVENT_POISON_NOVA = 6, + EVENT_EXPLOSIVE_BARRAGE = 7, // Krick OUTRO - EVENT_OUTRO_1, - EVENT_OUTRO_2, - EVENT_OUTRO_3, - EVENT_OUTRO_4, - EVENT_OUTRO_5, - EVENT_OUTRO_6, - EVENT_OUTRO_7, - EVENT_OUTRO_8, - EVENT_OUTRO_9, - EVENT_OUTRO_10, - EVENT_OUTRO_11, - EVENT_OUTRO_12, - EVENT_OUTRO_END, + EVENT_OUTRO_1 = 8, + EVENT_OUTRO_2 = 9, + EVENT_OUTRO_3 = 10, + EVENT_OUTRO_4 = 11, + EVENT_OUTRO_5 = 12, + EVENT_OUTRO_6 = 13, + EVENT_OUTRO_7 = 14, + EVENT_OUTRO_8 = 15, + EVENT_OUTRO_9 = 16, + EVENT_OUTRO_10 = 17, + EVENT_OUTRO_11 = 18, + EVENT_OUTRO_12 = 19, + EVENT_OUTRO_13 = 20, + EVENT_OUTRO_END = 21, }; enum KrickPhase { - PHASE_COMBAT, - PHASE_OUTRO, + PHASE_COMBAT = 1, + PHASE_OUTRO = 2, }; enum Actions { - ACTION_OUTRO, + ACTION_OUTRO = 1, }; -enum Misc +enum Points { - SEAT_KRICK = 0, - - // events GCD. Shall not be 0. - GCD_1 = 1, + POINT_KRICK_INTRO = 364770, + POINT_KRICK_DEATH = 364771, }; -// Krick is the Gnome. -// Ick is the Mount -// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. +static const Position outroPos[7] = +{ + {828.9342f, 118.6247f, 509.5190f, 0.0000000f}, // Krick's Outro Position + {841.0100f, 196.2450f, 573.9640f, 0.2046099f}, // Scourgelord Tyrannus Outro Position (Tele to...) + {777.2274f, 119.5521f, 510.0363f, 6.0562930f}, // Sylvanas / Jaine Outro Spawn Position (NPC_SYLVANAS_PART1) + {823.3984f, 114.4907f, 509.4899f, 0.0000000f}, // Sylvanas / Jaine Outro Move Position (1) + {835.5887f, 139.4345f, 530.9526f, 0.0000000f}, // Tyrannus Fly down Position (only not blizz one :/) + {828.9342f, 118.6247f, 514.5190f, 0.0000000f}, // Krick's Choke Position + {828.9342f, 118.6247f, 509.4958f, 0.0000000f}, // Kirck's Death Position +}; class boss_ick : public CreatureScript { -public: - boss_ick() : CreatureScript("boss_ick") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_ickAI(pCreature); - } + public: + boss_ick() : CreatureScript("boss_ick") { } - struct boss_ickAI : public ScriptedAI - { - boss_ickAI(Creature *c) : ScriptedAI(c) + struct boss_ickAI : public BossAI { - pInstance = c->GetInstanceScript(); - } + boss_ickAI(Creature *creature) : BossAI(creature, DATA_ICK), _vehicle(creature->GetVehicleKit()) + { + ASSERT(_vehicle); + } - InstanceScript* pInstance; + void InitializeAI() + { + if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } - EventMap events; + void Reset() + { + events.Reset(); + instance->SetBossState(DATA_ICK, NOT_STARTED); + } - void Reset() - { - events.Reset(); + Creature* GetKrick() + { + return ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_KRICK)); + } - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); - } + void EnterCombat(Unit * /*who*/) + { + _vehicle->InstallAllAccessories(me->GetEntry()); - Creature* GetKrick() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); - } + if (Creature* krick = GetKrick()) + DoScriptText(SAY_KRICK_AGGRO, krick); - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); - - Creature* pKrick = GetKrick(); - if (!pKrick) - pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); - - if (pKrick) - DoScriptText(SAY_KRICK_AGGRO, pKrick); - - events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - } + events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 10000); + events.ScheduleEvent(EVENT_SPECIAL, urand(30000, 35000)); - void EnterEvadeMode() - { - me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); - } + instance->SetBossState(DATA_ICK, IN_PROGRESS); + } - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pKrick = GetKrick()) + void EnterEvadeMode() { - if (pKrick->AI()) - pKrick->AI()->DoAction(ACTION_OUTRO); + me->GetMotionMaster()->Clear(); + ScriptedAI::EnterEvadeMode(); } - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); - } + void JustDied(Unit* /*pKiller*/) + { + if (Creature* krick = GetKrick()) + { + _vehicle->RemoveAllPassengers(); + if (krick->AI()) + krick->AI()->DoAction(ACTION_OUTRO); + } - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; + instance->SetBossState(DATA_ICK, DONE); + } - if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + void SetTempThreat(float threat) { - EnterEvadeMode(); - return; + _tempThreat = threat; } - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + void _ResetThreat(Unit* target) + { + DoModifyThreatPercent(target, -100); + me->AddThreat(target, _tempThreat); + } - switch(events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - case EVENT_PURSUE: - if (Creature* pKrick = GetKrick()) - DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); + if (!me->isInCombat()) + return; + + if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - me->Attack(pTarget,false); - DoScriptText(SAY_ICK_CHASE_1, me, pTarget); - DoCast(pTarget, SPELL_PURSUED); + case EVENT_TOXIC_WASTE: + if (Creature* krick = GetKrick()) + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + krick->CastSpell(target, SPELL_TOXIC_WASTE, false); + events.ScheduleEvent(EVENT_TOXIC_WASTE, urand(7000, 10000)); + break; + case EVENT_SHADOW_BOLT: + if (Creature* krick = GetKrick()) + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1)) + krick->CastSpell(target, SPELL_SHADOW_BOLT, false); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + return; + case EVENT_MIGHTY_KICK: + DoCastVictim(SPELL_MIGHTY_KICK); + events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000); + return; + case EVENT_SPECIAL: + //select one of these three special events + events.ScheduleEvent(RAND(EVENT_EXPLOSIVE_BARRAGE, EVENT_POISON_NOVA, EVENT_PURSUIT), 1000); + events.ScheduleEvent(EVENT_SPECIAL, urand(23000, 28000)); + break; + case EVENT_EXPLOSIVE_BARRAGE: + if (Creature* krick = GetKrick()) + { + DoScriptText(SAY_KRICK_BARRAGE_1, krick); + DoScriptText(SAY_KRICK_BARRAGE_2, krick); + krick->CastSpell(krick, SPELL_EXPLOSIVE_BARRAGE_KRICK, true); + DoCast(me, SPELL_EXPLOSIVE_BARRAGE_ICK); + } + events.DelayEvents(20000); + break; + case EVENT_POISON_NOVA: + if (Creature* krick = GetKrick()) + DoScriptText(SAY_KRICK_POISON_NOVA, krick); + + DoScriptText(SAY_ICK_POISON_NOVA, me); + DoCast(me, SPELL_POISON_NOVA); + break; + case EVENT_PURSUIT: + if (Creature* krick = GetKrick()) + DoScriptText(RAND(SAY_KRICK_CHASE_1, SAY_KRICK_CHASE_2, SAY_KRICK_CHASE_3), krick); + DoCast(me, SPELL_PURSUIT); + break; + default: + break; } + } - DoCast(SPELL_CONFUSION); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - return; + DoMeleeAttackIfReady(); + } - case EVENT_MIGHTY_KICK: - DoCast(me->getVictim(), SPELL_MIGHTY_KICK); - events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); - return; + private: + Vehicle* _vehicle; + float _tempThreat; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ickAI(creature); + } +}; + +class boss_krick : public CreatureScript +{ + public: + boss_krick() : CreatureScript("boss_krick") { } + + struct boss_krickAI : public ScriptedAI + { + boss_krickAI(Creature* creature) : ScriptedAI(creature), _summons(creature), _instanceScript(creature->GetInstanceScript()) + { + } + + void InitializeAI() + { + if (!_instanceScript || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } + + void Reset() + { + _events.Reset(); + _phase = PHASE_COMBAT; + _outroNpcGUID = 0; + _tyrannusGUID = 0; + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } - case EVENT_POISON_NOVA: - if (Creature* pKrick = GetKrick()) - DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); + Creature* GetIck() + { + return ObjectAccessor::GetCreature(*me, _instanceScript->GetData64(DATA_ICK)); + } - DoScriptText(SAY_ICK_POISON_NOVA, me); - DoCastAOE(SPELL_POISON_NOVA); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + void KilledUnit(Unit* victim) + { + if (victim == me) return; - case EVENT_TOXIC_WASTE: - DoCast(me->getVictim(), SPELL_TOXIC_WASTE); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + DoScriptText(RAND(SAY_KRICK_SLAY_1, SAY_KRICK_SLAY_2), me); + } + + void JustSummoned(Creature* summon) + { + _summons.Summon(summon); + if (summon->GetEntry() == NPC_EXPLODING_ORB) + { + summon->CastSpell(summon, SPELL_EXPLODING_ORB, true); + summon->CastSpell(summon, SPELL_AUTO_GROW, true); + } + } + + void DoAction(const int32 actionId) + { + if (actionId == ACTION_OUTRO) + { + Creature* tyrannusPtr = ObjectAccessor::GetCreature(*me, _instanceScript->GetData64(DATA_TYRANNUS_EVENT)); + if (tyrannusPtr) + tyrannusPtr->NearTeleportTo(outroPos[1].GetPositionX(), outroPos[1].GetPositionY(), outroPos[1].GetPositionZ(), outroPos[1].GetOrientation()); + else + tyrannusPtr = me->SummonCreature(NPC_TYRANNUS_EVENTS, outroPos[1], TEMPSUMMON_MANUAL_DESPAWN); + + tyrannusPtr->SetFlying(true); + me->GetMotionMaster()->MovePoint(POINT_KRICK_INTRO, outroPos[0].GetPositionX(), outroPos[0].GetPositionY(), outroPos[0].GetPositionZ()); + tyrannusPtr->SetFacingToObject(me); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || id != POINT_KRICK_INTRO) return; - case EVENT_SHADOW_BOLT: - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + DoScriptText(SAY_KRICK_OUTRO_1, me); + _phase = PHASE_OUTRO; + _events.Reset(); + _events.ScheduleEvent(EVENT_OUTRO_1, 1000); + } + + void UpdateAI(const uint32 diff) + { + if (_phase != PHASE_OUTRO) return; - case EVENT_EXPLOSIVE_BARRAGE: - if (Creature *pKrick = GetKrick()) + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); - DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); + case EVENT_OUTRO_1: + { + if (Creature* temp = me->GetCreature(*me, _instanceScript->GetData64(DATA_JAINA_SYLVANAS_1))) + temp->ForcedDespawn(); + + Creature* jainaOrSylvanas = NULL; + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + jainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, outroPos[2], TEMPSUMMON_MANUAL_DESPAWN); + else + jainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, outroPos[2], TEMPSUMMON_MANUAL_DESPAWN); + + if (jainaOrSylvanas) + { + jainaOrSylvanas->GetMotionMaster()->MovePoint(0, outroPos[3]); + _outroNpcGUID = jainaOrSylvanas->GetGUID(); + } + _events.ScheduleEvent(EVENT_OUTRO_2, 6000); + } + case EVENT_OUTRO_2: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + jainaOrSylvanas->SetFacingToObject(me); + me->SetFacingToObject(jainaOrSylvanas); + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_2, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_2, jainaOrSylvanas); + } + _events.ScheduleEvent(EVENT_OUTRO_3, 5000); + break; + case EVENT_OUTRO_3: + DoScriptText(SAY_KRICK_OUTRO_3, me); + _events.ScheduleEvent(EVENT_OUTRO_4, 18000); + break; + case EVENT_OUTRO_4: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_4, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_4, jainaOrSylvanas); + } + _events.ScheduleEvent(EVENT_OUTRO_5, 5000); + break; + case EVENT_OUTRO_5: + DoScriptText(SAY_KRICK_OUTRO_5, me); + _events.ScheduleEvent(EVENT_OUTRO_6, 1000); + break; + case EVENT_OUTRO_6: + if (Creature* tyrannus = me->GetCreature(*me, _instanceScript->GetData64(DATA_TYRANNUS_EVENT))) + { + tyrannus->SetSpeed(MOVE_FLIGHT, 3.5f, true); + tyrannus->GetMotionMaster()->MovePoint(1, outroPos[4]); + _tyrannusGUID = tyrannus->GetGUID(); + } + _events.ScheduleEvent(EVENT_OUTRO_7, 5000); + break; + case EVENT_OUTRO_7: + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + DoScriptText(SAY_TYRANNUS_OUTRO_7, tyrannus); + _events.ScheduleEvent(EVENT_OUTRO_8, 5000); + break; + case EVENT_OUTRO_8: + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->GetMotionMaster()->MovePoint(0, outroPos[5]); + DoCast(me, SPELL_STRANGULATING); + _events.ScheduleEvent(EVENT_OUTRO_9, 2000); + break; + case EVENT_OUTRO_9: + DoScriptText(SAY_KRICK_OUTRO_8, me); + // TODO: Tyrannus starts killing Krick. + // there shall be some visual spell effect + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + tyrannus->CastSpell(me, SPELL_NECROMANTIC_POWER, true); //not sure if it's the right spell :/ + _events.ScheduleEvent(EVENT_OUTRO_10, 1000); + break; + case EVENT_OUTRO_10: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); + me->GetMotionMaster()->MovePoint(0, outroPos[6]); + _events.ScheduleEvent(EVENT_OUTRO_11, 2000); + break; + case EVENT_OUTRO_11: + DoCast(me, SPELL_KRICK_KILL_CREDIT); // don't really know if we need it + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetHealth(0); + _events.ScheduleEvent(EVENT_OUTRO_12, 3000); + break; + case EVENT_OUTRO_12: + if (Creature* tyrannus = me->GetCreature(*me, _tyrannusGUID)) + DoScriptText(SAY_TYRANNUS_OUTRO_9, tyrannus); + _events.ScheduleEvent(EVENT_OUTRO_13, 2000); + break; + case EVENT_OUTRO_13: + if (Creature* jainaOrSylvanas = me->GetCreature(*me, _outroNpcGUID)) + { + if (_instanceScript->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_10, jainaOrSylvanas); + else + DoScriptText(SAY_SYLVANAS_OUTRO_10, jainaOrSylvanas); + } + // End of OUTRO. for now... + _events.ScheduleEvent(EVENT_OUTRO_END, 2000); + break; + case EVENT_OUTRO_END: + //if (Creature* jainaOrSylvanas = me->GetCreature(*me, npcOutroDialogGUID)) + // jainaOrSylvanas->DisappearAndDie(); + + //Todo: jaina walk and tyrannus fly to next step + me->DisappearAndDie(); + break; } + } + } - DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); - me->GetMotionMaster()->MoveIdle(); - events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec - events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); - return; + private: + InstanceScript* _instanceScript; + SummonList _summons; + EventMap _events; - case EVENT_END_EXPLOSIVE_BARRAGE: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); - break; - } + KrickPhase _phase; + uint64 _outroNpcGUID; + uint64 _tyrannusGUID; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const + { + return new boss_krickAI(creature); } - }; - }; -class boss_krick : public CreatureScript +class spell_krick_explosive_barrage : public SpellScriptLoader { -public: - boss_krick() : CreatureScript("boss_krick") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_krickAI(pCreature); - } + public: + spell_krick_explosive_barrage() : SpellScriptLoader("spell_krick_explosive_barrage") { } - struct boss_krickAI : public ScriptedAI - { - boss_krickAI(Creature *c) : ScriptedAI(c) + class spell_krick_explosive_barrage_AuraScript : public AuraScript { - pInstance = c->GetInstanceScript(); - } + PrepareAuraScript(spell_krick_explosive_barrage_AuraScript); - InstanceScript* pInstance; - EventMap events; + void HandlePeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + { + Map::PlayerList const &players = caster->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player* player = itr->getSource()) + if (player->IsWithinDist(caster, 60.0f)) // don't know correct range + caster->CastSpell(player, SPELL_EXPLOSIVE_BARRAGE_SUMMON, true); + } + } - KrickPhase phase; - uint64 uiNpcOutroDialog; - uint64 uiTyrannus; + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_krick_explosive_barrage_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; - void Reset() + AuraScript* GetAuraScript() const { - uiNpcOutroDialog = 0; - uiTyrannus = 0; - phase = PHASE_COMBAT; - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisible(false); + return new spell_krick_explosive_barrage_AuraScript(); } +}; - Creature* GetIck() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); - } +class spell_ick_explosive_barrage : public SpellScriptLoader +{ + public: + spell_ick_explosive_barrage() : SpellScriptLoader("spell_ick_explosive_barrage") { } - void KilledUnit(Unit * victim) + class spell_ick_explosive_barrage_AuraScript : public AuraScript { - if (victim == me) - return; + PrepareAuraScript(spell_ick_explosive_barrage_AuraScript); - DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); - } + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + caster->GetMotionMaster()->MoveIdle(); + } + + void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_UNIT) + { + caster->GetMotionMaster()->Clear(); + caster->GetMotionMaster()->MoveChase(caster->getVictim()); + } + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_ick_explosive_barrage_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_ick_explosive_barrage_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + AuraScript *GetAuraScript() const { - // if killed whatever the reason, it breaks the outro - uiDamage = 0; + return new spell_ick_explosive_barrage_AuraScript(); } +}; + +class spell_exploding_orb_hasty_grow : public SpellScriptLoader +{ + public: + spell_exploding_orb_hasty_grow() : SpellScriptLoader("spell_exploding_orb_hasty_grow") { } - void DoAction(const int32 actionId) + class spell_exploding_orb_hasty_grow_AuraScript : public AuraScript { - switch(actionId) + PrepareAuraScript(spell_exploding_orb_hasty_grow_AuraScript); + + void OnStackChange(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - case ACTION_OUTRO: + if (GetStackAmount() == 15) { - Position pos; - if (Creature* pIck = GetIck()) - { - // TODO: tele on Ick then run some distance. - pIck->GetNearPosition(pos, 5.0f, 3.14f); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); - } - me->SetVisible(true); - - Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); - if (pJainaOrSylvanas) { - Position pos; - me->GetNearPosition(pos, 5.0f, 0); - pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), - pos.GetAngle(me->GetPositionX(), me->GetPositionY())); - } - else { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - else - pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - } - - if (pJainaOrSylvanas) - { - pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); - me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); - uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); - } - - phase = PHASE_OUTRO; - events.Reset(); - events.ScheduleEvent(EVENT_OUTRO_1, 1000); - break; + GetTarget()->CastSpell(GetTarget(), SPELL_EXPLOSIVE_BARRAGE_DAMAGE, false); + GetTarget()->RemoveAurasDueToSpell(SPELL_HASTY_GROW); + GetTarget()->RemoveAurasDueToSpell(SPELL_AUTO_GROW); + GetTarget()->RemoveAurasDueToSpell(SPELL_EXPLODING_ORB); + if (Creature* creature = GetTarget()->ToCreature()) + creature->ForcedDespawn(1000); } } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_exploding_orb_hasty_grow_AuraScript::OnStackChange, EFFECT_0, SPELL_AURA_MOD_SCALE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_exploding_orb_hasty_grow_AuraScript(); } +}; + +class spell_krick_pursuit : public SpellScriptLoader +{ + public: + spell_krick_pursuit() : SpellScriptLoader("spell_krick_pursuit") { } - void UpdateAI(const uint32 diff) + class spell_krick_pursuit_SpellScript : public SpellScript { - if (phase == PHASE_OUTRO) + PrepareSpellScript(spell_krick_pursuit_SpellScript); + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - if (!pInstance) + if (GetCaster()->GetTypeId() != TYPEID_UNIT) return; - events.Update(diff); - switch(events.ExecuteEvent()) + Unit* caster = GetCaster(); + CreatureAI* ickAI = caster->ToCreature()->AI(); + if (Unit* target = ickAI->SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true)) { - case EVENT_OUTRO_1: - { - DoScriptText(SAY_KRICK_OUTRO_1, me); - events.ScheduleEvent(EVENT_OUTRO_2, 14000); - break; - } - case EVENT_OUTRO_2: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_3, 8500); - break; - } - case EVENT_OUTRO_3: - DoScriptText(SAY_KRICK_OUTRO_3, me); - events.ScheduleEvent(EVENT_OUTRO_4, 12000); - break; - case EVENT_OUTRO_4: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_5, 8000); - break; - } - case EVENT_OUTRO_5: - DoScriptText(SAY_KRICK_OUTRO_5, me); - events.ScheduleEvent(EVENT_OUTRO_6, 4000); - break; - case EVENT_OUTRO_6: - // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) - // store uiTyrannus - // Adjust timer so tyrannus has time to come - uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); - events.ScheduleEvent(EVENT_OUTRO_7, 1); - break; - case EVENT_OUTRO_7: - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); - events.ScheduleEvent(EVENT_OUTRO_8, 7000); - break; - case EVENT_OUTRO_8: - DoScriptText(SAY_KRICK_OUTRO_8, me); - // TODO: Tyrannus starts killing Krick. - // there shall be some visual spell effect - events.ScheduleEvent(EVENT_OUTRO_9, 6000); - break; - case EVENT_OUTRO_9: - // tyrannus kills krick - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetHealth(0); - - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); - - events.ScheduleEvent(EVENT_OUTRO_10, 12000); - break; - case EVENT_OUTRO_10: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); - } - - // End of OUTRO. for now... - events.ScheduleEvent(EVENT_OUTRO_END, 8000); - break; - } - case EVENT_OUTRO_END: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - pNpcDialog->DisappearAndDie(); - - me->DisappearAndDie(); - break; - } + DoScriptText(SAY_ICK_CHASE_1, caster, target); + caster->AddAura(GetSpellInfo()->Id, target); + CAST_AI(boss_ick::boss_ickAI, ickAI)->SetTempThreat(caster->getThreatManager().getThreat(target)); + caster->AddThreat(target, float(GetEffectValue())); + target->AddThreat(caster, float(GetEffectValue())); } - return; } + + void Register() + { + OnEffect += SpellEffectFn(spell_krick_pursuit_SpellScript::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + class spell_krick_pursuit_AuraScript : public AuraScript + { + PrepareAuraScript(spell_krick_pursuit_AuraScript); + + void HandleExtraEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (Creature* creCaster = caster->ToCreature()) + CAST_AI(boss_ick::boss_ickAI, creCaster->AI())->_ResetThreat(GetTarget()); + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_krick_pursuit_AuraScript::HandleExtraEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krick_pursuit_SpellScript(); } - }; + AuraScript* GetAuraScript() const + { + return new spell_krick_pursuit_AuraScript(); + } }; +class spell_krick_pursuit_confusion : public SpellScriptLoader +{ + public: + spell_krick_pursuit_confusion() : SpellScriptLoader("spell_krick_pursuit_confusion") { } + + class spell_krick_pursuit_confusion_AuraScript : public AuraScript + { + PrepareAuraScript(spell_krick_pursuit_confusion_AuraScript); + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + GetTarget()->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + GetTarget()->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_krick_pursuit_confusion_AuraScript::OnApply, EFFECT_2, SPELL_AURA_LINKED, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_krick_pursuit_confusion_AuraScript::OnRemove, EFFECT_2, SPELL_AURA_LINKED, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_krick_pursuit_confusion_AuraScript(); + } +}; void AddSC_boss_ick() { new boss_ick(); new boss_krick(); + new spell_krick_explosive_barrage(); + new spell_ick_explosive_barrage(); + new spell_exploding_orb_hasty_grow(); + new spell_krick_pursuit(); + new spell_krick_pursuit_confusion(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 7c4f93e277c..fd2c5dff9d5 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -18,266 +18,353 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -/* - * TODO: - * - Intro/Outro - * - improve script of Rimefang - */ - enum Yells { - SAY_AMBUSH_1 = -1658050, - SAY_AMBUSH_2 = -1658051, - SAY_GAUNTLET_START = -1658052, - SAY_INTRO_1 = -1658053, - SAY_INTRO_2 = -1658054, - - SAY_AGGRO = -1658055, - SAY_SLAY_1 = -1658056, - SAY_SLAY_2 = -1658057, - SAY_DEATH = -1658058, - SAY_MARK_RIMEFANG_1 = -1658059, - SAY_MARK_RIMEFANG_2 = -1658060, - SAY_DARK_MIGHT_1 = -1658061, - SAY_DARK_MIGHT_2 = -1658062, - - SAY_GORKUN_OUTRO_1 = -1658063, - SAY_GORKUN_OUTRO_2 = -1658064, - SAY_JAYNA_OUTRO_3 = -1658065, - SAY_SYLVANAS_OUTRO_3 = -1658066, - SAY_JAYNA_OUTRO_4 = -1658067, - SAY_SYLVANAS_OUTRO_4 = -1658068, - SAY_JAYNA_OUTRO_5 = -1658069, + SAY_AMBUSH_1 = -1658050, + SAY_AMBUSH_2 = -1658051, + SAY_GAUNTLET_START = -1658052, + SAY_TYRANNUS_INTRO_1 = -1658053, + SAY_GORKUN_INTRO_2 = -1658054, + SAY_TYRANNUS_INTRO_3 = -1658055, + + SAY_AGGRO = -1658056, + SAY_SLAY_1 = -1658057, + SAY_SLAY_2 = -1658058, + SAY_DEATH = -1658059, + SAY_MARK_RIMEFANG_1 = -1658060, + SAY_MARK_RIMEFANG_2 = -1658061, + SAY_DARK_MIGHT_1 = -1658062, + SAY_DARK_MIGHT_2 = -1658063, + + SAY_GORKUN_OUTRO_1 = -1658064, + SAY_GORKUN_OUTRO_2 = -1658065, + SAY_JAYNA_OUTRO_3 = -1658066, + SAY_SYLVANAS_OUTRO_3 = -1658067, + SAY_JAYNA_OUTRO_4 = -1658068, + SAY_SYLVANAS_OUTRO_4 = -1658069, + SAY_JAYNA_OUTRO_5 = -1658070, }; enum Spells { - SPELL_FORCEFUL_SMASH = 69155, - H_SPELL_FORCEFUL_SMASH = 69627, - SPELL_OVERLORDS_BRAND = 69172, - SPELL_OVERLORD_BRAND_DAMAGE = 69189, - SPELL_OVERLORD_BRAND_HEAL = 69190, - SPELL_DARK_MIGHT = 69167, - H_SPELL_DARK_MIGHT = 69629, - SPELL_HOARFROST = 69246, - SPELL_MARK_OF_RIMEFANG = 69275, - SPELL_ICY_BLAST = 69233, - H_SPELL_ICY_BLAST = 69646, - SPELL_ICY_BLAST_2 = 69238, - H_SPELL_ICY_BLAST_2 = 69628, + SPELL_OVERLORD_BRAND = 69172, + SPELL_OVERLORD_BRAND_HEAL = 69190, + SPELL_OVERLORD_BRAND_DAMAGE = 69189, + SPELL_FORCEFUL_SMASH = 69155, + SPELL_UNHOLY_POWER = 69167, + SPELL_MARK_OF_RIMEFANG = 69275, + SPELL_HOARFROST = 69246, + + SPELL_ICY_BLAST = 69232, + SPELL_ICY_BLAST_AURA = 69238, + + SPELL_EJECT_ALL_PASSENGERS = 50630, + SPELL_FULL_HEAL = 43979, }; enum Events { - EVENT_NONE, - EVENT_FORCEFUL_SMASH, - EVENT_OVERLORDS_BRAND, - EVENT_DARK_MIGHT, + EVENT_OVERLORD_BRAND = 1, + EVENT_FORCEFUL_SMASH = 2, + EVENT_UNHOLY_POWER = 3, + EVENT_MARK_OF_RIMEFANG = 4, // Rimefang - EVENT_MARK_OF_RIMEFANG, - EVENT_HOARFROST, - EVENT_ICY_BLAST, - EVENT_ICY_BLAST_2, + EVENT_MOVE_NEXT = 5, + EVENT_HOARFROST = 6, + EVENT_ICY_BLAST = 7, + + EVENT_INTRO_1 = 8, + EVENT_INTRO_2 = 9, + EVENT_INTRO_3 = 10, + EVENT_COMBAT_START = 11, }; -enum Misc +enum Phases { - SEAT_TYRANNUS = 0 + PHASE_NONE = 0, + PHASE_INTRO = 1, + PHASE_COMBAT = 2, + PHASE_OUTRO = 3, }; -class boss_tyrannus : public CreatureScript +enum Actions { -public: - boss_tyrannus() : CreatureScript("boss_tyrannus") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_tyrannusAI(pCreature); - } + ACTION_START_INTRO = 1, + ACTION_START_RIMEFANG = 2, + ACTION_START_OUTRO = 3, +}; - struct boss_tyrannusAI : public ScriptedAI - { - boss_tyrannusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceScript(); - } +#define GUID_HOARFROST 1 - InstanceScript* pInstance; - EventMap events; +static const Position rimefangPos[10] = +{ + {1017.299f, 168.9740f, 642.9259f, 0.000000f}, + {1047.868f, 126.4931f, 665.0453f, 0.000000f}, + {1069.828f, 138.3837f, 665.0453f, 0.000000f}, + {1063.042f, 164.5174f, 665.0453f, 0.000000f}, + {1031.158f, 195.1441f, 665.0453f, 0.000000f}, + {1019.087f, 197.8038f, 665.0453f, 0.000000f}, + {967.6233f, 168.9670f, 665.0453f, 0.000000f}, + {969.1198f, 140.4722f, 665.0453f, 0.000000f}, + {986.7153f, 141.6424f, 665.0453f, 0.000000f}, + {1012.601f, 142.4965f, 665.0453f, 0.000000f}, +}; - void Reset() - { - events.Reset(); +static const Position miscPos = {1018.376f, 167.2495f, 628.2811f, 0.000000f}; //tyrannus combat start position - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); - } +class boss_tyrannus : public CreatureScript +{ + public: + boss_tyrannus() : CreatureScript("boss_tyrannus") { } - Creature* GetRimefang() + struct boss_tyrannusAI : public BossAI { - return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); - } + boss_tyrannusAI(Creature* creature) : BossAI(creature, DATA_TYRANNUS) + { + } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->ExitVehicle(); + void InitializeAI() + { + if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != GetScriptId(PoSScriptName)) + me->IsAIEnabled = false; + else if (!me->isDead()) + Reset(); + } - // restore health if any damage done during intro - me->SetFullHealth(); + void Reset() + { + events.Reset(); + events.SetPhase(PHASE_NONE); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + instance->SetBossState(DATA_TYRANNUS, NOT_STARTED); + } - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); + Creature* GetRimefang() + { + return ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_RIMEFANG)); + } - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); - events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); - } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } + void AttackStart(Unit* victim) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); + if (victim && me->Attack(victim, true) && !(events.GetPhaseMask() & (1 << PHASE_INTRO))) + me->GetMotionMaster()->MoveChase(victim); + } - if (pInstance) + void EnterEvadeMode() { - pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); - if (Creature* pRimefang = GetRimefang()) - pRimefang->ForcedDespawn(); - } - } + instance->SetBossState(DATA_TYRANNUS, FAIL); + if (Creature* rimefang = GetRimefang()) + rimefang->AI()->EnterEvadeMode(); - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; + me->ForcedDespawn(); + } - events.Update(diff); + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + DoScriptText(RAND(SAY_SLAY_1, SAY_SLAY_2), me); + } - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + instance->SetBossState(DATA_TYRANNUS, DONE); + } - while (uint32 eventId = events.ExecuteEvent()) + void DoAction(const int32 actionId) { - switch(eventId) + if (actionId == ACTION_START_INTRO) { - case EVENT_FORCEFUL_SMASH: - DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - return; - case EVENT_OVERLORDS_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_OVERLORDS_BRAND); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); - return; - case EVENT_DARK_MIGHT: - DoScriptText(SAY_DARK_MIGHT_1, me); - DoScriptText(SAY_DARK_MIGHT_2, me); - DoCast(me, SPELL_DARK_MIGHT); - events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); - return; + DoScriptText(SAY_TYRANNUS_INTRO_1, me); + events.SetPhase(PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_1, 14000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_2, 22000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_INTRO_3, 34000, 0, PHASE_INTRO); + events.ScheduleEvent(EVENT_COMBAT_START, 36000, 0, PHASE_INTRO); + instance->SetBossState(DATA_TYRANNUS, IN_PROGRESS); } } - DoMeleeAttackIfReady(); - } - }; + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim() && !(events.GetPhaseMask() & (1 << PHASE_INTRO))) + return; -}; + events.Update(diff); -class boss_rimefang : public CreatureScript -{ -public: - boss_rimefang() : CreatureScript("boss_rimefang") { } + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_INTRO_1: + //DoScriptText(SAY_GORKUN_INTRO_2, pGorkunOrVictus); + break; + case EVENT_INTRO_2: + DoScriptText(SAY_TYRANNUS_INTRO_3, me); + break; + case EVENT_INTRO_3: + me->ExitVehicle(); + me->GetMotionMaster()->MovePoint(0, miscPos); + break; + case EVENT_COMBAT_START: + if (Creature* rimefang = me->GetCreature(*me, instance->GetData64(DATA_RIMEFANG))) + rimefang->AI()->DoAction(ACTION_START_RIMEFANG); //set rimefang also infight + + events.SetPhase(PHASE_COMBAT); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoCast(me, SPELL_FULL_HEAL); + me->SetInCombatWithZone(); + events.ScheduleEvent(EVENT_OVERLORD_BRAND, urand(5000, 7000)); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, urand(14000, 16000)); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, urand(25000, 27000)); + break; + case EVENT_OVERLORD_BRAND: + if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) + DoCast(target, SPELL_OVERLORD_BRAND); + events.ScheduleEvent(EVENT_OVERLORD_BRAND, urand(11000, 12000)); + break; + case EVENT_FORCEFUL_SMASH: + DoCastVictim(SPELL_FORCEFUL_SMASH); + events.ScheduleEvent(EVENT_UNHOLY_POWER, 1000); + break; + case EVENT_UNHOLY_POWER: + DoScriptText(SAY_DARK_MIGHT_1, me); + DoScriptText(SAY_DARK_MIGHT_2, me); + DoCast(me, SPELL_UNHOLY_POWER); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, urand(40000, 48000)); + break; + case EVENT_MARK_OF_RIMEFANG: + DoScriptText(SAY_MARK_RIMEFANG_1, me); + DoScriptText(SAY_MARK_RIMEFANG_2, me); + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_MARK_OF_RIMEFANG); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, urand(24000, 26000)); + break; + } + } - CreatureAI* GetAI(Creature* pCreature) const - { - return new boss_rimefangAI(pCreature); - } + DoMeleeAttackIfReady(); + } + }; - struct boss_rimefangAI : public ScriptedAI - { - boss_rimefangAI(Creature *c) : ScriptedAI(c) + CreatureAI* GetAI(Creature* creature) const { - pInstance = c->GetInstanceScript(); + return new boss_tyrannusAI(creature); } +}; - InstanceScript* pInstance; - EventMap events; +class boss_rimefang : public CreatureScript +{ + public: + boss_rimefang() : CreatureScript("boss_rimefang") { } - void Reset() + struct boss_rimefangAI : public ScriptedAI { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.Reset(); - } + boss_rimefangAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) + { + ASSERT(_vehicle); + } - void EnterCombat(Unit* /*who*/) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); - events.ScheduleEvent(EVENT_ICY_BLAST, 35000); - } + void Reset() + { + _events.Reset(); + _events.SetPhase(PHASE_NONE); + _currentWaypoint = 0; + _hoarfrostTargetGUID = 0; + me->SetFlying(true); + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; + void JustReachedHome() + { + _vehicle->InstallAllAccessories(me->GetEntry()); + } - events.Update(diff); + void DoAction(const int32 actionId) + { + if (actionId == ACTION_START_RIMEFANG) + { + _events.SetPhase(PHASE_COMBAT); + me->SetInCombatWithZone(); + _events.ScheduleEvent(EVENT_MOVE_NEXT, 500, 0, PHASE_COMBAT); + _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT); + } + } - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + void SetGUID(const uint64& guid, int32 type) + { + if (type == GUID_HOARFROST) + { + _hoarfrostTargetGUID = guid; + _events.ScheduleEvent(EVENT_HOARFROST, 1000); + } + } - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - switch(eventId) + if (!UpdateVictim() && !(_events.GetPhaseMask() & (1 << PHASE_COMBAT))) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - case EVENT_MARK_OF_RIMEFANG: - DoScriptText(SAY_MARK_RIMEFANG_1, me); - DoScriptText(SAY_MARK_RIMEFANG_2, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); - events.ScheduleEvent(EVENT_HOARFROST, 5000); - return; - case EVENT_HOARFROST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HOARFROST); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); - return; - case EVENT_ICY_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ICY_BLAST); - events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); - return; - case EVENT_ICY_BLAST_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); - events.ScheduleEvent(EVENT_ICY_BLAST, 30000); - return; + switch (eventId) + { + case EVENT_MOVE_NEXT: + if (_currentWaypoint >= 10 || _currentWaypoint == 0) + _currentWaypoint = 1; + me->GetMotionMaster()->MovePoint(0, rimefangPos[_currentWaypoint]); + ++_currentWaypoint; + _events.ScheduleEvent(EVENT_MOVE_NEXT, 2000, 0, PHASE_COMBAT); + break; + case EVENT_ICY_BLAST: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_ICY_BLAST); + _events.ScheduleEvent(EVENT_ICY_BLAST, 15000, 0, PHASE_COMBAT); + break; + case EVENT_HOARFROST: + if (Unit* target = me->GetUnit(*me, _hoarfrostTargetGUID)) + { + DoCast(target, SPELL_HOARFROST); + _hoarfrostTargetGUID = 0; + } + break; + default: + break; + } } } - } - }; + private: + Vehicle* _vehicle; + uint64 _hoarfrostTargetGUID; + EventMap _events; + uint8 _currentWaypoint; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_rimefangAI(creature); + } }; class player_overlord_brandAI : public PlayerAI { public: - player_overlord_brandAI(Player* pPlayer) : PlayerAI(pPlayer) + player_overlord_brandAI(Player* player) : PlayerAI(player) { tyrannus = NULL; } @@ -291,7 +378,8 @@ class player_overlord_brandAI : public PlayerAI void DamageDealt(Unit* /*victim*/, uint32& damage, DamageEffectType /*damageType*/) { - me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); + if (tyrannus->getVictim()) + me->CastCustomSpell(SPELL_OVERLORD_BRAND_DAMAGE, SPELLVALUE_BASE_POINT0, damage, tyrannus->getVictim(), true, NULL, NULL, tyrannus->GetGUID()); } void HealDone(Unit* /*target*/, uint32& addHealth) @@ -299,7 +387,7 @@ class player_overlord_brandAI : public PlayerAI me->CastCustomSpell(SPELL_OVERLORD_BRAND_HEAL, SPELLVALUE_BASE_POINT0, int32(addHealth*5.5f), tyrannus, true, NULL, NULL, tyrannus->GetGUID()); } - void UpdateAI(const uint32 /*diff*/) { } + void UpdateAI(const uint32 diff) { } private: Creature* tyrannus; @@ -352,9 +440,64 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader } }; +class spell_tyrannus_mark_of_rimefang : public SpellScriptLoader +{ + public: + spell_tyrannus_mark_of_rimefang() : SpellScriptLoader("spell_tyrannus_mark_of_rimefang") { } + + class spell_tyrannus_mark_of_rimefang_AuraScript : public AuraScript + { + PrepareAuraScript(spell_tyrannus_mark_of_rimefang_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (!GetCaster() || GetCaster()->GetTypeId() != TYPEID_UNIT) + return; + + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + if (Creature* rimefang = ObjectAccessor::GetCreature(*GetCaster(), instance->GetData64(DATA_RIMEFANG))) + rimefang->AI()->SetGUID(GetTarget()->GetGUID(), GUID_HOARFROST); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_tyrannus_mark_of_rimefang_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_tyrannus_mark_of_rimefang_AuraScript(); + } +}; + +class at_tyrannus_event_starter : public AreaTriggerScript +{ + public: + at_tyrannus_event_starter() : AreaTriggerScript("at_tyrannus_event_starter") { } + + bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) + { + InstanceScript* instance = player->GetInstanceScript(); + if (player->isGameMaster() || !instance) + return false; + + if (instance->GetBossState(DATA_TYRANNUS) != IN_PROGRESS || instance->GetBossState(DATA_TYRANNUS) != DONE) + if (Creature* tyrannus = Unit::GetCreature(*player, instance->GetData64(DATA_TYRANNUS))) + { + tyrannus->AI()->DoAction(ACTION_START_INTRO); + return true; + } + + return false; + } +}; + void AddSC_boss_tyrannus() { new boss_tyrannus(); new boss_rimefang(); new spell_tyrannus_overlord_brand(); + new spell_tyrannus_mark_of_rimefang(); + new at_tyrannus_event_starter(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index 12b7e1c97c1..c26a62d69d5 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -18,223 +18,211 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -#define MAX_ENCOUNTER 3 - -/* Pit of Saron encounters: -0- Forgemaster Garfrost -1- Krick and Ick -2- Scourgelord Tyrannus -*/ - class instance_pit_of_saron : public InstanceMapScript { -public: - instance_pit_of_saron() : InstanceMapScript("instance_pit_of_saron", 658) { } - - InstanceScript* GetInstanceScript(InstanceMap* pMap) const - { - return new instance_pit_of_saron_InstanceMapScript(pMap); - } - - struct instance_pit_of_saron_InstanceMapScript : public InstanceScript - { - instance_pit_of_saron_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {}; - - uint64 uiKrick; - uint64 uiIck; - uint64 uiGarfrost; - uint64 uiTyrannus; - uint64 uiRimefang; - - uint64 uiJainaOrSylvanas1; - uint64 uiJainaOrSylvanas2; - - uint32 uiTeamInInstance; - uint32 uiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - - uiGarfrost = 0; - uiKrick = 0; - uiIck = 0; - uiTyrannus = 0; - } + public: + instance_pit_of_saron() : InstanceMapScript(PoSScriptName, 658) { } - bool IsEncounterInProgress() const + struct instance_pit_of_saron_InstanceScript : public InstanceScript { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* creature) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) + instance_pit_of_saron_InstanceScript(Map* map) : InstanceScript(map) { - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); + SetBossNumber(MAX_ENCOUNTER); + _garfrostGUID = 0; + _krickGUID = 0; + _ickGUID = 0; + _tyrannusGUID = 0; + _rimefangGUID = 0; + _jainaOrSylvanas1GUID = 0; + _jainaOrSylvanas2GUID = 0; + _teamInInstance = 0; } - switch(creature->GetEntry()) + void OnCreatureCreate(Creature* creature, bool /*add*/) { - case CREATURE_KRICK: - uiKrick = creature->GetGUID(); - break; - - case CREATURE_ICK: - uiIck = creature->GetGUID(); - break; - - case CREATURE_GARFROST: - uiGarfrost = creature->GetGUID(); - break; - - case CREATURE_TYRANNUS: - uiTyrannus = creature->GetGUID(); - break; - - case CREATURE_RIMEFANG: - uiRimefang = creature->GetGUID(); - break; - - case NPC_SYLVANAS_PART1: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); - uiJainaOrSylvanas1 = creature->GetGUID(); - break; - case NPC_SYLVANAS_PART2: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); - uiJainaOrSylvanas2 = creature->GetGUID(); - break; - case NPC_KILARA: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_ELANDRA, ALLIANCE); - break; - case NPC_KORALEN: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_KORLAEN, ALLIANCE); - break; - case NPC_CHAMPION_1_HORDE: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_2_HORDE: - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? - if (uiTeamInInstance == ALLIANCE) - creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; + if (!_teamInInstance) + { + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* player = players.begin()->getSource()) + _teamInInstance = player->GetTeam(); + } + + switch (creature->GetEntry()) + { + case NPC_GARFROST: + _garfrostGUID = creature->GetGUID(); + break; + case NPC_KRICK: + _krickGUID = creature->GetGUID(); + break; + case NPC_ICK: + _ickGUID = creature->GetGUID(); + break; + case NPC_TYRANNUS: + _tyrannusGUID = creature->GetGUID(); + break; + case NPC_RIMEFANG: + _rimefangGUID = creature->GetGUID(); + break; + case NPC_TYRANNUS_EVENTS: + _tyrannusEventGUID = creature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); + _jainaOrSylvanas1GUID = creature->GetGUID(); + break; + case NPC_SYLVANAS_PART2: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); + _jainaOrSylvanas2GUID = creature->GetGUID(); + break; + case NPC_KILARA: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ELANDRA, ALLIANCE); + break; + case NPC_KORALEN: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_KORLAEN, ALLIANCE); + break; + case NPC_CHAMPION_1_HORDE: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_2_HORDE: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_HORDE_SLAVE_1: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_1, ALLIANCE); + break; + case NPC_HORDE_SLAVE_2: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_2, ALLIANCE); + break; + case NPC_HORDE_SLAVE_3: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_3, ALLIANCE); + break; + case NPC_HORDE_SLAVE_4: + if (_teamInInstance == ALLIANCE) + creature->UpdateEntry(NPC_ALLIANCE_SLAVE_4, ALLIANCE); + break; + default: + break; + } } - } - uint64 GetData64(uint32 identifier) - { - switch(identifier) + uint32 GetData(uint32 type) { - case DATA_GARFROST: return uiGarfrost; - case DATA_KRICK: return uiKrick; - case DATA_ICK: return uiIck; - case DATA_TYRANNUS: return uiTyrannus; - case DATA_RIMEFANG: return uiRimefang; - - case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; - case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; + switch (type) + { + case DATA_TEAM_IN_INSTANCE: + return _teamInInstance; + default: + break; + } + + return 0; } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) + uint64 GetData64(uint32 type) { - case DATA_GARFROST_EVENT: - uiEncounter[0] = data; - break; - case DATA_TYRANNUS_EVENT: - uiEncounter[1] = data; - break; - case DATA_KRICKANDICK_EVENT: - uiEncounter[2] = data; - break; + switch (type) + { + case DATA_GARFROST: + return _garfrostGUID; + case DATA_KRICK: + return _krickGUID; + case DATA_ICK: + return _ickGUID; + case DATA_TYRANNUS: + return _tyrannusGUID; + case DATA_RIMEFANG: + return _rimefangGUID; + case DATA_TYRANNUS_EVENT: + return _tyrannusEventGUID; + case DATA_JAINA_SYLVANAS_1: + return _jainaOrSylvanas1GUID; + case DATA_JAINA_SYLVANAS_2: + return _jainaOrSylvanas2GUID; + default: + break; + } + + return 0; } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) + std::string GetSaveData() { - case DATA_GARFROST_EVENT: return uiEncounter[0]; - case DATA_TYRANNUS_EVENT: return uiEncounter[1]; - case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; - } + OUT_SAVE_INST_DATA; - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; + std::ostringstream saveStream; + saveStream << "P S " << GetBossSaveData(); - std::ostringstream saveStream; - saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } - void Load(const char* in) - { - if (!in) + void Load(const char* in) { - OUT_LOAD_INST_DATA_FAIL; - return; + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'P' && dataHead2 == 'S') + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; } - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'P' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; + private: + uint64 _garfrostGUID; + uint64 _krickGUID; + uint64 _ickGUID; + uint64 _tyrannusGUID; + uint64 _rimefangGUID; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; + uint64 _tyrannusEventGUID; + uint64 _jainaOrSylvanas1GUID; + uint64 _jainaOrSylvanas2GUID; - } else OUT_LOAD_INST_DATA_FAIL; + uint32 _teamInInstance; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const + { + return new instance_pit_of_saron_InstanceScript(map); } - }; - }; - void AddSC_instance_pit_of_saron() { new instance_pit_of_saron(); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 777f6042830..c5abad82c4b 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -18,1134 +18,267 @@ #include "ScriptPCH.h" #include "pit_of_saron.h" -/***************************************SPELLS*************************************/ -// Ymirjar Wrathbringer -#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) - -//Ymirjar Skycaller -#define SPELL_FROSTBLADE 70291 -#define SPELL_GLACIAL_STRIKE 70292 - -//Ymirjar Flamebearer -#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) -#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) -#define SPELL_TACTICAL_BLINK 69584 - -//Ymirjar Deathbringer -#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) -#define SPELL_SUMMON_UNDEAD 69516 - -//Wrathbone Laborer -#define SPELL_BLINDING_DIRT 70302 -#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) -#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) - -//Wrathbone Coldwraith -#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) -#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) - -//Stonespine Gargoyle -#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) -#define SPELL_STONEFORM 69575 - -// Plagueborn Horror -#define SPELL_BLIGHT_BOMB 69582 -#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) -#define SPELL_TOXIC_WASTE 70274 - -//Iceborn Proto-Drake -#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) - -//Hungering Ghoul -#define SPELL_DEVOUR_FLESH 70393 - -//Fallen Warrior -#define SPELL_ARCING_SLICE 69579 -#define SPELL_DEMORALIZING_SHOUT 61044 -#define SPELL_SHIELD_BLOCK 69580 - -//Deathwhisper Torturer -#define SPELL_BLACK_BRAND 70392 -#define SPELL_CURSE_OF_AGONY 70391 - -//Deathwhisper Shadowcaster -#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) - -//Deathwhisper Necrolyte -#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) -#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) - -//Wrathbone Sorcerer -#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) - -//Geist Ambusher -#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) +enum eSpells +{ + SPELL_FIREBALL = 69583, //Ymirjar Flamebearer + SPELL_HELLFIRE = 69586, + SPELL_TACTICAL_BLINK = 69584, + SPELL_FROST_BREATH = 69527, //Iceborn Proto-Drake + SPELL_BLINDING_DIRT = 70302, //Wrathbone Laborer + SPELL_PUNCTURE_WOUND = 70278, + SPELL_SHOVELLED = 69572, + SPELL_LEAPING_FACE_MAUL = 69504, // Geist Ambusher +}; -/****************************************EVENTS************************************/ enum eEvents { - EVENT_NONE, - - // Ymirjar Wrathbringer - EVENT_BLIGHT, - - // Ymirjar Skycaller - EVENT_FROSTBLADE, - EVENT_GLACIAL_STRIKE, - // Ymirjar Flamebearer - EVENT_FIREBALL, - EVENT_HELLFIRE, - EVENT_TACTICAL_BLINK, - - //Ymirjar Deathbringer - EVENT_EMPOWERED_SHADOW_BOLT, - EVENT_SUMMON_UNDEAD, + EVENT_FIREBALL = 1, + EVENT_TACTICAL_BLINK = 2, //Wrathbone Laborer - EVENT_BLINDING_DIRT, - EVENT_PUNCTURE_WOUND, - EVENT_SHOVELLED, - - //Wrathbone Coldwraith - EVENT_FREEZING_CIRCLE, - EVENT_FROSTBOLT, - - //Stonespine Gargoyle - EVENT_GARGOYLE_STRIKE, - EVENT_STONEFORM, - - //Plagueborn Horror - EVENT_BLIGHT_BOMB, - EVENT_PUSTULANT_FLESH, - EVENT_TOXIC_WASTE, - - //Iceborn Proto-Drake - EVENT_FROST_BREATH, - - //Hungering Ghoul - EVENT_DEVOUR_FLESH, - - //Fallen Warrior - EVENT_ARCING_SLICE, - EVENT_DEMORALIZING_SHOUT, - EVENT_SHIELD_BLOCK, - - //Deathwhisper Torturer - EVENT_BLACK_BRAND, - EVENT_CURSE_OF_AGONY, - - //Deathwhisper Shadowcaster - EVENT_SHADOW_BOLT, - - //Deathwhisper Necrolyte - EVENT_CONVERSION_BEAM, - EVENT_SHADOW_BOLT_2, - - EVENT_SHADOW_BOLT_3, - - //Geist Ambusher - EVENT_LEAPING_FACE_MAUL, + EVENT_BLINDING_DIRT = 3, + EVENT_PUNCTURE_WOUND = 4, + EVENT_SHOVELLED = 5, }; -/****************************************AI****************************************/ - -class mob_ymirjar_wrathbringer : public CreatureScript +class mob_ymirjar_flamebearer : public CreatureScript { -public: - mob_ymirjar_wrathbringer() : CreatureScript("mob_ymirjar_wrathbringer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_wrathbringerAI(pCreature); - } - - struct mob_ymirjar_wrathbringerAI : public ScriptedAI - { - mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT, 7000); - } + public: + mob_ymirjar_flamebearer() : CreatureScript("mob_ymirjar_flamebearer") { } - void UpdateAI(const uint32 diff) + struct mob_ymirjar_flamebearerAI: public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_ymirjar_flamebearerAI(Creature* creature) : ScriptedAI(creature) { - switch(eventId) - { - case EVENT_BLIGHT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLIGHT); - events.RescheduleEvent(EVENT_BLIGHT, 8000); - return; - } } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_ymirjar_skycaller : public CreatureScript -{ -public: - mob_ymirjar_skycaller() : CreatureScript("mob_ymirjar_skycaller") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_skyCallerAI(pCreature); - } - - struct mob_ymirjar_skyCallerAI: public ScriptedAI - { - mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROSTBLADE, 1); - events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void Reset() { - switch(eventId) - { - case EVENT_GLACIAL_STRIKE: - DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); - events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - return; - case EVENT_FROSTBLADE: - DoCast(me, SPELL_FROSTBLADE); - events.CancelEvent(EVENT_FROSTBLADE); - return; - } + _events.Reset(); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_ymirjar_flamebearer : public CreatureScript -{ -public: - mob_ymirjar_flamebearer() : CreatureScript("mob_ymirjar_flamebearer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_flamebearerAI(pCreature); - } - - struct mob_ymirjar_flamebearerAI: public ScriptedAI - { - mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 4000); - events.ScheduleEvent(EVENT_HELLFIRE, 8000); - events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void EnterCombat(Unit* /*who*/) { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - events.RescheduleEvent(EVENT_FIREBALL, 5000); - return; - case EVENT_HELLFIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HELLFIRE); - events.RescheduleEvent(EVENT_HELLFIRE, 10000); - return; - case EVENT_TACTICAL_BLINK: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TACTICAL_BLINK); - events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); - return; - } + _events.ScheduleEvent(EVENT_FIREBALL, 4000); + _events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_ymirjar_deathbringer : public CreatureScript -{ -public: - mob_ymirjar_deathbringer() : CreatureScript("mob_ymirjar_deathbringer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_ymirjar_deathbringerAI(pCreature); - } - - struct mob_ymirjar_deathbringerAI: public ScriptedAI - { - mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; - events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) + while (uint32 eventId = _events.ExecuteEvent()) { - case EVENT_EMPOWERED_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); - events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - return; + switch (eventId) + { + case EVENT_FIREBALL: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_FIREBALL); + _events.RescheduleEvent(EVENT_FIREBALL, 5000); + break; + case EVENT_TACTICAL_BLINK: + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_TACTICAL_BLINK); + DoCast(me, SPELL_HELLFIRE); + _events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); + break; + default: + break; + } } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_wrathbone_laborer : public CreatureScript -{ -public: - mob_wrathbone_laborer() : CreatureScript("mob_wrathbone_laborer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_laborerAI(pCreature); - } - - struct mob_wrathbone_laborerAI: public ScriptedAI - { - mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - void Reset() - { - events.Reset(); - } + DoMeleeAttackIfReady(); + } - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } + private: + EventMap _events; + }; - void UpdateAI(const uint32 diff) + CreatureAI* GetAI(Creature* creature) const { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLINDING_DIRT); - events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); - events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHOVELLED); - events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } - } - - DoMeleeAttackIfReady(); + return new mob_ymirjar_flamebearerAI(creature); } - }; - }; -class mob_wrathbone_coldwraith : public CreatureScript +class mob_iceborn_protodrake : public CreatureScript { -public: - mob_wrathbone_coldwraith() : CreatureScript("mob_wrathbone_coldwraith") { } + public: + mob_iceborn_protodrake() : CreatureScript("mob_iceborn_protodrake") { } - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_coldwraithAI(pCreature); - } - - struct mob_wrathbone_coldwraithAI: public ScriptedAI - { - mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - events.ScheduleEvent(EVENT_FROSTBOLT, 5000); - } - - void UpdateAI(const uint32 diff) + struct mob_iceborn_protodrakeAI: public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_iceborn_protodrakeAI(Creature *creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) { - switch(eventId) - { - case EVENT_FREEZING_CIRCLE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_CIRCLE); - events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.RescheduleEvent(EVENT_FROSTBOLT, 5000); - return; - } + ASSERT(_vehicle); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_stonespine_gargoyle : public CreatureScript -{ -public: - mob_stonespine_gargoyle() : CreatureScript("mob_stonespine_gargoyle") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_stonespine_gargoyleAI(pCreature); - } - - struct mob_stonespine_gargoyleAI: public ScriptedAI - { - mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void Reset() { - switch(eventId) - { - case EVENT_GARGOYLE_STRIKE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_GARGOYLE_STRIKE); - events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); - return; - case EVENT_STONEFORM: - if (HealthBelowPct(10)) - DoCast(me, SPELL_STONEFORM); - return; - } + _frostBreathCooldown = 5000; } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_plagueborn_horror : public CreatureScript -{ -public: - mob_plagueborn_horror() : CreatureScript("mob_plagueborn_horror") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_plagueborn_horrorAI(pCreature); - } - - struct mob_plagueborn_horrorAI: public ScriptedAI - { - mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); - events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void EnterCombat(Unit* /*who*/) { - switch(eventId) - { - case EVENT_BLIGHT_BOMB: - if (HealthBelowPct(15)) - DoCast(me, SPELL_BLIGHT_BOMB); - return; - case EVENT_PUSTULANT_FLESH: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PUSTULANT_FLESH); - events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); - return; - case EVENT_TOXIC_WASTE: - DoCast(me, SPELL_TOXIC_WASTE); - events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); - return; - } + _vehicle->RemoveAllPassengers(); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_iceborn_protodrake : public CreatureScript -{ -public: - mob_iceborn_protodrake() : CreatureScript("mob_iceborn_protodrake") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_iceborn_protodrakeAI(pCreature); - } - - struct mob_iceborn_protodrakeAI: public ScriptedAI - { - mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_BREATH, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - switch(eventId) + if (!UpdateVictim()) + return; + + if (_frostBreathCooldown < diff) { - case EVENT_FROST_BREATH: - DoCast(me->getVictim(), SPELL_FROST_BREATH); - events.RescheduleEvent(EVENT_FROST_BREATH, 10000); - return; + DoCastVictim(SPELL_FROST_BREATH); + _frostBreathCooldown = 10000; } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_hungering_ghoul : public CreatureScript -{ -public: - mob_hungering_ghoul() : CreatureScript("mob_hungering_ghoul") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_hungering_ghoulAI(pCreature); - } - - struct mob_hungering_ghoulAI: public ScriptedAI - { - mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; + else + _frostBreathCooldown -= diff; - void Reset() - { - events.Reset(); - } + DoMeleeAttackIfReady(); + } - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); - } + private: + Vehicle* _vehicle; + uint32 _frostBreathCooldown; + }; - void UpdateAI(const uint32 diff) + CreatureAI* GetAI(Creature* creature) const { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DEVOUR_FLESH: - DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); - events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); - return; - } - } - - DoMeleeAttackIfReady(); + return new mob_iceborn_protodrakeAI(creature); } - }; - }; -class mob_fallen_warrior : public CreatureScript +class mob_wrathbone_laborer : public CreatureScript { -public: - mob_fallen_warrior() : CreatureScript("mob_fallen_warrior") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_fallen_warriorAI(pCreature); - } - - struct mob_fallen_warriorAI: public ScriptedAI - { - mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); - events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); - } + public: + mob_wrathbone_laborer() : CreatureScript("mob_wrathbone_laborer") { } - void UpdateAI(const uint32 diff) + struct mob_wrathbone_laborerAI: public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + mob_wrathbone_laborerAI(Creature* creature) : ScriptedAI(creature) { - switch(eventId) - { - case EVENT_ARCING_SLICE: - DoCast(me->getVictim(), SPELL_ARCING_SLICE); - events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); - return; - case EVENT_DEMORALIZING_SHOUT: - DoCast(me, SPELL_DEMORALIZING_SHOUT); - events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - return; - case EVENT_SHIELD_BLOCK: - DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); - events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); - return; - } } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_deathwhisper_torturer : public CreatureScript -{ -public: - mob_deathwhisper_torturer() : CreatureScript("mob_deathwhisper_torturer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_torturerAI(pCreature); - } - - struct mob_deathwhisper_torturerAI: public ScriptedAI - { - mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); - events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void Reset() { - switch(eventId) - { - case EVENT_BLACK_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_BRAND); - events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); - return; - case EVENT_CURSE_OF_AGONY: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_AGONY); - events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); - return; - } + _events.Reset(); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_deathwhisper_shadowcaster : public CreatureScript -{ -public: - mob_deathwhisper_shadowcaster() : CreatureScript("mob_deathwhisper_shadowcaster") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_shadowcasterAI(pCreature); - } - - struct mob_deathwhisper_shadowcasterAI: public ScriptedAI - { - mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) + void EnterCombat(Unit* /*who*/) { - switch(eventId) - { - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - } + _events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); + _events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + _events.ScheduleEvent(EVENT_SHOVELLED, 5000); } - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_deathwhisper_necrolyte : public CreatureScript -{ -public: - mob_deathwhisper_necrolyte() : CreatureScript("mob_deathwhisper_necrolyte") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_deathwhisper_necrolyteAI(pCreature); - } - - struct mob_deathwhisper_necrolyteAI: public ScriptedAI - { - mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); - events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; - events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) + while (uint32 eventId = _events.ExecuteEvent()) { - case EVENT_CONVERSION_BEAM: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CONVERSION_BEAM); - events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); - return; - case EVENT_SHADOW_BOLT_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_2); - events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); - return; + switch(eventId) + { + case EVENT_BLINDING_DIRT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 10.0f, true)) + DoCast(target, SPELL_BLINDING_DIRT); + _events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); + return; + case EVENT_PUNCTURE_WOUND: + DoCastVictim(SPELL_PUNCTURE_WOUND); + _events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + return; + case EVENT_SHOVELLED: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, -5.0f)) + DoCast(target, SPELL_SHOVELLED); + _events.RescheduleEvent(EVENT_SHOVELLED, 7000); + return; + } } - } - - DoMeleeAttackIfReady(); - } - }; - -}; - -class mob_wrathbone_sorcerer : public CreatureScript -{ -public: - mob_wrathbone_sorcerer() : CreatureScript("mob_wrathbone_sorcerer") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_wrathbone_sorcererAI(pCreature); - } - - struct mob_wrathbone_sorcererAI: public ScriptedAI - { - mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) - { - } - EventMap events; - - void Reset() - { - events.Reset(); - } + DoMeleeAttackIfReady(); + } - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); - } + private: + EventMap _events; + }; - void UpdateAI(const uint32 diff) + CreatureAI* GetAI(Creature* creature) const { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT_3: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_3); - events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); - return; - } - } - - DoMeleeAttackIfReady(); + return new mob_wrathbone_laborerAI(creature); } - }; - }; class mob_geist_ambusher : public CreatureScript { -public: - mob_geist_ambusher() : CreatureScript("mob_geist_ambusher") { } - - CreatureAI* GetAI(Creature* pCreature) const - { - return new mob_geist_ambusherAI(pCreature); - } - - struct mob_geist_ambusherAI: public ScriptedAI - { - mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } + public: + mob_geist_ambusher() : CreatureScript("mob_geist_ambusher") { } - void EnterCombat(Unit* /*who*/) + struct mob_geist_ambusherAI: public ScriptedAI { - //Only here so when I figure out how to make it cast on an NPC i can do that. - events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); - } + mob_geist_ambusherAI(Creature* creature) : ScriptedAI(creature) + { + } - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; + void Reset() + { + _leapingFaceMaulCooldown = 9000; + } - events.Update(diff); + void MoveInLineOfSight(Unit* who) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; - if (me->HasUnitState(UNIT_STAT_CASTING)) - return; + if (me->IsWithinDistInMap(who, 30.0f)) + DoCast(who, SPELL_LEAPING_FACE_MAUL); + } - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(const uint32 diff) { - switch(eventId) + if (!UpdateVictim()) + return; + + if (_leapingFaceMaulCooldown < diff) { - //Should only be used on NPCs - case EVENT_LEAPING_FACE_MAUL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); - events.CancelEvent(EVENT_LEAPING_FACE_MAUL); - return; + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true)) + DoCast(target, SPELL_LEAPING_FACE_MAUL); + _leapingFaceMaulCooldown = urand(9000, 14000); } + else + _leapingFaceMaulCooldown -= diff; + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + private: + uint32 _leapingFaceMaulCooldown; + }; + CreatureAI* GetAI(Creature* creature) const + { + return new mob_geist_ambusherAI(creature); + } }; void AddSC_pit_of_saron() { - new mob_ymirjar_wrathbringer(); - new mob_ymirjar_skycaller(); new mob_ymirjar_flamebearer(); - new mob_ymirjar_deathbringer(); new mob_wrathbone_laborer(); - new mob_wrathbone_coldwraith(); - new mob_stonespine_gargoyle(); - new mob_plagueborn_horror(); new mob_iceborn_protodrake(); - new mob_hungering_ghoul(); - new mob_fallen_warrior(); - new mob_deathwhisper_torturer(); - new mob_deathwhisper_shadowcaster(); - new mob_deathwhisper_necrolyte(); - new mob_wrathbone_sorcerer(); new mob_geist_ambusher(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h index 9368d479cd1..d71972d64fa 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -18,34 +18,32 @@ #ifndef DEF_PIT_OF_SARON_H #define DEF_PIT_OF_SARON_H -enum Data -{ - DATA_GARFROST_EVENT, - DATA_KRICKANDICK_EVENT, - DATA_TYRANNUS_EVENT, - DATA_TEAM_IN_INSTANCE, -}; +#define PoSScriptName "instance_pit_of_saron" +#define MAX_ENCOUNTER 3 -enum Data64 +enum DataTypes { - DATA_GARFROST, - DATA_KRICK, - DATA_ICK, - DATA_TYRANNUS, - DATA_RIMEFANG, + DATA_GARFROST = 0, + DATA_KRICK = 1, + DATA_ICK = 2, + DATA_TYRANNUS = 3, + DATA_RIMEFANG = 4, - DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. - DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_1 = 5, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_2 = 6, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. + DATA_TYRANNUS_EVENT = 7, + DATA_TEAM_IN_INSTANCE = 8, }; -enum Creatures +enum CreatureIds { - CREATURE_GARFROST = 36494, - CREATURE_KRICK = 36477, - CREATURE_ICK = 36476, - CREATURE_TYRANNUS = 36658, - CREATURE_RIMEFANG = 36661, + NPC_GARFROST = 36494, + NPC_KRICK = 36477, + NPC_ICK = 36476, + NPC_TYRANNUS = 36658, + NPC_RIMEFANG = 36661, + NPC_TYRANNUS_EVENTS = 36794, NPC_SYLVANAS_PART1 = 36990, NPC_SYLVANAS_PART2 = 38189, NPC_JAINA_PART1 = 36993, @@ -59,6 +57,25 @@ enum Creatures NPC_CHAMPION_3_HORDE = 37588, NPC_CHAMPION_1_ALLIANCE = 37496, NPC_CHAMPION_2_ALLIANCE = 37497, + + NPC_HORDE_SLAVE_1 = 36770, + NPC_HORDE_SLAVE_2 = 36771, + NPC_HORDE_SLAVE_3 = 36772, + NPC_HORDE_SLAVE_4 = 36773, + NPC_ALLIANCE_SLAVE_1 = 36764, + NPC_ALLIANCE_SLAVE_2 = 36765, + NPC_ALLIANCE_SLAVE_3 = 36766, + NPC_ALLIANCE_SLAVE_4 = 36767, + + NPC_FORGEMASTER_STALKER = 36495, + NPC_EXPLODING_ORB = 36610, + NPC_YMIRJAR_DEATHBRINGER = 36892, + NPC_ICY_BLAST = 36731 +}; + +enum GameObjectIds +{ + GO_SARONITE_ROCK = 196485, }; #endif |