bool HasPlayersInLeftSide() { Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers(); if (lPlayers.isEmpty()) return false; for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) { if (Player* pPlayer = itr->getSource()) { if (!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive()) return true; } } return false; }
bool HasPlayersInLeftSide() const { Map::PlayerList const& lPlayers = m_pInstance->instance->GetPlayers(); if (lPlayers.isEmpty()) return false; for (const auto& lPlayer : lPlayers) { if (Player* pPlayer = lPlayer.getSource()) { if (!m_pInstance->IsInRightSideGothArea(pPlayer) && pPlayer->isAlive()) return true; } } return false; }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; switch (m_uiPhase) { case PHASE_SPEECH: if (m_uiSpeechTimer < uiDiff) { switch (m_uiSpeech) { case 1: DoScriptText(SAY_SPEECH_1, m_creature); m_uiSpeechTimer = 4 * IN_MILLISECONDS; break; case 2: DoScriptText(SAY_SPEECH_2, m_creature); m_uiSpeechTimer = 6 * IN_MILLISECONDS; break; case 3: DoScriptText(SAY_SPEECH_3, m_creature); m_uiSpeechTimer = 5 * IN_MILLISECONDS; break; case 4: DoScriptText(SAY_SPEECH_4, m_creature); m_uiPhase = PHASE_BALCONY; break; } m_uiSpeech++; } else m_uiSpeechTimer -= uiDiff; // No break here case PHASE_BALCONY: // Do summoning if (m_uiTraineeTimer < uiDiff) { SummonAdds(true, NPC_UNREL_TRAINEE); m_uiTraineeTimer = 20 * IN_MILLISECONDS; } else m_uiTraineeTimer -= uiDiff; if (m_uiDeathKnightTimer < uiDiff) { SummonAdds(true, NPC_UNREL_DEATH_KNIGHT); m_uiDeathKnightTimer = 25 * IN_MILLISECONDS; } else m_uiDeathKnightTimer -= uiDiff; if (m_uiRiderTimer < uiDiff) { SummonAdds(true, NPC_UNREL_RIDER); m_uiRiderTimer = 30 * IN_MILLISECONDS; } else m_uiRiderTimer -= uiDiff; if (m_uiPhaseTimer < uiDiff) { m_uiPhase = PHASE_STOP_SUMMONING; m_uiPhaseTimer = 50 * IN_MILLISECONDS; } else m_uiPhaseTimer -= uiDiff; break; case PHASE_STOP_SUMMONING: if (m_uiPhaseTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT, CAST_TRIGGERED) == CAST_OK) { m_uiPhase = m_pInstance ? PHASE_TELEPORTING : PHASE_STOP_TELEPORTING; DoScriptText(SAY_TELEPORT, m_creature); DoScriptText(EMOTE_TO_FRAY, m_creature); // Remove Immunity m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false); DoResetThreat(); m_creature->SetInCombatWithZone(); } } else m_uiPhaseTimer -= uiDiff; break; case PHASE_TELEPORTING: // Phase is only reached if m_pInstance is valid if (m_uiTeleportTimer < uiDiff) { uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT; if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK) { m_uiTeleportTimer = urand(30000, 45000); // Teleports between 30 seconds and 45 seconds. m_uiShadowboltTimer = 2 * IN_MILLISECONDS; } } else m_uiTeleportTimer -= uiDiff; if (m_creature->GetHealthPercent() <= 30.0f) { m_uiPhase = PHASE_STOP_TELEPORTING; ProcessCentralDoor(); // as the doors now open, recheck whether mobs are standing around m_uiControlZoneTimer = 1; } // no break here case PHASE_STOP_TELEPORTING: if (m_uiHarvestSoulTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_HARVESTSOUL) == CAST_OK) m_uiHarvestSoulTimer = 15 * IN_MILLISECONDS; } else m_uiHarvestSoulTimer -= uiDiff; if (m_uiShadowboltTimer) { if (m_uiShadowboltTimer <= uiDiff) m_uiShadowboltTimer = 2 * IN_MILLISECONDS; else m_uiShadowboltTimer -= uiDiff; } // Shadowbold cooldown finished, cast when ready else if (!m_creature->IsNonMeleeSpellCasted(true)) { // Select valid target if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) DoCastSpellIfCan(pTarget, SPELL_SHADOWBOLT); } break; } // Control Check, if Death zone empty if (m_uiControlZoneTimer) { if (m_uiControlZoneTimer <= uiDiff) { m_uiControlZoneTimer = 0; if (m_pInstance && !HasPlayersInLeftSide()) { ProcessCentralDoor(); for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); itr++) { if (Creature* pCreature = m_pInstance->instance->GetCreature(*itr)) { if (!pCreature->isInCombat()) pCreature->SetInCombatWithZone(); } } } } else m_uiControlZoneTimer -= uiDiff; } }
void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; switch(m_uiPhase) { case PHASE_SPEECH: { if (m_uiSpeechTimer < uiDiff) { m_uiSpeechTimer = 5000; ++m_uiSpeechCount; switch(m_uiSpeechCount) { case 1: DoScriptText(SAY_SPEECH_2, m_creature); break; case 2: DoScriptText(SAY_SPEECH_3, m_creature); break; case 3: DoScriptText(SAY_SPEECH_4, m_creature); break; case 4: m_uiPhase = PHASE_BALCONY; break; } } else m_uiSpeechTimer -= uiDiff; break; } case PHASE_BALCONY: { if (m_uiSummonTimer < uiDiff) { if (m_uiSummonCount >= MAX_WAVES) { DoScriptText(SAY_TELEPORT, m_creature); DoScriptText(EMOTE_TO_FRAY, m_creature); DoCastSpellIfCan(m_creature, SPELL_TELEPORT_RIGHT); m_uiPhase = PHASE_GROUND; return; } // npc, npc, npc, timer static uint32 const auiSummonData[MAX_WAVES][4] = { {NPC_UNREL_TRAINEE, 0, 0, 20000}, {NPC_UNREL_TRAINEE, 0, 0, 20000}, {NPC_UNREL_TRAINEE, 0, 0, 10000}, {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000}, {NPC_UNREL_TRAINEE, 0, 0, 15000}, {NPC_UNREL_DEATH_KNIGHT, 0, 0, 10000}, {NPC_UNREL_TRAINEE, 0, 0, 15000}, {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 0, 10000}, {NPC_UNREL_RIDER, 0, 0, 10000}, {NPC_UNREL_TRAINEE, 0, 0, 5000}, {NPC_UNREL_DEATH_KNIGHT, 0, 0, 15000}, {NPC_UNREL_TRAINEE, NPC_UNREL_RIDER, 0, 10000}, {NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_DEATH_KNIGHT, 0, 10000}, {NPC_UNREL_TRAINEE, 0, 0, 10000}, {NPC_UNREL_RIDER, 0, 0, 5000}, {NPC_UNREL_DEATH_KNIGHT, 0, 0, 5000}, {NPC_UNREL_TRAINEE, 0, 0, 20000}, {NPC_UNREL_RIDER, NPC_UNREL_DEATH_KNIGHT, NPC_UNREL_TRAINEE, 15000}, {NPC_UNREL_TRAINEE, 0, 0, 30000}, }; SummonAdds(true, auiSummonData[m_uiSummonCount][0]); if (auiSummonData[m_uiSummonCount][1]) SummonAdds(true, auiSummonData[m_uiSummonCount][1]); if (auiSummonData[m_uiSummonCount][2]) SummonAdds(true, auiSummonData[m_uiSummonCount][2]); m_uiSummonTimer = auiSummonData[m_uiSummonCount][3]; ++m_uiSummonCount; } else m_uiSummonTimer -= uiDiff; break; } case PHASE_GROUND: case PHASE_END: { if (m_uiPhase == PHASE_GROUND) { if (m_creature->GetHealthPercent() < 30.0f) { if (m_pInstance->IsInRightSideGothArea(m_creature)) { DoScriptText(EMOTE_GATE, m_creature); m_pInstance->SetData(TYPE_GOTHIK, SPECIAL); m_uiPhase = PHASE_END; m_uiShadowboltTimer = 2000; return; } } if (m_uiTeleportTimer < uiDiff) { uint32 uiTeleportSpell = m_pInstance->IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT; if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK) { DoResetThreat(); m_uiTeleportTimer = 15000; m_uiShadowboltTimer = 2000; return; } } else m_uiTeleportTimer -= uiDiff; } if (m_uiShadowboltTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOWBOLT: SPELL_SHADOWBOLT_H) == CAST_OK) m_uiShadowboltTimer = 1500; } else m_uiShadowboltTimer -= uiDiff; DoMeleeAttackIfReady(); // possibly no melee at all break; } } }