diff options
author | offl <11556157+offl@users.noreply.github.com> | 2025-07-22 22:26:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-22 21:26:15 +0200 |
commit | 4dece3fe4efb06661083bfd565976ed61e4ed7b3 (patch) | |
tree | 9ad5658f13ce0e35c5b8f946eabe3802f8673e49 /src | |
parent | cfa9fb701a7d5ec14750f55d1fa30247e8c0def9 (diff) |
Scripts/Arcatraz: Rewrite Mellichar's event (#31081)
Diffstat (limited to 'src')
5 files changed, 623 insertions, 457 deletions
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index f5bd8748a44..5dd878fdddb 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3519,6 +3519,15 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->_GetEffect(EFFECT_0).RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_150_YARDS); // 150yd }); + // Radius in DBC is not enough + ApplySpellFix({ + 36854, // Channel + 36856 // Channel + }, [](SpellInfo* spellInfo) + { + spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(5); // 40yd + }); + // Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data // To prevent aura staying on target after talent unlearned ApplySpellFix({ 48420 }, [](SpellInfo* spellInfo) diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp index 765d655a6c9..4ec8b22c8a5 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -15,485 +15,669 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Arcatraz -SD%Complete: 60 -SDComment: Warden Mellichar, event controller for Skyriss event. Millhouse Manastorm. @todo make better combatAI for Millhouse. -SDCategory: Tempest Keep, The Arcatraz -EndScriptData */ - -/* ContentData -npc_millhouse_manastorm -npc_warden_mellichar -EndContentData */ +/* + * The way Mellichar's event is reset requires additional research + */ #include "ScriptMgr.h" #include "arcatraz.h" #include "InstanceScript.h" #include "MotionMaster.h" #include "ScriptedCreature.h" +#include "SpellInfo.h" -/*##### -# npc_millhouse_manastorm -#####*/ - -enum MillhouseSays +enum MillhouseTexts { SAY_INTRO_1 = 0, SAY_INTRO_2 = 1, - SAY_WATER = 2, - SAY_BUFFS = 3, - SAY_DRINK = 4, - SAY_READY = 5, - SAY_KILL = 6, - SAY_PYRO = 7, - SAY_ICEBLOCK = 8, - SAY_LOWHP = 9, - SAY_DEATH = 10, - SAY_COMPLETE = 11, + SAY_INTRO_3 = 2, + SAY_INTRO_4 = 3, + SAY_WATER = 4, + SAY_BUFFS = 5, + SAY_DRINK = 6, + SAY_READY = 7, + SAY_SLAY = 8, + SAY_PYRO = 9, + SAY_ICEBLOCK = 10, + SAY_LOWHP = 11, + SAY_DEATH = 12, + SAY_COMPLETE = 13 }; enum MillhouseSpells { + SPELL_SIMPLE_TELEPORT = 12980, SPELL_CONJURE_WATER = 36879, SPELL_ARCANE_INTELLECT = 36880, SPELL_ICE_ARMOR = 36881, - SPELL_ARCANE_MISSILES = 33833, - SPELL_CONE_OF_COLD = 12611, - SPELL_FIRE_BLAST = 13341, + SPELL_DRINK = 30024, + SPELL_FIREBALL = 14034, SPELL_FROSTBOLT = 15497, + SPELL_ARCANE_MISSILES = 33832, + SPELL_CONE_OF_COLD = 12611, + SPELL_FIRE_BLAST = 13341, SPELL_PYROBLAST = 33975, + SPELL_ICE_BLOCK = 36911 +}; + +enum MillhouseEvents +{ + EVENT_INTRO_1 = 1, + EVENT_INTRO_2, + EVENT_INTRO_3, + EVENT_INTRO_4, + EVENT_INTRO_5, + EVENT_INTRO_6, + EVENT_INTRO_7, + EVENT_INTRO_8, + EVENT_INTRO_9, + EVENT_INTRO_10, + EVENT_INTRO_11, + EVENT_INTRO_12, + + EVENT_MAIN_SPELL, + EVENT_ARCANE_MISSILES, + EVENT_CONE_OF_COLD, + EVENT_FIRE_BLAST, + EVENT_PYROBLAST, + EVENT_ICE_BLOCK, + EVENT_LOW_HEALTH }; +enum MillhouseMisc +{ + POINT_CENTER = 1 +}; + +Position const CenterPos = { 445.88043f, -158.70554f, 43.068977f, 0.0f }; + +// 20977 - Millhouse Manastorm struct npc_millhouse_manastorm : public ScriptedAI { - npc_millhouse_manastorm(Creature* creature) : ScriptedAI(creature), Init(false) + npc_millhouse_manastorm(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()), _lowHealth(false), _hasIceBlock(false) { } + + void JustAppeared() override { - Initialize(); - instance = creature->GetInstanceScript(); + me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP); + _events.ScheduleEvent(EVENT_INTRO_1, 0s); } - void Initialize() + void Reset() override { - EventProgress_Timer = 2000; - LowHp = false; - Phase = 1; + _events.Reset(); + _lowHealth = false; + _hasIceBlock = false; - Pyroblast_Timer = 1000; - Fireball_Timer = 2500; + if (_instance->GetBossState(DATA_HARBINGER_SKYRISS) == DONE) + { + Talk(SAY_COMPLETE); + me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP); + } } - InstanceScript* instance; - - uint32 EventProgress_Timer; - uint32 Phase; - bool Init; - bool LowHp; + void JustEngagedWith(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_MAIN_SPELL, 0s); + _events.ScheduleEvent(EVENT_ARCANE_MISSILES, 10s, 20s); + _events.ScheduleEvent(EVENT_CONE_OF_COLD, 15s, 25s); + _events.ScheduleEvent(EVENT_FIRE_BLAST, 20s, 30s); + _events.ScheduleEvent(EVENT_PYROBLAST, 30s, 45s); + } - uint32 Pyroblast_Timer; - uint32 Fireball_Timer; + void AttackStart(Unit* who) override + { + ScriptedAI::AttackStartCaster(who, 30.0f); + } - void Reset() override + void MovementInform(uint32 type, uint32 pointId) override { - Initialize(); + if (type != POINT_MOTION_TYPE) + return; - if (instance->GetData(DATA_WARDEN_2) == DONE) + if (pointId == POINT_CENTER) + _events.ScheduleEvent(EVENT_INTRO_12, 0s); + } + + void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override + { + if (!_lowHealth && me->HealthBelowPctDamaged(20, damage)) { - Init = true; - me->SetImmuneToNPC(false); + _lowHealth = true; + _events.ScheduleEvent(EVENT_LOW_HEALTH, 0s); } + // Guessed, how this spell should be used? + if (!_hasIceBlock && me->HealthBelowPctDamaged(10, damage)) + { + _hasIceBlock = true; + _events.ScheduleEvent(EVENT_ICE_BLOCK, 0s); + } + } - if (instance->GetBossState(DATA_HARBINGER_SKYRISS) == DONE) - Talk(SAY_COMPLETE); + void OnSpellStart(SpellInfo const* spell) override + { + if (spell->Id == SPELL_PYROBLAST) + Talk(SAY_PYRO); } - void AttackStart(Unit* who) override + void OnSpellCast(SpellInfo const* spell) override { - if (me->Attack(who, true)) - { - AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - me->GetMotionMaster()->MoveChase(who, 25.0f); - } + if (spell->Id == SPELL_ICE_BLOCK) + Talk(SAY_ICEBLOCK); } - void KilledUnit(Unit* who) override + void KilledUnit(Unit* /*who*/) override { - if (who->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_KILL); + Talk(SAY_SLAY); } void JustDied(Unit* /*killer*/) override { Talk(SAY_DEATH); - - /*for questId 10886 (heroic mode only) - if (instance->GetBossState(DATA_HARBINGER_SKYRISS) != DONE) - ->FailQuest();*/ } void UpdateAI(uint32 diff) override { - if (!Init) + if (!UpdateVictim()) { - if (EventProgress_Timer <= diff) - { - if (Phase < 8) - { - switch (Phase) - { - case 1: - Talk(SAY_INTRO_1); - EventProgress_Timer = 18000; - break; - case 2: - Talk(SAY_INTRO_2); - EventProgress_Timer = 18000; - break; - case 3: - Talk(SAY_WATER); - DoCast(me, SPELL_CONJURE_WATER); - EventProgress_Timer = 7000; - break; - case 4: - Talk(SAY_BUFFS); - DoCast(me, SPELL_ICE_ARMOR); - EventProgress_Timer = 7000; - break; - case 5: - Talk(SAY_DRINK); - DoCast(me, SPELL_ARCANE_INTELLECT); - EventProgress_Timer = 7000; - break; - case 6: - Talk(SAY_READY); - EventProgress_Timer = 6000; - break; - case 7: - instance->SetData(DATA_WARDEN_2, DONE); - Init = true; - me->SetImmuneToNPC(false); - break; - } - ++Phase; - } - } - else - EventProgress_Timer -= diff; + UpdateIntroEvents(diff); + return; } - if (!UpdateVictim()) + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) return; - if (!LowHp && HealthBelowPct(20)) - { - Talk(SAY_LOWHP); - LowHp = true; - } - if (Pyroblast_Timer <= diff) + while (uint32 eventId = _events.ExecuteEvent()) { - if (me->IsNonMeleeSpellCast(false)) + switch (eventId) + { + case EVENT_MAIN_SPELL: + DoCastVictim(RAND(SPELL_FIREBALL, SPELL_FROSTBOLT)); + _events.Repeat(3s); + break; + case EVENT_ARCANE_MISSILES: + DoCastVictim(SPELL_ARCANE_MISSILES); + _events.Repeat(20s, 30s); + break; + case EVENT_CONE_OF_COLD: + DoCastSelf(SPELL_CONE_OF_COLD); + _events.Repeat(20s, 30s); + break; + case EVENT_FIRE_BLAST: + DoCastVictim(SPELL_FIRE_BLAST); + _events.Repeat(25s, 40s); + break; + case EVENT_PYROBLAST: + DoCastVictim(SPELL_PYROBLAST); + _events.Repeat(40s, 60s); + break; + case EVENT_ICE_BLOCK: + DoCastSelf(SPELL_ICE_BLOCK); + break; + case EVENT_LOW_HEALTH: + Talk(SAY_LOWHP); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) return; + } - Talk(SAY_PYRO); + DoMeleeAttackIfReady(); + } - DoCastVictim(SPELL_PYROBLAST); - Pyroblast_Timer = 40000; - } - else - Pyroblast_Timer -=diff; + void UpdateIntroEvents(uint32 diff) + { + _events.Update(diff); - if (Fireball_Timer <= diff) + while (uint32 eventId = _events.ExecuteEvent()) { - DoCastVictim(SPELL_FIREBALL); - Fireball_Timer = 4000; + switch (eventId) + { + case EVENT_INTRO_1: + DoCastSelf(SPELL_SIMPLE_TELEPORT); + _events.ScheduleEvent(EVENT_INTRO_2, 2s); + break; + case EVENT_INTRO_2: + Talk(SAY_INTRO_1); + _events.ScheduleEvent(EVENT_INTRO_3, 4s + 500ms); + break; + case EVENT_INTRO_3: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + _events.ScheduleEvent(EVENT_INTRO_4, 14s); + break; + case EVENT_INTRO_4: + if (Creature* mellichar = _instance->GetCreature(DATA_MELLICHAR)) + me->SetFacingToObject(mellichar); + Talk(SAY_INTRO_2); + _events.ScheduleEvent(EVENT_INTRO_5, 9s); + break; + case EVENT_INTRO_5: + Talk(SAY_INTRO_3); + me->SetFacingTo(0.03490658476948738f); + _events.ScheduleEvent(EVENT_INTRO_6, 8s); + break; + case EVENT_INTRO_6: + if (Creature* mellichar = _instance->GetCreature(DATA_MELLICHAR)) + me->SetFacingToObject(mellichar); + Talk(SAY_INTRO_4); + _events.ScheduleEvent(EVENT_INTRO_7, 5s); + break; + case EVENT_INTRO_7: + Talk(SAY_WATER); + DoCastSelf(SPELL_CONJURE_WATER); + _events.ScheduleEvent(EVENT_INTRO_8, 7s); + break; + case EVENT_INTRO_8: + Talk(SAY_BUFFS); + DoCastSelf(SPELL_ARCANE_INTELLECT); + _events.ScheduleEvent(EVENT_INTRO_9, 3s); + break; + case EVENT_INTRO_9: + DoCastSelf(SPELL_ICE_ARMOR); + _events.ScheduleEvent(EVENT_INTRO_10, 6s); + break; + case EVENT_INTRO_10: + Talk(SAY_DRINK); + DoCastSelf(SPELL_DRINK); + _events.ScheduleEvent(EVENT_INTRO_11, 6s); + break; + case EVENT_INTRO_11: + Talk(SAY_READY); + // Clear stand state from Drink spell manually, otherwise it will be not cleared + me->SetStandState(UNIT_STAND_STATE_STAND); + me->GetMotionMaster()->MovePoint(POINT_CENTER, CenterPos); + break; + case EVENT_INTRO_12: + if (Creature* mellichar = _instance->GetCreature(DATA_MELLICHAR)) + me->SetFacingToObject(mellichar); + me->SetImmuneToAll(false); + me->SetHomePosition(me->GetPosition()); + break; + default: + break; + } } - else - Fireball_Timer -=diff; - - DoMeleeAttackIfReady(); } -}; -/*##### -# npc_warden_mellichar -#####*/ -enum WardenSays -{ - YELL_INTRO1 = 0, - YELL_INTRO2 = 1, - YELL_RELEASE1 = 2, - YELL_RELEASE2A = 3, - YELL_RELEASE2B = 4, - YELL_RELEASE3 = 5, - YELL_RELEASE4 = 6, - YELL_WELCOME = 7, +private: + EventMap _events; + InstanceScript* _instance; + bool _lowHealth; + bool _hasIceBlock; }; -enum WardenUnits +enum WardenTexts { - //phase 2(acid mobs) - ENTRY_TRICKSTER = 20905, - ENTRY_PH_HUNTER = 20906, - //phase 3 - ENTRY_MILLHOUSE = 20977, - //phase 4(acid mobs) - ENTRY_AKKIRIS = 20908, - ENTRY_SULFURON = 20909, - //phase 5(acid mobs) - ENTRY_TW_DRAK = 20910, - ENTRY_BL_DRAK = 20911, - //phase 6 - ENTRY_SKYRISS = 20912, + SAY_RELEASE_1 = 0, + SAY_RELEASE_2 = 1, + SAY_RELEASE_3 = 2, + SAY_RELEASE_4 = 3, + SAY_RELEASE_5 = 4, + SAY_RELEASE_6 = 5, + SAY_RELEASE_7 = 6, + SAY_RELEASE_8 = 7 }; enum WardenSpells { - //TARGET_SCRIPT - SPELL_TARGET_ALPHA = 36856, - SPELL_TARGET_BETA = 36854, - SPELL_TARGET_DELTA = 36857, - SPELL_TARGET_GAMMA = 36858, - SPELL_TARGET_OMEGA = 36852, - SPELL_BUBBLE_VISUAL = 36849, + SPELL_SEAL_SPHERE = 36849, + SPELL_TARGET_OMEGA = 36852, + SPELL_TARGET_ALPHA = 36854, + SPELL_TARGET_BETA = 36856, + SPELL_TARGET_DELTA = 36857, + SPELL_TARGET_GAMMA = 36858, + SPELL_QUIET_SUICIDE = 3617 }; -struct npc_warden_mellichar : public ScriptedAI +enum WardenEvents { - npc_warden_mellichar(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - IsRunning = false; - CanSpawn = false; - - EventProgress_Timer = 22000; - Phase = 1; - } + EVENT_MAIN_CHANNEL = 1, + + EVENT_RELEASE_1_1, + EVENT_RELEASE_1_2, + EVENT_RELEASE_1_3, + EVENT_RELEASE_1_4, + EVENT_RELEASE_1_5, + EVENT_RELEASE_1_6, + EVENT_RELEASE_1_7, + EVENT_RELEASE_1_8, + EVENT_RELEASE_1_9, + + EVENT_RELEASE_2_1, + EVENT_RELEASE_2_2, + EVENT_RELEASE_2_3, + EVENT_RELEASE_2_4, + EVENT_RELEASE_2_5, + EVENT_RELEASE_2_6, + + EVENT_RELEASE_3_1, + EVENT_RELEASE_3_2, + EVENT_RELEASE_3_3, + EVENT_RELEASE_3_4, + EVENT_RELEASE_3_5, + EVENT_RELEASE_3_6, + EVENT_RELEASE_3_7, + + EVENT_RELEASE_4_1, + EVENT_RELEASE_4_2, + EVENT_RELEASE_4_3, + EVENT_RELEASE_4_4, + EVENT_RELEASE_4_5, + EVENT_RELEASE_4_6, + + EVENT_RELEASE_5_1, + EVENT_RELEASE_5_2, + EVENT_RELEASE_5_3, + EVENT_RELEASE_5_4, + EVENT_RELEASE_5_5 +}; - InstanceScript* instance; +enum WardenCreatures +{ + // Prisoner 1 + NPC_TRICKSTER = 20905, + NPC_PH_HUNTER = 20906, + // Prisoner 2 + NPC_MILLHOUSE_M = 20977, + // Prisoner 3 + NPC_AKKIRIS = 20908, + NPC_SULFURON = 20909, + // Prisoner 4 + NPC_TW_DRAK = 20910, + NPC_BL_DRAK = 20911, + // Prisoner 5 + NPC_SKYRISS = 20912 +}; - bool IsRunning; - bool CanSpawn; +Position const PrisonerSpawnPos[5] = +{ + { 472.231f, -150.860f, 42.6573f, 3.106690f }, + { 417.242f, -149.795f, 42.6548f, 0.191986f }, + { 420.851f, -174.337f, 42.6655f, 0.122173f }, + { 470.364f, -174.656f, 42.6753f, 3.595380f }, + { 446.086f, -182.506f, 44.0852f, 1.570800f } +}; - uint32 EventProgress_Timer; - uint32 Phase; +// 20904 - Warden Mellichar +struct npc_warden_mellichar : public ScriptedAI +{ + npc_warden_mellichar(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()), _summons(me), _inProgress(false) { } void Reset() override { - Initialize(); - - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_TARGET_OMEGA); - - instance->SetBossState(DATA_HARBINGER_SKYRISS, NOT_STARTED); + _events.Reset(); + _summons.DespawnAll(); + _events.ScheduleEvent(EVENT_MAIN_CHANNEL, 0s); + me->SetReactState(REACT_PASSIVE); + + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_STASIS_POD_ALPHA)); + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_STASIS_POD_BETA)); + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_STASIS_POD_DELTA)); + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_STASIS_POD_GAMMA)); + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_STASIS_POD_OMEGA)); + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_WARDENS_SHIELD)); + + if (_instance->GetBossState(DATA_HARBINGER_SKYRISS) == FAIL) + { + _instance->SetBossState(DATA_HARBINGER_SKYRISS, NOT_STARTED); + me->DespawnOrUnsummon(0s, 1min); + } } - void AttackStart(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* who) override { - if (IsRunning) + if (_inProgress) return; - if (!me->GetVictim() && me->CanCreatureAttack(who)) - { - if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - if (who->GetTypeId() != TYPEID_PLAYER) - return; + if (who->GetTypeId() != TYPEID_PLAYER || !who->IsWithinDist(me, INTERACTION_DISTANCE)) + return; - float attackRadius = me->GetAttackDistance(who)/10; - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - JustEngagedWith(who); - } + JustEngagedWith(who); } void JustEngagedWith(Unit* /*who*/) override { - Talk(YELL_INTRO1); - DoCast(me, SPELL_BUBBLE_VISUAL); + if (_inProgress) + return; - instance->SetBossState(DATA_HARBINGER_SKYRISS, IN_PROGRESS); - instance->HandleGameObject(instance->GetGuidData(DATA_WARDENS_SHIELD), false); - IsRunning = true; + _inProgress = true; + _events.ScheduleEvent(EVENT_RELEASE_1_1, 1s); + _instance->SetBossState(DATA_HARBINGER_SKYRISS, IN_PROGRESS); } - void JustSummoned(Creature* summon) override + void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override { - DoZoneInCombat(summon); - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true)) - summon->AI()->AttackStart(target); + if (spellInfo->Id == SPELL_SEAL_SPHERE) + _instance->HandleGameObject(ObjectGuid::Empty, false, _instance->GetGameObject(DATA_WARDENS_SHIELD)); } - bool CanProgress() + void DamageTaken(Unit* who, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override { - if (Phase == 7 && instance->GetData(DATA_WARDEN_4) == DONE) - return true; - if (Phase == 6 && instance->GetData(DATA_WARDEN_3) == DONE) - return true; - if (Phase == 5 && instance->GetData(DATA_WARDEN_2) == DONE) - return true; - if (Phase == 4) - return true; - if (Phase == 3 && instance->GetData(DATA_WARDEN_1) == DONE) - return true; - if (Phase == 2 && instance->GetBossState(DATA_HARBINGER_SKYRISS) == IN_PROGRESS) - return true; - if (Phase == 1 && instance->GetBossState(DATA_HARBINGER_SKYRISS) == IN_PROGRESS) - return true; - - return false; + // Creature is unkillable by default. But allow to kill self with Quiet Suicide spell + if (damage >= me->GetHealth() && who != me) + damage = me->GetHealth() -1; } - void DoPrepareForPhase() + void DoAction(int32 action) override { - me->InterruptNonMeleeSpells(true); - me->RemoveAurasByType(SPELL_AURA_DUMMY); + if (action == ACTION_RESET_PRISON) + Reset(); + } - switch (Phase) + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + DoZoneInCombat(summon); + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + // Not entirely correct. Next phase is started when prisoner is about to die, not when he's dead + switch (summon->GetEntry()) { - case 2: - DoCast(me, SPELL_TARGET_ALPHA); - instance->SetData(DATA_WARDEN_1, IN_PROGRESS); - instance->HandleGameObject(instance->GetGuidData(DATA_WARDENS_SHIELD), false); - break; - case 3: - DoCast(me, SPELL_TARGET_BETA); - instance->SetData(DATA_WARDEN_2, IN_PROGRESS); + case NPC_TRICKSTER: + case NPC_PH_HUNTER: + _events.ScheduleEvent(EVENT_RELEASE_2_1, 0s); break; - case 5: - DoCast(me, SPELL_TARGET_DELTA); - instance->SetData(DATA_WARDEN_3, IN_PROGRESS); + case NPC_AKKIRIS: + case NPC_SULFURON: + _events.ScheduleEvent(EVENT_RELEASE_4_1, 0s); break; - case 6: - DoCast(me, SPELL_TARGET_GAMMA); - instance->SetData(DATA_WARDEN_4, IN_PROGRESS); + case NPC_TW_DRAK: + case NPC_BL_DRAK: + _events.ScheduleEvent(EVENT_RELEASE_5_1, 0s); break; - case 7: - instance->SetData(DATA_WARDEN_5, IN_PROGRESS); + default: break; } - CanSpawn = true; } void UpdateAI(uint32 diff) override { - if (!IsRunning) - return; + _events.Update(diff); - if (EventProgress_Timer <= diff) + while (uint32 eventId = _events.ExecuteEvent()) { - if (instance->GetBossState(DATA_HARBINGER_SKYRISS) == FAIL) + switch (eventId) { - Reset(); - return; - } + case EVENT_MAIN_CHANNEL: + DoCastSelf(SPELL_TARGET_OMEGA); + _events.Repeat(12s); + break; - if (CanSpawn) - { - //continue beam omega pod, unless we are about to summon skyriss - if (Phase != 7) - DoCast(me, SPELL_TARGET_OMEGA); - - switch (Phase) - { - case 2: - switch (urand(0, 1)) - { - case 0: - me->SummonCreature(ENTRY_TRICKSTER, 472.231f, -150.86f, 42.6573f, 3.10669f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - case 1: - me->SummonCreature(ENTRY_PH_HUNTER, 472.231f, -150.86f, 42.6573f, 3.10669f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - } - break; - case 3: - me->SummonCreature(ENTRY_MILLHOUSE, 417.242f, -149.795f, 42.6548f, 0.191986f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // static pos - break; - case 4: - Talk(YELL_RELEASE2B); - break; - case 5: - switch (urand(0, 1)) - { - case 0: - me->SummonCreature(ENTRY_AKKIRIS, 420.851f, -174.337f, 42.6655f, 0.122173f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - case 1: - me->SummonCreature(ENTRY_SULFURON, 420.851f, -174.337f, 42.6655f, 0.122173f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - } - break; - case 6: - switch (urand(0, 1)) - { - case 0: - me->SummonCreature(ENTRY_TW_DRAK, 470.364f, -174.656f, 42.6753f, 3.59538f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - case 1: - me->SummonCreature(ENTRY_BL_DRAK, 470.364f, -174.656f, 42.6753f, 3.59538f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // random pos - break; - } - break; - case 7: - me->SummonCreature(ENTRY_SKYRISS, 446.086f, -182.506f, 44.0852f, 1.5708f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10min); // static pos - Talk(YELL_WELCOME); - break; - } - CanSpawn = false; - ++Phase; - } - if (CanProgress()) - { - switch (Phase) - { - case 1: - Talk(YELL_INTRO2); - EventProgress_Timer = 10000; - ++Phase; - break; - case 2: - Talk(YELL_RELEASE1); - DoPrepareForPhase(); - EventProgress_Timer = 7000; - break; - case 3: - Talk(YELL_RELEASE2A); - DoPrepareForPhase(); - EventProgress_Timer = 10000; - break; - case 4: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 5: - Talk(YELL_RELEASE3); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 6: - Talk(YELL_RELEASE4); - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - case 7: - DoPrepareForPhase(); - EventProgress_Timer = 15000; - break; - } + case EVENT_RELEASE_1_1: + me->InterruptNonMeleeSpells(true); + me->RemoveAurasDueToSpell(SPELL_TARGET_OMEGA); + me->SetImmuneToPC(true); + _events.CancelEvent(EVENT_MAIN_CHANNEL); + _events.ScheduleEvent(EVENT_RELEASE_1_2, 2s); + break; + case EVENT_RELEASE_1_2: + me->SetFacingTo(1.605702877044677734f); + // Apparently casting this spell makes him reset orientation to default + DoCastSelf(SPELL_SEAL_SPHERE); + Talk(SAY_RELEASE_1); + _events.ScheduleEvent(EVENT_RELEASE_1_3, 23s); + break; + case EVENT_RELEASE_1_3: + Talk(SAY_RELEASE_2); + _events.ScheduleEvent(EVENT_RELEASE_1_4, 2s); + break; + case EVENT_RELEASE_1_4: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + _events.ScheduleEvent(EVENT_RELEASE_1_5, 2s); + break; + case EVENT_RELEASE_1_5: + DoCastSelf(SPELL_TARGET_ALPHA); + _events.ScheduleEvent(EVENT_RELEASE_1_6, 4s); + break; + case EVENT_RELEASE_1_6: + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_STASIS_POD_ALPHA)); + _events.ScheduleEvent(EVENT_RELEASE_1_7, 2s); + break; + case EVENT_RELEASE_1_7: + me->SetFacingTo(4.747295379638671875f); + _events.ScheduleEvent(EVENT_RELEASE_1_8, 2s); + break; + case EVENT_RELEASE_1_8: + _events.ScheduleEvent(EVENT_MAIN_CHANNEL, 0s); + _events.ScheduleEvent(EVENT_RELEASE_1_9, 6s); + break; + case EVENT_RELEASE_1_9: + me->SummonCreature(RAND(NPC_TRICKSTER, NPC_PH_HUNTER), PrisonerSpawnPos[0], TEMPSUMMON_MANUAL_DESPAWN); + break; + + case EVENT_RELEASE_2_1: + me->InterruptNonMeleeSpells(true); + me->RemoveAurasDueToSpell(SPELL_TARGET_OMEGA); + me->SetFacingTo(1.675516128540039062f); + Talk(SAY_RELEASE_3); + _events.CancelEvent(EVENT_MAIN_CHANNEL); + _events.ScheduleEvent(EVENT_RELEASE_2_2, 5s); + break; + case EVENT_RELEASE_2_2: + DoCastSelf(SPELL_TARGET_BETA); + _events.ScheduleEvent(EVENT_RELEASE_2_3, 3s); + break; + case EVENT_RELEASE_2_3: + me->SetFacingTo(4.747295379638671875f); + Talk(SAY_RELEASE_4); + _events.ScheduleEvent(EVENT_RELEASE_2_4, 1s); + break; + case EVENT_RELEASE_2_4: + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_STASIS_POD_BETA)); + _events.ScheduleEvent(EVENT_RELEASE_2_5, 1s); + break; + case EVENT_RELEASE_2_5: + _events.ScheduleEvent(EVENT_MAIN_CHANNEL, 0s); + _events.ScheduleEvent(EVENT_RELEASE_2_6, 7s); + break; + case EVENT_RELEASE_2_6: + me->SummonCreature(NPC_MILLHOUSE_M, PrisonerSpawnPos[1], TEMPSUMMON_MANUAL_DESPAWN); + _events.ScheduleEvent(EVENT_RELEASE_3_1, 12s); + break; + + case EVENT_RELEASE_3_1: + me->InterruptNonMeleeSpells(true); + me->RemoveAurasDueToSpell(SPELL_TARGET_OMEGA); + _events.CancelEvent(EVENT_MAIN_CHANNEL); + _events.ScheduleEvent(EVENT_RELEASE_3_2, 2s); + break; + case EVENT_RELEASE_3_2: + me->SetFacingTo(2.478367567062377929f); + Talk(SAY_RELEASE_5); + _events.ScheduleEvent(EVENT_RELEASE_3_3, 6s); + break; + case EVENT_RELEASE_3_3: + DoCastSelf(SPELL_TARGET_DELTA); + _events.ScheduleEvent(EVENT_RELEASE_3_4, 3s); + break; + case EVENT_RELEASE_3_4: + me->SetFacingTo(4.747295379638671875f); + _events.ScheduleEvent(EVENT_RELEASE_3_5, 1s); + break; + case EVENT_RELEASE_3_5: + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_STASIS_POD_DELTA)); + _events.ScheduleEvent(EVENT_RELEASE_3_6, 4s); + break; + case EVENT_RELEASE_3_6: + _events.ScheduleEvent(EVENT_MAIN_CHANNEL, 0s); + _events.ScheduleEvent(EVENT_RELEASE_3_7, 4s); + break; + case EVENT_RELEASE_3_7: + me->SummonCreature(RAND(NPC_AKKIRIS, NPC_SULFURON), PrisonerSpawnPos[2], TEMPSUMMON_MANUAL_DESPAWN); + break; + + case EVENT_RELEASE_4_1: + me->InterruptNonMeleeSpells(true); + me->RemoveAurasDueToSpell(SPELL_TARGET_OMEGA); + me->SetFacingTo(6.056292533874511718f); + Talk(SAY_RELEASE_6); + _events.CancelEvent(EVENT_MAIN_CHANNEL); + _events.ScheduleEvent(EVENT_RELEASE_4_2, 5s); + break; + case EVENT_RELEASE_4_2: + DoCastSelf(SPELL_TARGET_GAMMA); + _events.ScheduleEvent(EVENT_RELEASE_4_3, 2s); + break; + case EVENT_RELEASE_4_3: + me->SetFacingTo(4.747295379638671875f); + _events.ScheduleEvent(EVENT_RELEASE_4_4, 1s); + break; + case EVENT_RELEASE_4_4: + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_STASIS_POD_GAMMA)); + _events.ScheduleEvent(EVENT_RELEASE_4_5, 2s); + break; + case EVENT_RELEASE_4_5: + _events.ScheduleEvent(EVENT_MAIN_CHANNEL, 0s); + _events.ScheduleEvent(EVENT_RELEASE_4_6, 7s); + break; + case EVENT_RELEASE_4_6: + me->SummonCreature(RAND(NPC_TW_DRAK, NPC_BL_DRAK), PrisonerSpawnPos[3], TEMPSUMMON_MANUAL_DESPAWN); + break; + + case EVENT_RELEASE_5_1: + me->InterruptNonMeleeSpells(true); + me->RemoveAurasDueToSpell(SPELL_TARGET_OMEGA); + Talk(SAY_RELEASE_7); + _events.CancelEvent(EVENT_MAIN_CHANNEL); + _events.ScheduleEvent(EVENT_RELEASE_5_2, 1s); + break; + case EVENT_RELEASE_5_2: + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_STASIS_POD_OMEGA)); + _events.ScheduleEvent(EVENT_RELEASE_5_3, 10s); + break; + case EVENT_RELEASE_5_3: + me->SummonCreature(NPC_SKYRISS, PrisonerSpawnPos[4], TEMPSUMMON_MANUAL_DESPAWN); + _events.ScheduleEvent(EVENT_RELEASE_5_4, 24s); + break; + case EVENT_RELEASE_5_4: + Talk(SAY_RELEASE_8); + _events.ScheduleEvent(EVENT_RELEASE_5_5, 7s); + break; + case EVENT_RELEASE_5_5: + DoCastSelf(SPELL_QUIET_SUICIDE); + _instance->HandleGameObject(ObjectGuid::Empty, true, _instance->GetGameObject(DATA_WARDENS_SHIELD)); + me->DespawnOrUnsummon(18s); + break; + default: + break; } } - else - EventProgress_Timer -= diff; } + +private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + bool _inProgress; }; void AddSC_arcatraz() diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h index 9e30c8bb381..a6ef0631565 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.h @@ -31,7 +31,7 @@ enum AZDataTypes DATA_ZEREKETH = 0, DATA_DALLIAH = 1, DATA_SOCCOTHRATES = 2, - DATA_HARBINGER_SKYRISS = 3, + DATA_HARBINGER_SKYRISS = 3, // used by SmartAI // Additional Data DATA_CONVERSATION = 4, @@ -40,16 +40,20 @@ enum AZDataTypes DATA_WARDEN_3 = 7, // used by SmartAI DATA_WARDEN_4 = 8, // used by SmartAI DATA_WARDEN_5 = 9, // used by SmartAI - DATA_MELLICHAR = 10, - DATA_WARDENS_SHIELD = 11 + DATA_MELLICHAR, + DATA_WARDENS_SHIELD, + DATA_STASIS_POD_ALPHA, + DATA_STASIS_POD_BETA, + DATA_STASIS_POD_DELTA, + DATA_STASIS_POD_GAMMA, + DATA_STASIS_POD_OMEGA }; enum AZCreatureIds { NPC_DALLIAH = 20885, NPC_SOCCOTHRATES = 20886, - NPC_MELLICHAR = 20904, // skyriss will kill this unit - NPC_ALPHA_POD_TARGET = 21436, + NPC_MELLICHAR = 20904, NPC_MILLHOUSE = 20977 }; @@ -70,6 +74,11 @@ enum AZSpellIds SPELL_QID_10886 = 39564 }; +enum AZMisc +{ + ACTION_RESET_PRISON = 1 +}; + template <class AI, class T> inline AI* GetArcatrazAI(T* obj) { diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp index 2dcad062e32..9c75c590f6d 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp @@ -15,8 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* Need more docs on how event fully work. Reset all event and force start over if fail at one point? */ - #include "ScriptMgr.h" #include "SpellInfo.h" #include "SpellScript.h" @@ -29,7 +27,7 @@ enum SkyrissTexts { SAY_INTRO = 0, SAY_AGGRO = 1, - SAY_KILL = 2, + SAY_SLAY = 2, SAY_MIND = 3, SAY_FEAR = 4, SAY_IMAGE = 5, @@ -50,7 +48,7 @@ enum SkyrissSpells SPELL_SUMMON_66_ILLUSION = 36931, SPELL_SUMMON_33_ILLUSION = 36932, - + // Illusion SPELL_BIRTH = 26262, SPELL_BLINK_VISUAL = 36937, SPELL_66_HEALTH = 36928, @@ -66,7 +64,11 @@ enum SkyrissEvents EVENT_DOMINATION, EVENT_MANA_BURN, EVENT_SUMMON_66, - EVENT_SUMMON_33 + EVENT_SUMMON_33, + + EVENT_INTRO_1, + EVENT_INTRO_2, + EVENT_INTRO_3 }; enum SkyrissMisc @@ -85,25 +87,17 @@ enum SkyrissPhases : uint8 // 20912 - Harbinger Skyriss struct boss_harbinger_skyriss : public BossAI { - boss_harbinger_skyriss(Creature* creature) : BossAI(creature, DATA_HARBINGER_SKYRISS), _intro(false), _phase(PHASE_NONE) { } + boss_harbinger_skyriss(Creature* creature) : BossAI(creature, DATA_HARBINGER_SKYRISS), _phase(PHASE_NONE) { } - void Initialize() + void JustAppeared() override { - Intro_Phase = 1; - Intro_Timer = 5000; + events.ScheduleEvent(EVENT_INTRO_1, 0s); } - uint32 Intro_Phase; - uint32 Intro_Timer; - void Reset() override { - DoCastSelf(SPELL_SIMPLE_TELEPORT); _Reset(); - _intro = false; _phase = PHASE_NONE; - me->SetImmuneToAll(!_intro); - Initialize(); } void JustEngagedWith(Unit* who) override @@ -132,13 +126,9 @@ struct boss_harbinger_skyriss : public BossAI } } - void KilledUnit(Unit* victim) override + void KilledUnit(Unit* /*victim*/) override { - // Won't yell killing pet/other unit - if (victim->GetEntry() == NPC_ALPHA_POD_TARGET) - return; - - Talk(SAY_KILL); + Talk(SAY_SLAY); } void DamageTaken(Unit* /*killer*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override @@ -163,42 +153,34 @@ struct boss_harbinger_skyriss : public BossAI void UpdateAI(uint32 diff) override { - if (!_intro) + if (!UpdateVictim()) { - if (Intro_Timer <= diff) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - switch (Intro_Phase) + switch (eventId) { - case 1: - Talk(SAY_INTRO); - instance->HandleGameObject(instance->GetGuidData(DATA_WARDENS_SHIELD), true); - ++Intro_Phase; - Intro_Timer = 25000; - break; - case 2: - Talk(SAY_AGGRO); - if (Unit* mellic = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MELLICHAR))) - { - //should have a better way to do this. possibly spell exist. - mellic->setDeathState(JUST_DIED); - mellic->SetHealth(0); - instance->HandleGameObject(instance->GetGuidData(DATA_WARDENS_SHIELD), false); - } - ++Intro_Phase; - Intro_Timer = 3000; - break; - case 3: - me->SetImmuneToAll(false); - _intro = true; - break; + case EVENT_INTRO_1: + Talk(SAY_INTRO); + DoCastSelf(SPELL_SIMPLE_TELEPORT); + events.ScheduleEvent(EVENT_INTRO_2, 30s); + break; + case EVENT_INTRO_2: + Talk(SAY_AGGRO); + DoCastSelf(SPELL_MIND_REND_COSMETIC); + events.ScheduleEvent(EVENT_INTRO_3, 2s); + break; + case EVENT_INTRO_3: + me->SetImmuneToAll(false); + DoZoneInCombat(); + break; + default: + break; } } - else - Intro_Timer -=diff; - } - - if (!UpdateVictim()) return; + } events.Update(diff); @@ -251,7 +233,6 @@ struct boss_harbinger_skyriss : public BossAI } private: - bool _intro; uint8 _phase; }; diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp index 5f1321fb762..18a830bdcd9 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "arcatraz.h" #include "Creature.h" +#include "CreatureAI.h" #include "GameObject.h" #include "InstanceScript.h" #include "Map.h" @@ -29,6 +30,23 @@ DoorData const doorData[] = { 0, 0, DOOR_TYPE_ROOM } // END }; +ObjectData const creatureData[] = +{ + { NPC_MELLICHAR, DATA_MELLICHAR }, + { 0, 0 } // END +}; + +ObjectData const gameObjectData[] = +{ + { GO_STASIS_POD_ALPHA, DATA_STASIS_POD_ALPHA }, + { GO_STASIS_POD_BETA, DATA_STASIS_POD_BETA }, + { GO_STASIS_POD_DELTA, DATA_STASIS_POD_DELTA }, + { GO_STASIS_POD_GAMMA, DATA_STASIS_POD_GAMMA }, + { GO_STASIS_POD_OMEGA, DATA_STASIS_POD_OMEGA }, + { GO_WARDENS_SHIELD, DATA_WARDENS_SHIELD }, + { 0, 0 } //END +}; + class instance_arcatraz : public InstanceMapScript { public: @@ -41,6 +59,7 @@ class instance_arcatraz : public InstanceMapScript SetHeaders(DataHeader); SetBossNumber(EncounterCount); LoadDoorData(doorData); + LoadObjectData(creatureData, gameObjectData); ConversationState = NOT_STARTED; @@ -59,9 +78,6 @@ class instance_arcatraz : public InstanceMapScript case NPC_SOCCOTHRATES: SoccothratesGUID = creature->GetGUID(); break; - case NPC_MELLICHAR: - MellicharGUID = creature->GetGUID(); - break; case NPC_MILLHOUSE: MillhouseGUID = creature->GetGUID(); break; @@ -70,35 +86,6 @@ class instance_arcatraz : public InstanceMapScript } } - void OnGameObjectCreate(GameObject* go) override - { - InstanceScript::OnGameObjectCreate(go); - - switch (go->GetEntry()) - { - case GO_STASIS_POD_ALPHA: - StasisPodGUIDs[0] = go->GetGUID(); - break; - case GO_STASIS_POD_BETA: - StasisPodGUIDs[1] = go->GetGUID(); - break; - case GO_STASIS_POD_DELTA: - StasisPodGUIDs[2] = go->GetGUID(); - break; - case GO_STASIS_POD_GAMMA: - StasisPodGUIDs[3] = go->GetGUID(); - break; - case GO_STASIS_POD_OMEGA: - StasisPodGUIDs[4] = go->GetGUID(); - break; - case GO_WARDENS_SHIELD: - WardensShieldGUID = go->GetGUID(); - break; - default: - break; - } - } - void SetData(uint32 type, uint32 data) override { switch (type) @@ -108,8 +95,6 @@ class instance_arcatraz : public InstanceMapScript case DATA_WARDEN_3: case DATA_WARDEN_4: case DATA_WARDEN_5: - if (data == IN_PROGRESS) - HandleGameObject(StasisPodGUIDs[type - DATA_WARDEN_1], true); StasisPodStates[type - DATA_WARDEN_1] = uint8(data); break; case DATA_CONVERSATION: @@ -146,10 +131,6 @@ class instance_arcatraz : public InstanceMapScript return DalliahGUID; case DATA_SOCCOTHRATES: return SoccothratesGUID; - case DATA_MELLICHAR: - return MellicharGUID; - case DATA_WARDENS_SHIELD: - return WardensShieldGUID; default: break; } @@ -172,7 +153,7 @@ class instance_arcatraz : public InstanceMapScript SetData(DATA_WARDEN_4, NOT_STARTED); SetData(DATA_WARDEN_5, NOT_STARTED); } - else if (state == DONE) + if (state == DONE) { if (!instance->IsHeroic()) break; @@ -181,6 +162,11 @@ class instance_arcatraz : public InstanceMapScript if (millhouse->IsAlive()) DoCastSpellOnPlayers(SPELL_QID_10886); } + if (state == FAIL) + { + if (Creature* mellichar = GetCreature(DATA_MELLICHAR)) + mellichar->AI()->DoAction(ACTION_RESET_PRISON); + } break; default: break; @@ -191,9 +177,6 @@ class instance_arcatraz : public InstanceMapScript protected: ObjectGuid DalliahGUID; ObjectGuid SoccothratesGUID; - ObjectGuid StasisPodGUIDs[5]; - ObjectGuid MellicharGUID; - ObjectGuid WardensShieldGUID; ObjectGuid MillhouseGUID; uint8 ConversationState; |