void UpdateAI(const uint32 diff) { if (!UpdateCombatState() || !CheckInRoom()) return; events.Update(diff); while(uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_CURSE: DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); events.ScheduleEvent(EVENT_CURSE, 20000+rand()%10000); return; case EVENT_WARRIOR: DoScriptText(SAY_SUMMON, me); SummonUndead(MOB_WARRIOR, HEROIC(2,3)); events.ScheduleEvent(EVENT_WARRIOR, 30000); return; case EVENT_BLINK: DoCastAOE(SPELL_CRIPPLE, true); DoCastAOE(SPELL_BLINK); DoResetThreat(); events.ScheduleEvent(EVENT_BLINK, 20000+rand()%10000); return; case EVENT_BALCONY: me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->AttackStop(); me->RemoveAllAuras(); me->NearTeleportTo(TELE_X, TELE_Y, TELE_Z, TELE_O); events.Reset(); events.ScheduleEvent(EVENT_WAVE, 2000); waveCount = 0; return; case EVENT_WAVE: DoScriptText(SAY_SUMMON, me); switch(balconyCount) { case 0: SummonUndead(MOB_CHAMPION, HEROIC(2,4)); break; case 1: SummonUndead(MOB_CHAMPION, HEROIC(1,2)); SummonUndead(MOB_GUARDIAN, HEROIC(1,2)); break; case 2: SummonUndead(MOB_GUARDIAN, HEROIC(2,4)); break; default:SummonUndead(MOB_CHAMPION, HEROIC(5,10)); SummonUndead(MOB_GUARDIAN, HEROIC(5,10));break; } ++waveCount; events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, 34000); return; case EVENT_GROUND: { ++balconyCount; float x, y, z, o; me->GetHomePosition(x, y, z, o); me->NearTeleportTo(x, y, z, o); EnterPhaseGround(); return; } } } if (me->HasReactState(REACT_AGGRESSIVE)) DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 diff) { if (!phase) return; events.Update(diff); if (phase != PHASE_BIRTH && !UpdateCombatState() || !CheckInRoom()) return; if (CanTheHundredClub) { if (CheckFrostResistTimer <= diff) { CheckPlayersFrostResist(); CheckFrostResistTimer = (rand() % 5 + 5) * 1000; } else CheckFrostResistTimer -= diff; } if (phase == PHASE_GROUND) { while (uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_BERSERK: DoScriptText(EMOTE_ENRAGE, me); DoCast(me, SPELL_BERSERK); return; case EVENT_CLEAVE: DoCast(me->getVictim(), SPELL_CLEAVE); events.ScheduleEvent(EVENT_CLEAVE, 5000+rand()%10000, 0, PHASE_GROUND); return; case EVENT_TAIL: DoCastAOE(SPELL_TAIL_SWEEP); events.ScheduleEvent(EVENT_TAIL, 5000+rand()%10000, 0, PHASE_GROUND); return; case EVENT_DRAIN: DoCastAOE(SPELL_LIFE_DRAIN); events.ScheduleEvent(EVENT_DRAIN, 24000, 0, PHASE_GROUND); return; case EVENT_BLIZZARD: { //DoCastAOE(SPELL_SUMMON_BLIZZARD); if (Creature *pSummon = DoSummon(MOB_BLIZZARD, me, 0.0f, urand(25000,30000), TEMPSUMMON_TIMED_DESPAWN)) pSummon->GetMotionMaster()->MoveRandom(40); events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20000,7000), 0, PHASE_GROUND); break; } case EVENT_FLIGHT: phase = PHASE_FLIGHT; events.SetPhase(PHASE_FLIGHT); me->SetReactState(REACT_PASSIVE); me->AttackStop(); float x, y, z, o; me->GetHomePosition(x, y, z, o); me->GetMotionMaster()->MovePoint(1, x, y, z); return; } } DoMeleeAttackIfReady(); } else { if (uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_LIFTOFF: me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->SendMovementFlagUpdate(); events.ScheduleEvent(EVENT_ICEBOLT, 1500); iceboltCount = RAID_MODE(2,3); return; case EVENT_ICEBOLT: { std::vector<Unit*> targets; std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); for (; i != me->getThreatManager().getThreatList().end(); ++i) if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) targets.push_back((*i)->getTarget()); if (targets.empty()) iceboltCount = 0; else { std::vector<Unit*>::const_iterator itr = targets.begin(); advance(itr, rand()%targets.size()); iceblocks.insert(std::make_pair((*itr)->GetGUID(), 0)); DoCast(*itr, SPELL_ICEBOLT); --iceboltCount; } if (iceboltCount) events.ScheduleEvent(EVENT_ICEBOLT, 1000); else events.ScheduleEvent(EVENT_BREATH, 1000); return; } case EVENT_BREATH: { DoScriptText(EMOTE_BREATH, me); DoCastAOE(SPELL_FROST_MISSILE); events.ScheduleEvent(EVENT_EXPLOSION, 8000); return; } case EVENT_EXPLOSION: CastExplosion(); ClearIceBlock(); events.ScheduleEvent(EVENT_LAND, 3000); return; case EVENT_LAND: me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); me->SendMovementFlagUpdate(); events.ScheduleEvent(EVENT_GROUND, 1500); return; case EVENT_GROUND: EnterPhaseGround(); return; case EVENT_BIRTH: me->SetVisibility(VISIBILITY_ON); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetReactState(REACT_AGGRESSIVE); return; } }//if (uint32 eventId = events.ExecuteEvent()) }//if (phase == PHASE_GROUND) }
void UpdateAI(const uint32 diff) { if (!UpdateCombatState()) return; events.Update(diff); if (Phase == 1) { while(uint32 eventId = events.GetEvent()) { switch (eventId) { case EVENT_WASTE: DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); events.RepeatEvent(urand(2000,5000)); break; case EVENT_ABOMIN: if (nAbomination < 8) { DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); nAbomination++; events.RepeatEvent(20000); } else events.PopEvent(); break; case EVENT_WEAVER: if (nWeaver < 8) { DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); nWeaver++; events.RepeatEvent(25000); } else events.PopEvent(); break; case EVENT_TRIGGER: if (GameObject *pKTTrigger = m_creature->GetMap()->GetGameObject(KTTriggerGUID)) pKTTrigger->SetPhaseMask(2, true); events.PopEvent(); break; case EVENT_PHASE: events.Reset(); DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); spawns.DespawnAll(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); me->CastStop(); DoStartMovement(me->getVictim()); events.ScheduleEvent(EVENT_BOLT, urand(5000,10000)); events.ScheduleEvent(EVENT_NOVA, 15000); events.ScheduleEvent(EVENT_DETONATE, urand(30000,40000)); events.ScheduleEvent(EVENT_FISSURE, urand(10000,30000)); events.ScheduleEvent(EVENT_BLAST, urand(60000,120000)); if (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); Phase = 2; break; default: events.PopEvent(); break; } } } else { //start phase 3 when we are 45% health if (Phase != 3) { if (HealthBelowPct(45)) { Phase = 3 ; DoScriptText(SAY_REQUEST_AID, m_creature); //here Lich King should respond to KelThuzad but I don't know which Creature to make talk //so for now just make Kelthuzad says it. DoScriptText(SAY_ANSWER_REQUEST, m_creature); for (uint8 i = 0; i <= 3; ++i) { if (GameObject *pPortal = m_creature->GetMap()->GetGameObject(PortalsGUID[i])) { if (pPortal->getLootState() == GO_READY) pPortal->UseDoorOrButton(); } } } } else if (nGuardiansOfIcecrownCount < RAID_MODE(2,4)) { if (uiGuardiansOfIcecrownTimer <= diff) { // TODO : Add missing text if (Creature* pGuardian = DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8,11)])) pGuardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2); ++nGuardiansOfIcecrownCount; uiGuardiansOfIcecrownTimer = 5000; } else uiGuardiansOfIcecrownTimer -= diff; } if (me->hasUnitState(UNIT_STAT_CASTING)) return; if (uint32 eventId = events.GetEvent()) { switch (eventId) { case EVENT_BOLT: DoCastVictim(RAID_MODE(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); events.RepeatEvent(urand(5000,10000)); break; case EVENT_NOVA: DoCastAOE(RAID_MODE(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); events.RepeatEvent(urand(15000,30000)); break; case EVENT_CHAIN: { uint32 count = urand(1,3); for (uint8 i = 1; i <= count; i++) { Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true); if (pTarget && !pTarget->isCharmed() && (chained.find(pTarget->GetGUID()) == chained.end())) { DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); float scale = pTarget->GetFloatValue(OBJECT_FIELD_SCALE_X); chained.insert(std::make_pair(pTarget->GetGUID(), scale)); pTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm } } if (!chained.empty()) DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); events.RepeatEvent(urand(100000,180000)); break; } case EVENT_CHAINED_SPELL: { std::map<uint64, float>::iterator itr; for (itr = chained.begin(); itr != chained.end();) { if (Unit* player = Unit::GetPlayer((*itr).first)) { if (!player->isCharmed()) { player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); std::map<uint64, float>::iterator next = itr; ++next; chained.erase(itr); itr = next; continue; } if (Unit *pTarget = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, NotCharmedTargetSelector())) { switch(player->getClass()) { case CLASS_DRUID: if (urand(0,1)) player->CastSpell(pTarget, SPELL_MOONFIRE, false); else player->CastSpell(m_creature, SPELL_LIFEBLOOM, false); break; case CLASS_HUNTER: player->CastSpell(pTarget, RAND(SPELL_MULTI_SHOT, SPELL_VOLLEY), false); break; case CLASS_MAGE: player->CastSpell(pTarget, RAND(SPELL_FROST_FIREBOLT, SPELL_ARCANE_MISSILES), false); break; case CLASS_WARLOCK: player->CastSpell(pTarget, RAND(SPELL_CURSE_OF_AGONY, SPELL_SHADOW_BOLT), true); break; case CLASS_WARRIOR: player->CastSpell(pTarget, RAND(SPELL_BLADESTORM, SPELL_CLEAVE), false); break; case CLASS_PALADIN: if (urand(0,1)) player->CastSpell(pTarget, SPELL_HAMMER_OF_JUSTICE, false); else player->CastSpell(m_creature, SPELL_HOLY_SHOCK, false); break; case CLASS_PRIEST: if (urand(0,1)) player->CastSpell(pTarget, SPELL_VAMPIRIC_TOUCH, false); else player->CastSpell(m_creature, SPELL_RENEW, false); break; case CLASS_SHAMAN: if (urand(0,1)) player->CastSpell(pTarget, SPELL_EARTH_SHOCK, false); else player->CastSpell(m_creature, SPELL_HEALING_WAVE, false); break; case CLASS_ROGUE: player->CastSpell(pTarget, RAND(SPELL_HEMORRHAGE, SPELL_MUTILATE), false); break; case CLASS_DEATH_KNIGHT: if (urand(0,1)) player->CastSpell(pTarget, SPELL_PLAGUE_STRIKE, true); else player->CastSpell(pTarget, SPELL_HOWLING_BLAST, true); break; } } } itr++; } if (chained.empty()) events.PopEvent(); else events.RepeatEvent(5000); break; } case EVENT_DETONATE: { std::vector<Unit*> unitList; std::list<HostileReference*> *threatList = &me->getThreatManager().getThreatList(); for (std::list<HostileReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) { if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->getPowerType() == POWER_MANA && (*itr)->getTarget()->GetPower(POWER_MANA)) unitList.push_back((*itr)->getTarget()); } if (!unitList.empty()) { std::vector<Unit*>::iterator itr = unitList.begin(); advance(itr, rand()%unitList.size()); DoCast(*itr, SPELL_MANA_DETONATION); DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); } events.RepeatEvent(urand(20000,50000)); break; } case EVENT_FISSURE: if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) DoCast(pTarget, SPELL_SHADOW_FISURE); events.RepeatEvent(urand(10000,45000)); break; case EVENT_BLAST: if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, RAID_MODE(1,0), 0, true)) DoCast(pTarget, SPELL_FROST_BLAST); if (rand()%2) DoScriptText(SAY_FROST_BLAST, m_creature); events.RepeatEvent(urand(30000,90000)); break; default: events.PopEvent(); break; } } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if (!CanStartEvent)//boss is invisible, don't attack { if (CheckCanStart()) { if (Submerged) { me->SetVisibility(VISIBILITY_ON); Submerged = false; WaitTimer2 = 500; } if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim { me->RemoveAllAuras(); me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); DoCast(me, SPELL_EMERGE, false); WaitTimer2 = 60000;//never reached WaitTimer = 3000; } else WaitTimer2 -= diff; if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack { WaitTimer = 3000; CanStartEvent=true;//fresh fished from pool me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } else WaitTimer -= diff; } return; } if (me->getThreatManager().getThreatList().empty())//check if should evade { if (me->isInCombat()) EnterEvadeMode(); return; } if (!Submerged) { if (PhaseTimer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_SUBMERGE); PhaseTimer = 60000;//60secs submerged Submerged = true; } else PhaseTimer-=diff; if (SpoutTimer <= diff) { me->MonsterTextEmote(EMOTE_SPOUT,0,true); me->SetReactState(REACT_PASSIVE); me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); SpoutTimer = 45000; WhirlTimer = 20000;//whirl directly after spout RotTimer = 20000; return; } else SpoutTimer -= diff; //Whirl directly after a Spout and at random times if (WhirlTimer <= diff) { WhirlTimer = 18000; DoCast(me, SPELL_WHIRL); } else WhirlTimer -= diff; if (CheckTimer <= diff)//check if there are players in melee range { InRange = false; Map* pMap = me->GetMap(); Map::PlayerList const &PlayerList = pMap->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (me->IsWithinMeleeRange(i->getSource())) InRange = true; } } CheckTimer = 2000; } else CheckTimer -= diff; if (RotTimer) { Map* pMap = me->GetMap(); if (pMap->IsDungeon()) { Map::PlayerList const &PlayerList = pMap->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water } } if (SpoutAnimTimer <= diff) { DoCast(me, SPELL_SPOUT_ANIM, true); SpoutAnimTimer = 1000; } else SpoutAnimTimer -= diff; if (RotTimer <= diff) { RotTimer = 0; } else RotTimer -= diff; return; } if (GeyserTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); if (!pTarget && me->getVictim()) pTarget = me->getVictim(); if (pTarget) DoCast(pTarget, SPELL_GEYSER, true); GeyserTimer = rand()%5000 + 15000; } else GeyserTimer -= diff; if (!InRange)//if on players in melee range cast Waterbolt { if (WaterboltTimer <= diff) { Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); if (!pTarget && me->getVictim()) pTarget = me->getVictim(); if (pTarget) DoCast(pTarget, SPELL_WATERBOLT, true); WaterboltTimer = 3000; } else WaterboltTimer -= diff; } if (!UpdateCombatState()) return; DoMeleeAttackIfReady(); }else//submerged { if (PhaseTimer <= diff) { Submerged = false; me->InterruptNonMeleeSpells(false);//shouldn't be any me->RemoveAllAuras(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); DoCast(me, SPELL_EMERGE, true); Spawned = false; SpoutTimer = 3000; // directly cast Spout after emerging! PhaseTimer = 120000; return; } else PhaseTimer-=diff; if (me->getThreatManager().getThreatList().empty())//check if should evade { EnterEvadeMode(); return; } if (!me->isInCombat()) DoZoneInCombat(); if (!Spawned) { me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); //spawn adds for (uint8 i = 0; i < 9; ++i) { Creature* Summoned; if (i < 6) Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); if (Summoned) Summons.Summon(Summoned); } Spawned = true; } } }
void UpdateAI(const uint32 diff) { if (!UpdateCombatState()) return; events.Update(diff); if (Phase == 1) { while(uint32 eventId = events.GetEvent()) { switch(eventId) { case EVENT_WASTE: DoSummon(NPC_WASTE, Pos[RAND(0,3,6,9)]); events.RepeatEvent(5000); break; case EVENT_ABOMIN: DoSummon(NPC_ABOMINATION, Pos[RAND(1,4,7,10)]); events.RepeatEvent(25000); break; case EVENT_WEAVER: DoSummon(NPC_WEAVER, Pos[RAND(0,3,6,9)]); events.RepeatEvent(20000); break; case EVENT_PHASE: events.Reset(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetReactState(REACT_AGGRESSIVE); events.ScheduleEvent(EVENT_BOLT, urand(1000,10000)); events.ScheduleEvent(EVENT_NOVA, urand(10000,15000)); events.ScheduleEvent(EVENT_DETONATE, 20000); events.ScheduleEvent(EVENT_FISSURE, 25000); events.ScheduleEvent(EVENT_BLAST, urand(30000,60000)); if (HeroicMode) events.ScheduleEvent(EVENT_CHAIN, urand(30000,60000)); Phase = 2; return; default: events.PopEvent(); break; } } } else { //start phase 3 when we are 40% health if (Phase != 3) { if (HealthBelowPct(40)) { Phase = 3 ; DoScriptText(SAY_REQUEST_AID, m_creature); //here Lich King should respond to KelThuzad but I don't know which Creature to make talk //so for now just make Kelthuzad says it. DoScriptText(SAY_ANSWER_REQUEST, m_creature); } } else if (GuardiansOfIcecrown_Count < HEROIC(2,5)) { if (GuardiansOfIcecrown_Timer <= diff) { DoSummon(NPC_ICECROWN, Pos[RAND(2,5,8)]); ++GuardiansOfIcecrown_Count; GuardiansOfIcecrown_Timer = 5000; } else GuardiansOfIcecrown_Timer -= diff; } if (me->hasUnitState(UNIT_STAT_CASTING)) return; if (uint32 eventId = events.GetEvent()) { switch(eventId) { case EVENT_BOLT: DoCastVictim(HEROIC(SPELL_FROST_BOLT,H_SPELL_FROST_BOLT)); events.RepeatEvent(urand(1000,10000)); return; case EVENT_NOVA: DoCastAOE(HEROIC(SPELL_FROST_BOLT_AOE,H_SPELL_FROST_BOLT_AOE)); events.RepeatEvent(urand(10000,20000)); return; case EVENT_CHAIN: if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) DoCast(pTarget, SPELL_CHAINS_OF_KELTHUZAD); DoScriptText(RAND(SAY_CHAIN_1,SAY_CHAIN_2), me); events.RepeatEvent(urand(30000,60000)); return; case EVENT_DETONATE: { std::vector<Unit*> unitList; std::list<HostilReference*> *threatList = &me->getThreatManager().getThreatList(); for (std::list<HostilReference*>::const_iterator itr = threatList->begin(); itr != threatList->end(); ++itr) { if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->getPowerType() == POWER_MANA && (*itr)->getTarget()->GetPower(POWER_MANA)) unitList.push_back((*itr)->getTarget()); } if (!unitList.empty()) { std::vector<Unit*>::iterator itr = unitList.begin(); advance(itr, rand()%unitList.size()); DoCast(*itr, SPELL_MANA_DETONATION); DoScriptText(RAND(SAY_SPECIAL_1,SAY_SPECIAL_2,SAY_SPECIAL_3), me); } events.RepeatEvent(20000); return; } case EVENT_FISSURE: if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) DoCast(pTarget, SPELL_SHADOW_FISURE); events.RepeatEvent(25000); return; case EVENT_BLAST: if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) DoCast(pTarget, SPELL_FROST_BLAST); if (rand()%2) DoScriptText(SAY_FROST_BLAST, m_creature); events.RepeatEvent(urand(30000,60000)); return; default: events.PopEvent(); return; } } DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 diff) { if (!UpdateCombatState() || !CheckInRoom()) return; events.Update(diff); if (!thirtyPercentReached && HealthBelowPct(30) && phaseTwo) { thirtyPercentReached = true; if (instance) instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); } if (me->hasUnitState(UNIT_STAT_CASTING)) return; while (uint32 eventId = events.ExecuteEvent()) { switch(eventId) { case EVENT_SUMMON: if (waves[waveCount].entry) { if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) DoGothikSummon(waves[waveCount].entry); else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) DoGothikSummon(waves[waveCount].entry); else if (waves[waveCount].mode == 1) DoGothikSummon(waves[waveCount].entry); // if group is not splitted, open gate and merge both sides at ~ 2 minutes (wave 11) if (waveCount == 11) { if (!CheckGroupSplitted()) { if (instance) instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); summons.DoAction(0, 0); summons.DoZoneInCombat(); mergedSides = true; } } if (waves[waveCount].mode == 1) events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); else if ((waves[waveCount].mode == 2) && (getDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); else if ((waves[waveCount].mode == 0) && (getDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) events.ScheduleEvent(EVENT_SUMMON,waves[waveCount].time); else events.ScheduleEvent(EVENT_SUMMON, 0); ++waveCount; } else { phaseTwo = true; DoScriptText(SAY_TELEPORT, me); DoTeleportTo(PosGroundLiveSide); me->SetReactState(REACT_AGGRESSIVE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); summons.DoAction(0, 0); summons.DoZoneInCombat(); events.ScheduleEvent(EVENT_BOLT, 1000); events.ScheduleEvent(EVENT_HARVEST, urand(3000,15000)); events.ScheduleEvent(EVENT_TELEPORT, 20000); } break; case EVENT_BOLT: DoCast(me->getVictim(), RAID_MODE(SPELL_SHADOW_BOLT, H_SPELL_SHADOW_BOLT)); events.ScheduleEvent(EVENT_BOLT, 1000); break; case EVENT_HARVEST: DoCast(me->getVictim(), SPELL_HARVEST_SOUL, true); events.ScheduleEvent(EVENT_HARVEST, urand(20000,25000)); break; case EVENT_TELEPORT: if (!thirtyPercentReached) { me->AttackStop(); if (IN_LIVE_SIDE(me)) { DoTeleportTo(PosGroundDeadSide); } else { DoTeleportTo(PosGroundLiveSide); } me->getThreatManager().resetAggro(NotOnSameSide(me)); if (Unit *pTarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) { me->getThreatManager().addThreat(pTarget, 100.0f); AttackStart(pTarget); } events.ScheduleEvent(EVENT_TELEPORT, 20000); } break; } } DoMeleeAttackIfReady(); }