// Replaces missing spell 28236 void DoSearchZombieChow() { for (GuidList::const_iterator itr = m_lZombieChowGuidList.begin(); itr != m_lZombieChowGuidList.end(); ++itr) { if (Creature* pZombie = m_creature->GetMap()->GetCreature(*itr)) { if (!pZombie->isAlive()) continue; // Devour a Zombie if (pZombie->IsWithinDistInMap(m_creature, 15.0f)) m_creature->DealDamage(pZombie, pZombie->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } } }
// function to return the closest ground Bunny Creature* GetClosestLowerBunny(Creature* pSource) { if (m_lLowerBunniesGuids.empty()) return NULL; std::list<Creature*> lBunnies; for (GuidList::const_iterator itr = m_lLowerBunniesGuids.begin(); itr != m_lLowerBunniesGuids.end(); ++itr) { if (Creature* pBunny = m_creature->GetMap()->GetCreature(*itr)) lBunnies.push_back(pBunny); } lBunnies.sort(ObjectDistanceOrder(pSource)); return lBunnies.front(); }
void DoSetupAdds() { m_uiSetupAddsTimer = 0; if (!m_pInstance) return; GuidList lAddGuids; m_pInstance->GetKelidanAddList(lAddGuids); // Sort Adds to vector if not already done if (!lAddGuids.empty()) { m_vAddGuids.reserve(lAddGuids.size()); std::list<Creature*> lAdds; for (GuidList::const_iterator itr = lAddGuids.begin(); itr != lAddGuids.end(); ++itr) { if (Creature* pAdd = m_pInstance->instance->GetCreature(*itr)) lAdds.push_back(pAdd); } // Sort them by angle lAdds.sort(SortByAngle(m_creature)); for (std::list<Creature*>::const_iterator itr = lAdds.begin(); itr != lAdds.end(); ++itr) m_vAddGuids.push_back((*itr)->GetObjectGuid()); } // Respawn killed adds and reset counter m_uiKilledAdds = 0; for (GuidVector::const_iterator itr = m_vAddGuids.begin(); itr != m_vAddGuids.end(); ++itr) { Creature* pAdd = m_pInstance->instance->GetCreature(*itr); if (pAdd && !pAdd->isAlive()) pAdd->Respawn(); } // Cast pentagram uint8 s = m_vAddGuids.size(); for (uint8 i = 0; i < s; ++i) { Creature* pCaster = m_pInstance->instance->GetCreature(m_vAddGuids[i]); Creature* pTarget = m_pInstance->instance->GetCreature(m_vAddGuids[(i + 2) % s]); if (pCaster && pTarget) pCaster->CastSpell(pTarget, SPELL_CHANNELING, TRIGGERED_NONE); } m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); }
void JustReachedHome() override { if (m_pInstance) { m_pInstance->SetData(NPC_DEVOURER_OF_SOULS, FAIL); // If we previously failed, set such that possible to try again m_pInstance->SetData(TYPE_ACHIEV_PHANTOM_BLAST, IN_PROGRESS); } for (GuidList::const_iterator itr = m_lWellGuids.begin(); itr != m_lWellGuids.end(); ++itr) { if (Creature* pWell = m_creature->GetMap()->GetCreature(*itr)) pWell->ForcedDespawn(); } m_lWellGuids.clear(); }
// make sparks come back void CallBackSparks() { for (GuidList::const_iterator itr = m_lSparkGUIDList.begin(); itr != m_lSparkGUIDList.end(); ++itr) { if (Creature* pSpark = m_creature->GetMap()->GetCreature(*itr)) { if (pSpark->IsAlive()) { // Required to prevent combat movement, elsewise they might switch movement on aggro-change if (ScriptedAI* pSparkAI = dynamic_cast<ScriptedAI*>(pSpark->AI())) pSparkAI->SetCombatMovement(false); pSpark->GetMotionMaster()->MovePoint(POINT_CALLBACK, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); } } } }
void AttackedBy(Unit* pAttacker) override { // When the Shade starts to attack Akama, switch to melee phase if (m_uiPhase == PHASE_CHANNEL && pAttacker->GetEntry() == NPC_SHADE_OF_AKAMA) { m_creature->InterruptNonMeleeSpells(false); AttackStart(pAttacker); m_uiPhase = PHASE_COMBAT; // despawn all sorcerers at this point for (GuidList::const_iterator itr = m_lSorcerersGUIDList.begin(); itr != m_lSorcerersGUIDList.end(); ++itr) { if (Creature* pSorcerer = m_creature->GetMap()->GetCreature(*itr)) pSorcerer->ForcedDespawn(); } } }
/** Given a list of guids returns the concatenation using | as delimiter @param[in] check list of guids @returns Concatenated string */ std::string ConcatenateGuids(GuidList const& check) { if (check.empty()) return ""; // need the guids in order to avoid duplicates GuidSet guids(check.begin(), check.end()); std::ostringstream o; GuidSet::const_iterator it = guids.begin(); o << it->GetRawValue(); for (++it; it != guids.end(); ++it) o << '|' << it->GetRawValue(); return o.str(); }
Creature* instance_zulgurub::SelectRandomPantherTrigger(bool bIsLeft) { GuidList* plTempList = bIsLeft ? &m_lLeftPantherTriggerGUIDList : &m_lRightPantherTriggerGUIDList; std::vector<Creature*> vTriggers; vTriggers.reserve(plTempList->size()); for (GuidList::const_iterator itr = plTempList->begin(); itr != plTempList->end(); ++itr) { if (Creature* pTemp = instance->GetCreature(*itr)) vTriggers.push_back(pTemp); } if (vTriggers.empty()) return NULL; return vTriggers[urand(0, vTriggers.size()-1)]; }
void DoTransferAbility() { for (GuidList::const_iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr) { if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr)) { if (*itr == m_creature->GetObjectGuid()) continue; if (!pBuddy->isAlive()) continue; pBuddy->SetHealth(pBuddy->GetMaxHealth()); DoCastSpellIfCan(pBuddy, m_uiMyAbility, CAST_TRIGGERED); } } }
void JustDied(Unit* /*pKiller*/) override { if (!m_pInstance) return; m_pInstance->SetData(TYPE_GRUBBIS, FAIL); if (m_bSouthernCaveInOpened) // close southern cave-in door m_pInstance->DoUseDoorOrButton(GO_CAVE_IN_SOUTH); if (m_bNorthernCaveInOpened) // close northern cave-in door m_pInstance->DoUseDoorOrButton(GO_CAVE_IN_NORTH); for (GuidList::const_iterator itr = m_luiSummonedMobGUIDs.begin(); itr != m_luiSummonedMobGUIDs.end(); ++itr) { if (Creature* pSummoned = m_creature->GetMap()->GetCreature(*itr)) pSummoned->ForcedDespawn(); } }
void JustDied(Unit* /*pKiller*/) override { DoScriptText(SAY_DEATH, m_creature); if (m_pInstance) { m_pInstance->SetData(TYPE_TRIBUNAL, FAIL); // Continue at right state after respawn if (m_bHasContinued) m_pInstance->SetData(TYPE_TRIBUNAL, IN_PROGRESS); } for (GuidList::const_iterator itr = m_luiDwarfGUIDs.begin(); itr != m_luiDwarfGUIDs.end(); ++itr) { if (Creature* pDwarf = m_creature->GetMap()->GetCreature(*itr)) pDwarf->ForcedDespawn(); } m_luiDwarfGUIDs.clear(); }
// Wrapper which sends each sphere in a different direction void ReceiveAIEvent(AIEventType eventType, Creature* /*sender*/, Unit* invoker, uint32 /**/) override { if (eventType != AI_EVENT_CUSTOM_A || invoker != m_creature) return; float fX, fY; uint8 uiIndex = m_bIsRegularMode ? urand(0, 2) : 0; for (GuidList::const_iterator itr = m_lFlameOrbsGuidList.begin(); itr != m_lFlameOrbsGuidList.end(); ++itr) { if (Creature* pOrb = m_creature->GetMap()->GetCreature(*itr)) { pOrb->CastSpell(pOrb, m_bIsRegularMode ? SPELL_FLAME_SPHERE_PERIODIC : SPELL_FLAME_SPHERE_PERIODIC_H, true); pOrb->GetNearPoint2D(fX, fY, 70.0f, (2 * M_PI_F / 3)*uiIndex); pOrb->GetMotionMaster()->MovePoint(0, fX, fY, pOrb->GetPositionZ()); } ++uiIndex; } }
// Wrapper to handle the blue beams animation void DoHandleBeamHelpers(bool bReset) { if (!m_pInstance) return; GuidList lBeamHelpersGuid; m_pInstance->GetBeamHelpersGUIDList(lBeamHelpersGuid); for (GuidList::const_iterator itr = lBeamHelpersGuid.begin(); itr != lBeamHelpersGuid.end(); ++itr) { if (Creature* pBeam = m_creature->GetMap()->GetCreature(*itr)) { if (bReset) pBeam->InterruptNonMeleeSpells(false); else pBeam->CastSpell(m_creature, SPELL_BLUE_BEAM, TRIGGERED_NONE); } } }
void SummonAdds(bool bRightSide, uint32 uiSummonEntry) { GuidList* plSummonPosGuids; switch(uiSummonEntry) { case NPC_UNREL_TRAINEE: plSummonPosGuids = &m_lTraineeSummonPosGuids; break; case NPC_UNREL_DEATH_KNIGHT: plSummonPosGuids = &m_lDeathKnightSummonPosGuids; break; case NPC_UNREL_RIDER: plSummonPosGuids = &m_lRiderSummonPosGuids; break; default: return; } if (plSummonPosGuids->empty()) return; for (GuidList::iterator itr = plSummonPosGuids->begin(); itr != plSummonPosGuids->end(); ++itr) { if (Creature* pPos = m_creature->GetMap()->GetCreature(*itr)) m_creature->SummonCreature(uiSummonEntry, pPos->GetPositionX(), pPos->GetPositionY(), pPos->GetPositionZ(), pPos->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); } }
void JustRespawned() override { Reset(); // Needed to reset the flags properly GuidList lTeslaGUIDList; if (!m_pInstance) return; m_pInstance->GetThadTeslaCreatures(lTeslaGUIDList); if (lTeslaGUIDList.empty()) return; for (GuidList::const_iterator itr = lTeslaGUIDList.begin(); itr != lTeslaGUIDList.end(); ++itr) { if (Creature* pTesla = m_pInstance->instance->GetCreature(*itr)) { if (npc_tesla_coilAI* pTeslaAI = dynamic_cast<npc_tesla_coilAI*>(pTesla->AI())) pTeslaAI->ReApplyChain(m_creature->GetEntry()); } } }
void SetData(uint32 uiType, uint32 /*uiData*/) override { switch (uiType) { case DATA_START: DoSummonGrandChampion(uiFirstBoss); NextStep(10000, false, 1); break; case DATA_IN_POSITION: //movement done. me->GetMotionMaster()->MovePoint(1, 735.81f, 661.92f, 412.39f); if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_MAIN_GATE))) instance->HandleGameObject(go->GetGUID(), false); NextStep(10000, false, 3); break; case DATA_LESSER_CHAMPIONS_DEFEATED: { ++uiLesserChampions; GuidList TempList; if (uiLesserChampions == 3 || uiLesserChampions == 6) { switch (uiLesserChampions) { case 3: TempList = Champion2List; break; case 6: TempList = Champion3List; break; } for (GuidList::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) AggroAllPlayers(summon); }else if (uiLesserChampions == 9) StartGrandChampionsAttack(); break; } } }
// function to enable harpoon repair animation void DoMoveEngineersToHarpoon() { float fX, fY, fZ; uint8 uiIndex = 1; // get the current harpoon and move the engineers in front of it if (GameObject* pHarpoon = m_creature->GetMap()->GetGameObject(m_vHarpoonsGuids[m_uiCurrentHarpoon])) { for (GuidList::const_iterator itr = m_lEngineersGuids.begin(); itr != m_lEngineersGuids.end(); ++itr) { if (Creature* pEngineer = m_creature->GetMap()->GetCreature(*itr)) { pHarpoon->GetNearPoint(pHarpoon, fX, fY, fZ, 0, INTERACTION_DISTANCE, M_PI_F / 4 * uiIndex); // ToDo: maybe there should be some emotes here pEngineer->SetWalk(false); pEngineer->GetMotionMaster()->MovePoint(1, fX, fY, fZ); ++uiIndex; } } } ++m_uiCurrentHarpoon; }
void CaveDestruction(bool isRight) { if (GoSummonList.empty()) return; for (GuidList::const_iterator itr = GoSummonList.begin(); itr != GoSummonList.end(); ++itr) { if (GameObject* go = ObjectAccessor::GetGameObject(*me, *itr)) { if (Creature* trigger = go->SummonTrigger(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 1)) { //visual effects are not working! trigger->CastSpell(trigger, 11542, true); trigger->CastSpell(trigger, 35470, true); } go->RemoveFromWorld(); //go->CastSpell(me, 12158); makes all die?! } } if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(isRight ? DATA_GO_CAVE_IN_RIGHT : DATA_GO_CAVE_IN_LEFT))) instance->HandleGameObject(ObjectGuid::Empty, false, go); }
void UpdateEscortAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); // Check if all Onyxia guards are dead if (m_uiGuardCheckTimer) { if (m_uiGuardCheckTimer <= uiDiff) { uint8 uiDeadGuardsCount = 0; for (GuidList::const_iterator itr = m_lRoyalGuardsGuidList.begin(); itr != m_lRoyalGuardsGuidList.end(); ++itr) { if (Creature* pGuard = m_creature->GetMap()->GetCreature(*itr)) { if (!pGuard->isAlive() && pGuard->GetEntry() == NPC_GUARD_ONYXIA) ++uiDeadGuardsCount; } } if (uiDeadGuardsCount == m_lRoyalGuardsGuidList.size()) { StartNextDialogueText(NPC_GUARD_ONYXIA); m_uiGuardCheckTimer = 0; } else m_uiGuardCheckTimer = 1000; } else m_uiGuardCheckTimer -= uiDiff; } }
void JustDidDialogueStep(int32 iEntry) override { if (!m_pScriptedMap) return; switch (iEntry) { // Set orientation and prepare the npcs for the next event case SAY_WINDSOR_GET_READY: m_creature->SetFacingTo(0.6f); break; case SAY_PRESTOR_SIEZE: if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid)) Start(false, pPlayer); break; case SAY_JON_DIALOGUE_8: // Turn left and move the guards if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) pJonathan->SetFacingTo(5.375f); if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[5])) { pGuard->SetFacingTo(2.234f); pGuard->SetStandState(UNIT_STAND_STATE_KNEEL); } if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[4])) pGuard->GetMotionMaster()->MovePoint(1, aMoveLocations[1][0], aMoveLocations[1][1], aMoveLocations[1][2]); if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[3])) pGuard->GetMotionMaster()->MovePoint(2, aMoveLocations[2][0], aMoveLocations[2][1], aMoveLocations[2][2]); break; case SAY_JON_DIALOGUE_9: // Turn right and move the guards if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) pJonathan->SetFacingTo(2.234f); if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[2])) { pGuard->SetFacingTo(5.375f); pGuard->SetStandState(UNIT_STAND_STATE_KNEEL); } if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[1])) pGuard->GetMotionMaster()->MovePoint(3, aMoveLocations[3][0], aMoveLocations[3][1], aMoveLocations[3][2]); if (Creature* pGuard = m_creature->GetMap()->GetCreature(m_guardsGuid[0])) pGuard->GetMotionMaster()->MovePoint(4, aMoveLocations[4][0], aMoveLocations[4][1], aMoveLocations[4][2]); break; case SAY_JON_DIALOGUE_10: if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) pJonathan->SetFacingToObject(m_creature); break; case EMOTE_ONESHOT_SALUTE: if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) pJonathan->HandleEmote(EMOTE_ONESHOT_SALUTE); break; case NPC_JONATHAN: if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) { pJonathan->SetWalk(true); pJonathan->GetMotionMaster()->MovePoint(0, aMoveLocations[5][0], aMoveLocations[5][1], aMoveLocations[5][2]); } break; case EMOTE_ONESHOT_KNEEL: if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) { pJonathan->SetFacingToObject(m_creature); pJonathan->SetStandState(UNIT_STAND_STATE_KNEEL); } break; case SAY_WINDSOR_DIALOGUE_12: if (Creature* pJonathan = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_JONATHAN)) m_creature->SetFacingToObject(pJonathan); break; case SAY_WINDSOR_DIALOGUE_13: m_creature->SetFacingTo(0.6f); break; case EMOTE_ONESHOT_POINT: m_creature->HandleEmote(EMOTE_ONESHOT_POINT); break; case NPC_WINDSOR: SetEscortPaused(false); break; case SAY_WINDSOR_BEFORE_KEEP: m_bIsKeepReady = true; m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); break; case NPC_GUARD_CITY: SetEscortPaused(false); break; case NPC_WRYNN: // Remove npc flags during the event if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) pOnyxia->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); if (Creature* pWrynn = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_WRYNN)) pWrynn->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) pBolvar->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); break; case SAY_BOLVAR_KEEP_2: if (Creature* pWrynn = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_WRYNN)) { pWrynn->SetWalk(false); pWrynn->ForcedDespawn(15000); pWrynn->GetMotionMaster()->MovePoint(0, aMoveLocations[6][0], aMoveLocations[6][1], aMoveLocations[6][2]); // Store all the nearby guards, in order to transform them into Onyxia guards std::list<Creature*> lGuardsList; GetCreatureListWithEntryInGrid(lGuardsList, pWrynn, NPC_GUARD_ROYAL, 25.0f); for (std::list<Creature*>::const_iterator itr = lGuardsList.begin(); itr != lGuardsList.end(); ++itr) m_lRoyalGuardsGuidList.push_back((*itr)->GetObjectGuid()); } break; case SPELL_WINDSOR_READ: DoCastSpellIfCan(m_creature, SPELL_WINDSOR_READ); break; case EMOTE_BOLVAR_GASP: if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) { pOnyxia->UpdateEntry(NPC_LADY_ONYXIA); if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) pBolvar->SetFacingToObject(pOnyxia); } break; case SAY_PRESTOR_KEEP_9: if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) { pBolvar->SetWalk(false); pBolvar->GetMotionMaster()->MovePoint(0, aMoveLocations[7][0], aMoveLocations[7][1], aMoveLocations[7][2]); } break; case SAY_BOLVAR_KEEP_10: if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) { if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) { pBolvar->SetFacingToObject(pOnyxia); DoScriptText(EMOTE_PRESTOR_LAUGH, pOnyxia); } } break; case SAY_PRESTOR_KEEP_11: for (GuidList::const_iterator itr = m_lRoyalGuardsGuidList.begin(); itr != m_lRoyalGuardsGuidList.end(); ++itr) { if (Creature* pGuard = m_creature->GetMap()->GetCreature(*itr)) { if (!pGuard->isAlive()) continue; pGuard->UpdateEntry(NPC_GUARD_ONYXIA); DoScriptText(EMOTE_GUARD_TRANSFORM, pGuard); if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) pGuard->AI()->AttackStart(pBolvar); } } m_uiGuardCheckTimer = 1000; break; case SPELL_WINDSOR_DEATH: if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) pOnyxia->CastSpell(m_creature, SPELL_WINDSOR_DEATH, false); break; case SAY_WINDSOR_KEEP_12: if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) DoScriptText(SAY_PRESTOR_KEEP_13, pOnyxia); // Fake death m_creature->InterruptNonMeleeSpells(true); m_creature->SetHealth(0); m_creature->StopMoving(); m_creature->ClearComboPointHolders(); m_creature->RemoveAllAurasOnDeath(); m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->ClearAllReactives(); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MoveIdle(); m_creature->SetStandState(UNIT_STAND_STATE_DEAD); break; case SAY_PRESTOR_KEEP_14: if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) { pOnyxia->ForcedDespawn(1000); pOnyxia->HandleEmote(EMOTE_ONESHOT_LIFTOFF); pOnyxia->CastSpell(pOnyxia, SPELL_ONYXIA_DESPAWN, false); } break; case NPC_GUARD_ONYXIA: if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) pBolvar->GetMotionMaster()->MovePoint(0, aMoveLocations[7][0], aMoveLocations[7][1], aMoveLocations[7][2]); break; case NPC_BOLVAR: if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) { pBolvar->SetWalk(true); pBolvar->GetMotionMaster()->MovePoint(0, aMoveLocations[8][0], aMoveLocations[8][1], aMoveLocations[8][2]); } break; case SAY_BOLVAR_KEEP_15: if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) pBolvar->SetStandState(UNIT_STAND_STATE_KNEEL); DoScriptText(SAY_WINDSOR_KEEP_16, m_creature); DoScriptText(EMOTE_WINDSOR_DIE, m_creature); if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid)) pPlayer->GroupEventHappens(QUEST_THE_GREAT_MASQUERADE, m_creature); break; case NPC_GUARD_PATROLLER: // Reset Bolvar and Wrynn if (Creature* pBolvar = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_BOLVAR)) { pBolvar->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); pBolvar->SetStandState(UNIT_STAND_STATE_STAND); pBolvar->GetMotionMaster()->MoveTargetedHome(); } if (Creature* pWrynn = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_WRYNN)) { pWrynn->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); pWrynn->Respawn(); pWrynn->SetWalk(true); pWrynn->GetMotionMaster()->MoveTargetedHome(); } // Onyxia will respawn by herself in about 30 min, so just reset flags if (Creature* pOnyxia = m_pScriptedMap->GetSingleCreatureFromStorage(NPC_PRESTOR)) pOnyxia->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER); // Allow creature to despawn SetEscortPaused(false); break; } }
void UpdateAI(const uint32 uiDiff) override { if (m_bBothDead) // This is the case while fighting Thaddius return; if (m_bFakeDeath) { if (m_uiReviveTimer < uiDiff) { if (Creature* pOther = GetOtherAdd()) { if (boss_thaddiusAddsAI* pOtherAI = dynamic_cast<boss_thaddiusAddsAI*>(pOther->AI())) { if (!pOtherAI->IsCountingDead()) // Raid was to slow to kill the second add Revive(); else { m_bBothDead = true; // Now both adds are counting dead pOtherAI->m_bBothDead = true; // Set both Teslas to overload GuidList lTeslaGUIDList; m_pInstance->GetThadTeslaCreatures(lTeslaGUIDList); for (GuidList::const_iterator itr = lTeslaGUIDList.begin(); itr != lTeslaGUIDList.end(); ++itr) { if (Creature* pTesla = m_pInstance->instance->GetCreature(*itr)) { if (npc_tesla_coilAI* pTeslaAI = dynamic_cast<npc_tesla_coilAI*>(pTesla->AI())) pTeslaAI->SetOverloading(); } } } } } } else m_uiReviveTimer -= uiDiff; return; } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiHoldTimer) // A short timer preventing combat movement after revive { if (m_uiHoldTimer <= uiDiff) { SetCombatMovement(true); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); m_uiHoldTimer = 0; } else m_uiHoldTimer -= uiDiff; } if (m_uiWarStompTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_WARSTOMP) == CAST_OK) m_uiWarStompTimer = urand(8 * IN_MILLISECONDS, 10 * IN_MILLISECONDS); } else m_uiWarStompTimer -= uiDiff; UpdateAddAI(uiDiff); // For Add Specific Abilities DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { DialogueUpdate(uiDiff); if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiBerserkTimer) { if (m_uiBerserkTimer <= uiDiff) { // it's unclear wether it casts Berserk or Ascend to Heavens if (DoCastSpellIfCan(m_creature, SPELL_ASCEND_HEAVENS, CAST_INTERRUPT_PREVIOUS) == CAST_OK) { DoScriptText(SAY_BERSERK, m_creature); m_uiBerserkTimer = 0; } } else m_uiBerserkTimer -= uiDiff; } if (m_uiQuantumStrikeTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_QUANTUM_STRIKE : SPELL_QUANTUM_STRIKE_H) == CAST_OK) m_uiQuantumStrikeTimer = 4000; } else m_uiQuantumStrikeTimer -= uiDiff; if (m_uiBigBangTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_BIG_BANG : SPELL_BIG_BANG_H) == CAST_OK) m_uiBigBangTimer = 90000; } else m_uiBigBangTimer -= uiDiff; if (m_uiCosmicSmashTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_COSMIC_SMASH_SUMMON : SPELL_COSMIC_SMASH_SUMMON_H) == CAST_OK) m_uiCosmicSmashTimer = urand(40000, 50000); } else m_uiCosmicSmashTimer -= uiDiff; if (m_uiPhasePunchTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_PHASE_PUNCH) == CAST_OK) m_uiPhasePunchTimer = 15000; } else m_uiPhasePunchTimer -= uiDiff; // summons are happening only above 20% hp if (!m_bIsLowHealth) { if (m_uiCollapsingStarTimer < uiDiff) { // spawn as many stars as it's needed to a max of 4 uint8 uiMaxStars = MAX_BLACK_HOLES - m_uiActiveStars; if (uiMaxStars) { for (uint8 i = 0; i < uiMaxStars; ++i) DoSpawnCollapsingStar(); DoScriptText(SAY_SUMMON_STAR, m_creature); m_uiCollapsingStarTimer = 60000; } else m_uiCollapsingStarTimer = 10000; } else m_uiCollapsingStarTimer -= uiDiff; if (m_uiConstellationTimer < uiDiff) { // activate as many constelations as it's needed to a max of 3 uint8 uiMaxConstellations = MAX_ACTIVE_CONSTELATIONS - m_uiActiveConstelations; if (uiMaxConstellations) { m_uiConstellationTimer = 50000; for (uint8 i = 0; i < uiMaxConstellations; ++i) ActivateRandomConstellation(); } else m_uiConstellationTimer = 10000; } else m_uiConstellationTimer -= uiDiff; } // switch to second phase if (!m_bIsLowHealth && m_creature->GetHealthPercent() < 20.0f) { DoScriptText(SAY_PHASE_2, m_creature); m_bIsLowHealth = true; // despawn all remaining blackholes and collapsing stars for (GuidList::const_iterator itr = m_lSummonedGuids.begin(); itr != m_lSummonedGuids.end(); ++itr) { if (Creature* pBlackHole = m_creature->GetMap()->GetCreature(*itr)) pBlackHole->ForcedDespawn(); } // spawn new worm holes for (uint8 i = 0; i < MAX_WORM_HOLES; ++i) m_creature->SummonCreature(NPC_WORM_HOLE, afWormHoles[i][0], afWormHoles[i][1], afWormHoles[i][2], 0, TEMPSUMMON_DEAD_DESPAWN, 0); } DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (m_uiVisualTimer) { if (m_uiVisualTimer <= uiDiff) { GuidList lControllersList; if (m_pInstance) m_pInstance->GetJedogaEventControllersList(lControllersList); for (GuidList::const_iterator itr = lControllersList.begin(); itr != lControllersList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) pTemp->CastSpell(m_creature, SPELL_BEAM_VISUAL, false); } if (DoCastSpellIfCan(m_creature, SPELL_LIGHTNING_VISUAL) == CAST_OK) m_uiVisualTimer = 0; } else m_uiVisualTimer -= uiDiff; } if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; // Don't use abilities while sacrificing if (m_bIsSacrificing) return; // Note: this was changed in 3.3.2 and now it does this only once if (m_creature->GetHealthPercent() < 50.0f && !m_bSacrifice) { SetCombatMovement(false); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->GetMotionMaster()->MovePoint(POINT_ID_SACRIFICE, aJedogaLandingLoc[0], aJedogaLandingLoc[1], aJedogaLandingLoc[2]); m_bSacrifice = true; m_bIsSacrificing = true; } if (m_uiThundershockTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_THUNDERSHOCK : SPELL_THUNDERSHOCK_H); m_uiThundershockTimer = 40000; } else m_uiThundershockTimer -= uiDiff; if (m_uiLightningBoltTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_LIGHTNING_BOLT : SPELL_LIGHTNING_BOLT_H); m_uiLightningBoltTimer = 7000; } else m_uiLightningBoltTimer -= uiDiff; if (m_uiCycloneStrikeTimer < uiDiff) { DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CYCLONE_STRIKE : SPELL_CYCLONE_STRIKE_H); m_uiCycloneStrikeTimer = 15000; } else m_uiCycloneStrikeTimer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) override { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bHasFrenzy && m_creature->GetHealthPercent() < 20.0f) { if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK) { DoScriptText(EMOTE_GENERIC_FRENZY, m_creature); m_bHasFrenzy = true; } } // Stinger Spray if (m_uiStingerSprayTimer < uiDiff) { if (DoCastSpellIfCan(m_creature, SPELL_STINGER_SPRAY) == CAST_OK) m_uiStingerSprayTimer = urand(15000, 20000); } else m_uiStingerSprayTimer -= uiDiff; // Paralyze if (m_uiParalyzeTimer < uiDiff) { Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1, SPELL_PARALYZE, SELECT_FLAG_PLAYER); if (!pTarget) pTarget = m_creature->getVictim(); if (DoCastSpellIfCan(pTarget, SPELL_PARALYZE) == CAST_OK) { m_paralyzeTarget = pTarget->GetObjectGuid(); m_uiParalyzeTimer = 15000; // Summon a larva uint8 uiLoc = urand(0, 1); m_creature->SummonCreature(NPC_LARVA, aAyamissSpawnLocs[uiLoc].m_fX, aAyamissSpawnLocs[uiLoc].m_fY, aAyamissSpawnLocs[uiLoc].m_fZ, 0, TEMPSPAWN_TIMED_OOC_OR_CORPSE_DESPAWN, 30000); } } else m_uiParalyzeTimer -= uiDiff; // Summon Swarmer if (m_uiSummonSwarmerTimer < uiDiff) { // The spell which summons these guys was removed in 2.0.1 -> therefore we need to summon them manually at a random location around the area // The summon locations is guesswork - the real location is supposed to be handled by world triggers // There should be about 24 swarmers per min float fX, fY, fZ; for (uint8 i = 0; i < 2; ++i) { m_creature->GetRandomPoint(aAyamissSpawnLocs[2].m_fX, aAyamissSpawnLocs[2].m_fY, aAyamissSpawnLocs[2].m_fZ, 80.0f, fX, fY, fZ); m_creature->SummonCreature(NPC_SWARMER, fX, fY, aAyamissSpawnLocs[2].m_fZ, 0.0f, TEMPSPAWN_CORPSE_DESPAWN, 0); } m_uiSummonSwarmerTimer = 5000; } else m_uiSummonSwarmerTimer -= uiDiff; // All the swarmers attack at a certain period of time if (m_uiSwarmerAttackTimer < uiDiff) { for (GuidList::const_iterator itr = m_lSwarmersGuidList.begin(); itr != m_lSwarmersGuidList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) pTemp->AI()->AttackStart(pTarget); } } m_lSwarmersGuidList.clear(); m_uiSwarmerAttackTimer = 60000; } else m_uiSwarmerAttackTimer -= uiDiff; if (m_uiPhase == PHASE_AIR) { // Start ground phase at 70% of HP if (m_creature->GetHealthPercent() <= 70.0f) { m_uiPhase = PHASE_GROUND; SetCombatMovement(true); m_creature->SetLevitate(false); DoResetThreat(); if (m_creature->getVictim()) m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); } // Poison Stinger if (m_uiPoisonStingerTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_POISON_STINGER) == CAST_OK) m_uiPoisonStingerTimer = urand(2000, 3000); } else m_uiPoisonStingerTimer -= uiDiff; } else { if (m_uiLashTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_LASH) == CAST_OK) m_uiLashTimer = urand(8000, 15000); } else m_uiLashTimer -= uiDiff; if (m_uiTrashTimer < uiDiff) { if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_TRASH) == CAST_OK) m_uiTrashTimer = urand(5000, 7000); } else m_uiTrashTimer -= uiDiff; DoMeleeAttackIfReady(); } }
void UpdateAI(const uint32 uiDiff) override { if (!m_bIsEventStarted || !m_pInstance) return; if (m_uiNextEventTimer <= uiDiff) { switch (m_uiEventStep) { case 0: { break; } case 1: { DoSummonGuards(); m_pInstance->DoUseDoorOrButton(GO_SAURFANG_DOOR, 0, false); if (Creature* pSaurfang = GetSaurfang()) pSaurfang->GetMotionMaster()->MovePoint(0, fPositions[1][0], fPositions[1][1], fPositions[1][2]); NextStep(1000); break; } case 2: { m_pInstance->DoUseDoorOrButton(GO_SAURFANG_DOOR, 0, true); DoScriptText(SAY_INTRO_HORDE_1, m_creature); m_creature->GetMotionMaster()->MovePoint(0, fPositions[7][0], fPositions[7][1], fPositions[7][2]); // move guards int8 n = 8; for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pTmp = m_creature->GetMap()->GetCreature(*i)) pTmp->GetMotionMaster()->MovePoint(0, fPositions[n][0], fPositions[n][1], fPositions[n][2]); ++n; } NextStep(6000); break; } case 3: { if (Creature* pSaurfang = GetSaurfang()) DoScriptText(SAY_INTRO_HORDE_2, pSaurfang); NextStep(13000); break; } case 4: { DoScriptText(SAY_INTRO_HORDE_3, m_creature); NextStep(7000); break; } case 5: { if (Creature* pSaurfang = GetSaurfang()) DoScriptText(SAY_INTRO_HORDE_4, pSaurfang); NextStep(11000); break; } case 6: { DoScriptText(SAY_INTRO_HORDE_5, m_creature); NextStep(16000); break; } case 7: { DoScriptText(SAY_INTRO_HORDE_6, m_creature); NextStep(15000); break; } case 8: { DoScriptText(SAY_INTRO_HORDE_7, m_creature); NextStep(3000); break; } case 9: { if (Creature* pSaurfang = GetSaurfang()) { float x, y, z; pSaurfang->GetPosition(x, y, z); DoScriptText(SAY_INTRO_HORDE_8, m_creature); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(0, x, y, z, false); // move guards for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pTmp = m_creature->GetMap()->GetCreature(*i)) { pTmp->SetWalk(false); pTmp->GetMotionMaster()->MovePoint(0, x, y, z, false); pTmp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); pTmp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); } } pSaurfang->CastSpell(pSaurfang, SPELL_GRIP_OF_AGONY, true); } NextStep(1500); break; } case 10: { float x, y, z; // npcs float in air m_creature->SetWalk(true); m_creature->SetSpeedRate(MOVE_WALK, 3.0f); m_creature->SetLevitate(true); m_creature->GetPosition(x, y, z); m_creature->GetMotionMaster()->MovePoint(0, x, y, z + frand(5.0f, 7.0f)); // move guards for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pTmp = m_creature->GetMap()->GetCreature(*i)) { pTmp->SetWalk(true); pTmp->SetSpeedRate(MOVE_WALK, 3.0f); pTmp->SetLevitate(true); pTmp->GetPosition(x, y, z); pTmp->GetMotionMaster()->MovePoint(0, x, y, z + frand(5.0f, 7.0f)); } } if (Creature* pSaurfang = GetSaurfang()) DoScriptText(SAY_INTRO_HORDE_9, pSaurfang); NextStep(10000); break; } case 11: { if (Creature* pSaurfang = GetSaurfang()) { pSaurfang->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); pSaurfang->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); pSaurfang->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); pSaurfang->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); pSaurfang->SetInCombatWithZone(); } NextStep(); break; } case 12: { // fight is in progress break; } case 13: { m_creature->HandleEmote(EMOTE_ONESHOT_NONE); m_creature->GetMotionMaster()->MoveFall(); // move guards for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pTmp = m_creature->GetMap()->GetCreature(*i)) { pTmp->HandleEmote(EMOTE_ONESHOT_NONE); pTmp->GetMotionMaster()->MoveFall(); } } NextStep(3000); break; } case 14: { m_creature->SetLevitate(false); m_creature->SetSpeedRate(MOVE_WALK, 1.0f); m_creature->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY); for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pGuard = m_creature->GetMap()->GetCreature(*i)) { pGuard->SetLevitate(false); pGuard->SetSpeedRate(MOVE_WALK, 1.0f); pGuard->GetMotionMaster()->MoveFollow(m_creature, frand(2.0f, 5.0f), frand(M_PI_F / 2, 1.5f * M_PI_F)); pGuard->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY); } } NextStep(1000); break; } case 15: { DoScriptText(SAY_OUTRO_HORDE_1, m_creature); m_creature->HandleEmote(EMOTE_ONESHOT_KNEEL); NextStep(3000); break; } case 16: { if (Creature* pSaurfang = GetSaurfang()) { float x, y, z; pSaurfang->GetContactPoint(m_creature, x, y, z, 1.0f); m_creature->GetMotionMaster()->MovePoint(0, x, y, z); } NextStep(0); break; } case 17: { if (Creature* pSaurfang = GetSaurfang()) { // wait until Overlord comes to Deathbringer if (!m_creature->IsWithinDist(pSaurfang, 2.0f)) return; m_creature->StopMoving(); m_creature->SetFacingToObject(pSaurfang); } NextStep(1000); break; } case 18: { if (Creature* pSaurfang = GetSaurfang()) { DoScriptText(SAY_OUTRO_HORDE_2, m_creature); m_creature->HandleEmote(EMOTE_ONESHOT_KNEEL); // doesnt work, invalid target (probably related to strangluating aura problem, maybe factions?) // pSaurfang->CastSpell(m_creature, SPELL_VEHICLE_HARDCODED, true); } NextStep(3000); break; } case 19: { // take deathbringer DoScriptText(SAY_OUTRO_HORDE_3, m_creature); NextStep(11000); break; } case 20: { DoScriptText(SAY_OUTRO_HORDE_4, m_creature); m_creature->GetMotionMaster()->MovePoint(0, fPositions[2][0], fPositions[2][1], fPositions[2][2], false); NextStep(); break; } case 21: { // wait until coming to gunship boarding place if (!m_creature->IsWithinDist2d(fPositions[2][0], fPositions[2][1], 3.0f)) return; for (GuidList::iterator i = m_lGuards.begin(); i != m_lGuards.end(); ++i) { if (Creature* pGuard = m_creature->GetMap()->GetCreature(*i)) pGuard->ForcedDespawn(); } m_creature->ForcedDespawn(); return; } default: break; } } else m_uiNextEventTimer -= uiDiff; }
void JustDidDialogueStep(int32 iEntry) override { switch (iEntry) { case SPELL_AKAMA_SOUL_RETRIEVE: DoCastSpellIfCan(m_creature, SPELL_AKAMA_SOUL_RETRIEVE); break; case EMOTE_ONESHOT_ROAR: m_creature->HandleEmote(EMOTE_ONESHOT_ROAR); break; case SAY_FREE_1: DoSummonBrokenAshtongue(); break; case SAY_BROKEN_FREE_01: if (Creature* pBroken = GetClosestCreatureWithEntry(m_creature, NPC_ASH_BROKEN, 35.0f)) DoScriptText(SAY_BROKEN_FREE_01, pBroken); break; case EMOTE_STATE_KNEEL: for (GuidList::const_iterator itr = m_lBrokenGUIDList.begin(); itr != m_lBrokenGUIDList.end(); ++itr) { if (Creature* pBroken = m_creature->GetMap()->GetCreature(*itr)) pBroken->HandleEmote(EMOTE_STATE_KNEEL); } break; case SAY_BROKEN_FREE_02: for (GuidList::const_iterator itr = m_lBrokenGUIDList.begin(); itr != m_lBrokenGUIDList.end(); ++itr) { if (Creature* pBroken = m_creature->GetMap()->GetCreature(*itr)) DoScriptText(SAY_BROKEN_FREE_02, pBroken); } break; } }
void UpdateAI(const uint32 uiDiff) override { 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) { if (m_pInstance) m_pInstance->SetData(TYPE_DO_GOTH_SUMMON, NPC_UNREL_TRAINEE); m_uiTraineeTimer = 20 * IN_MILLISECONDS; } else m_uiTraineeTimer -= uiDiff; if (m_uiDeathKnightTimer < uiDiff) { if (m_pInstance) m_pInstance->SetData(TYPE_DO_GOTH_SUMMON, NPC_UNREL_DEATH_KNIGHT); m_uiDeathKnightTimer = 25 * IN_MILLISECONDS; } else m_uiDeathKnightTimer -= uiDiff; if (m_uiRiderTimer < uiDiff) { if (m_pInstance) m_pInstance->SetData(TYPE_DO_GOTH_SUMMON, NPC_UNREL_RIDER); m_uiRiderTimer = 30 * IN_MILLISECONDS; } else m_uiRiderTimer -= uiDiff; if (m_uiPhaseTimer < uiDiff) { m_uiPhase = PHASE_STOP_SUMMONING; m_uiPhaseTimer = 27 * 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 = IsInRightSideGothArea(m_creature) ? SPELL_TELEPORT_LEFT : SPELL_TELEPORT_RIGHT; if (DoCastSpellIfCan(m_creature, uiTeleportSpell) == CAST_OK) { m_uiTeleportTimer = 20 * IN_MILLISECONDS; 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 = 0; 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, SPELL_SHADOWBOLT, SELECT_FLAG_IN_LOS)) DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOWBOLT : SPELL_SHADOWBOLT_H); } 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; } }
// function to spawn a random pack of dwarfes void DoSpawnArenaDwarf() { switch (m_uiDwarfIndex) { case 0: // commoners (always in groups of 6-7) { std::vector<Creature*> vBunnies; for (GuidList::const_iterator itr = m_lUpperBunniesGuids.begin(); itr != m_lUpperBunniesGuids.end(); ++itr) { if (Creature* pBunny = m_creature->GetMap()->GetCreature(*itr)) vBunnies.push_back(pBunny); } std::random_shuffle(vBunnies.begin(), vBunnies.end()); uint8 uiMaxCommoners = urand(6, 7); if (uiMaxCommoners > vBunnies.size() - 1) uiMaxCommoners = vBunnies.size(); for (uint8 i = 0; i < uiMaxCommoners; ++i) m_creature->SummonCreature(NPC_DARK_RUNE_COMMONER, vBunnies[i]->GetPositionX(), vBunnies[i]->GetPositionY(), vBunnies[i]->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); break; } case 1: // warbringers (along with champions or evokers) if (Creature* pBunny = SelectRandomUpperBunny()) m_creature->SummonCreature(NPC_DARK_RUNE_WARBRINGER, pBunny->GetPositionX(), pBunny->GetPositionY(), pBunny->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); // warbringers can have another buddy summoned at the same time if (roll_chance_i(75)) { if (Creature* pBunny = SelectRandomUpperBunny()) m_creature->SummonCreature(roll_chance_i(70) ? NPC_DARK_RUNE_CHAMPION : NPC_DARK_RUNE_EVOKER, pBunny->GetPositionX(), pBunny->GetPositionY(), pBunny->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); } break; case 2: // evokers alone if (Creature* pBunny = SelectRandomUpperBunny()) m_creature->SummonCreature(NPC_DARK_RUNE_EVOKER, pBunny->GetPositionX(), pBunny->GetPositionY(), pBunny->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); break; } // get a new index which will be different from the first one uint8 uiNewIndex = (m_uiDwarfIndex + urand(1, 2)) % 3; m_uiDwarfIndex = uiNewIndex; }
void UpdateAI(const uint32 uiDiff) override { if (!SelectHostileTarget()) return; switch (m_Phase) { case PHASE_TRANSITION: if (m_uiPhaseTimer < uiDiff) { // Note: we need to set the display id before casting the transform spell, in order to get the proper animation m_creature->SetDisplayId(DISPLAY_ID_CTHUN_BODY); // Transform and start C'thun phase if (DoCastSpellIfCan(m_creature, SPELL_TRANSFORM) == CAST_OK) { m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoSpawnFleshTentacles(); m_Phase = PHASE_CTHUN; m_uiPhaseTimer = 0; } } else m_uiPhaseTimer -= uiDiff; break; case PHASE_CTHUN: if (m_uiMouthTentacleTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, uint32(0), SELECT_FLAG_IN_LOS)) { // Cast the spell using the target as source pTarget->InterruptNonMeleeSpells(false); pTarget->CastSpell(pTarget, SPELL_MOUTH_TENTACLE, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, m_creature->GetObjectGuid()); m_stomachEnterTargetGuid = pTarget->GetObjectGuid(); m_uiStomachEnterTimer = 3800; m_uiMouthTentacleTimer = urand(13000, 15000); } } else m_uiMouthTentacleTimer -= uiDiff; // Teleport the target to the stomach after a few seconds if (m_uiStomachEnterTimer) { if (m_uiStomachEnterTimer <= uiDiff) { // Check for valid player if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_stomachEnterTargetGuid)) { DoTeleportPlayer(pPlayer, afCthunLocations[2][0], afCthunLocations[2][1], afCthunLocations[2][2], afCthunLocations[2][3]); m_lPlayersInStomachList.push_back(pPlayer->GetObjectGuid()); } m_stomachEnterTargetGuid.Clear(); m_uiStomachEnterTimer = 0; } else m_uiStomachEnterTimer -= uiDiff; } break; case PHASE_CTHUN_WEAKENED: // Handle Flesh Tentacles respawn when the vulnerability spell expires if (m_uiPhaseTimer < uiDiff) { DoSpawnFleshTentacles(); m_uiPhaseTimer = 0; m_Phase = PHASE_CTHUN; } else m_uiPhaseTimer -= uiDiff; break; default: break; } if (m_uiGiantClawTentacleTimer < uiDiff) { // Summon 1 Giant Claw Tentacle every 60 seconds if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, uint32(0), SELECT_FLAG_IN_LOS)) m_creature->SummonCreature(NPC_GIANT_CLAW_TENTACLE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); m_uiGiantClawTentacleTimer = 60000; } else m_uiGiantClawTentacleTimer -= uiDiff; if (m_uiGiantEyeTentacleTimer < uiDiff) { // Summon 1 Giant Eye Tentacle every 60 seconds if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, uint32(0), SELECT_FLAG_IN_LOS)) m_creature->SummonCreature(NPC_GIANT_EYE_TENTACLE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0); m_uiGiantEyeTentacleTimer = 60000; } else m_uiGiantEyeTentacleTimer -= uiDiff; if (m_uiEyeTentacleTimer < uiDiff) { DoDespawnEyeTentacles(); // Spawn 8 Eye Tentacles every 30 seconds float fX, fY, fZ; for (uint8 i = 0; i < MAX_EYE_TENTACLES; ++i) { m_creature->GetNearPoint(m_creature, fX, fY, fZ, 0, 30.0f, M_PI_F / 4 * i); m_creature->SummonCreature(NPC_EYE_TENTACLE, fX, fY, fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0); } m_uiEyeTentacleTimer = 30000; } else m_uiEyeTentacleTimer -= uiDiff; // Note: this should be handled by the maps if (m_uiDigestiveAcidTimer < uiDiff) { // Iterate the Stomach players list and apply the Digesti acid debuff on them every 4 sec for (GuidList::const_iterator itr = m_lPlayersInStomachList.begin(); itr != m_lPlayersInStomachList.end(); ++itr) { if (Player* pPlayer = m_creature->GetMap()->GetPlayer(*itr)) pPlayer->CastSpell(pPlayer, SPELL_DIGESTIVE_ACID, TRIGGERED_OLD_TRIGGERED, nullptr, nullptr, m_creature->GetObjectGuid()); } m_uiDigestiveAcidTimer = 4000; } else m_uiDigestiveAcidTimer -= uiDiff; }
// Wrapper to keep Runic Smash in a distinct function void UpdateRunicSmash(const uint32 uiDiff) { if (!m_bSmashActive) return; if (m_uiSmashUpdateTimer < uiDiff) { // check all the targets which are in a certain distance from the colossus for (GuidList::const_iterator itr = m_lCurrentSmashBunnies.begin(); itr != m_lCurrentSmashBunnies.end(); ++itr) { if (Creature* pBunny = m_creature->GetMap()->GetCreature(*itr)) { // use 12 and 16 as multipliers in order to get the perfect combination if (pBunny->GetPositionY() > m_creature->GetPositionY() + 12 * m_uiSmashIndex && pBunny->GetPositionY() < m_creature->GetPositionY() + 16 * m_uiSmashIndex) pBunny->CastSpell(pBunny, SPELL_RUNIC_SMASH, false); } } ++m_uiSmashIndex; if (m_uiSmashIndex == MAX_RUNIC_SMASH + 1) { m_bSmashActive = false; m_uiSmashIndex = 1; } m_uiSmashUpdateTimer = 250; } else m_uiSmashUpdateTimer -= uiDiff; }