void ShatterGolems() { if (m_lGolemGUIDList.empty()) return; uint8 m_uiBrittleGolemsCount = 0; for(GUIDList::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { // only shatter brittle golems if (pTemp->GetEntry() == NPC_BRITTLE_GOLEM) { pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SHATTER : SPELL_SHATTER_H, true); ++m_uiBrittleGolemsCount; } } } // If shattered more than 4 golems mark achiev as failed if (m_uiBrittleGolemsCount > MAX_ACHIEV_GOLEMS) { if (m_pInstance) m_pInstance->SetData(TYPE_VOLKHAN, SPECIAL); } }
void Reset() { // Remove immunity m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false); m_uiPhase = PHASE_SPEECH; m_uiSpeech = 1; m_uiTraineeTimer = 24 * IN_MILLISECONDS; m_uiDeathKnightTimer = 74 * IN_MILLISECONDS; m_uiRiderTimer = 134 * IN_MILLISECONDS; m_uiTeleportTimer = urand(30000, 45000); // Teleport every 30-45 seconds. m_uiShadowboltTimer = 2 * IN_MILLISECONDS; m_uiHarvestSoulTimer = 2500; m_uiPhaseTimer = 3 * MINUTE * IN_MILLISECONDS + 44 * IN_MILLISECONDS; // last summon at 3:44 - Teleport down at 4:34 m_uiControlZoneTimer = urand(120 * IN_MILLISECONDS, 150 * IN_MILLISECONDS); m_uiSpeechTimer = 1 * IN_MILLISECONDS; // Despawn Adds for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); itr++) { if (Creature* pCreature = m_creature->GetMap()->GetCreature(*itr)) pCreature->ForcedDespawn(); } m_lSummonedAddGuids.clear(); m_lTraineeSummonPosGuids.clear(); m_lDeathKnightSummonPosGuids.clear(); m_lRiderSummonPosGuids.clear(); }
// Wrapper to despawn the Singularities and Darkness on death or on evade void DespawnSummonedCreatures() { for (GUIDList::const_iterator itr = m_lSummonedCreaturesList.begin(); itr != m_lSummonedCreaturesList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) pTemp->ForcedDespawn(); } }
// Small Helper-function static void GetValidNPCsOfList(Map* pMap, GUIDList& lGUIDs, std::list<Creature*>& lNPCs) { lNPCs.clear(); for (GUIDList::const_iterator itr = lGUIDs.begin(); itr != lGUIDs.end(); ++itr) { if (Creature* pMob = pMap->GetCreature(*itr)) lNPCs.push_back(pMob); } }
// Unsummon Majordomo adds void UnsummonMajordomoAdds() { for (GUIDList::const_iterator itr = m_luiMajordomoAddsGUIDs.begin(); itr != m_luiMajordomoAddsGUIDs.end(); ++itr) { if (Creature* pAdd = m_creature->GetMap()->GetCreature(*itr)) if (pAdd->IsTemporarySummon()) ((TemporarySummon*)pAdd)->UnSummon(); } m_luiMajordomoAddsGUIDs.clear(); }
void ShatterRemainingCrystals() { if (m_lCrystalGuids.empty()) return; for (GUIDList::const_iterator itr = m_lCrystalGuids.begin(); itr != m_lCrystalGuids.end(); ++itr) { //Creature* pCrystal = m_creature->GetMap()->GetCreature(FelCrystals[i]); Creature* pCrystal = m_creature->GetMap()->GetCreature(*itr); if (pCrystal && pCrystal->isAlive()) pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } }
void JustReachedHome() { for(GUIDList::const_iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr) { if (*itr == m_creature->GetObjectGuid()) continue; if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr)) { if (pBuddy->isDead()) pBuddy->Respawn(); } } }
void DespawnGolems() { if (m_lGolemGUIDList.empty()) return; for(GUIDList::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) { if (pTemp->isAlive()) pTemp->ForcedDespawn(); } } }
void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); if (m_pInstance) { m_pInstance->SetData(TYPE_SELIN, IN_PROGRESS); if (m_lCrystalGuids.empty()) { // Get and output crystals m_pInstance->GetFelCrystalList(m_lCrystalGuids); for (GUIDList::const_iterator itr = m_lCrystalGuids.begin(); itr != m_lCrystalGuids.end(); ++itr) debug_log("SSC: Selin: Added Fel Crystal %s to list", ObjectGuid(*itr).GetString().c_str()); } } }
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 instance_molten_core::DoHandleAdds(GUIDList &luiAddsGUIDs, bool bRespawn /*=true*/) { if (luiAddsGUIDs.empty()) return; for (GUIDList::const_iterator itr = luiAddsGUIDs.begin(); itr != luiAddsGUIDs.end(); ++itr) { if (Creature* pAdd = instance->GetCreature(*itr)) { // Respawn dead mobs (or corpses) if (bRespawn && !pAdd->isAlive()) pAdd->Respawn(); // Kill adds else if (!bRespawn) pAdd->DealDamage(pAdd, pAdd->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } } }
void DespawnOrKillAdds(bool bDespawn) { for (GUIDList::const_iterator itr = m_lSummonedAddGuids.begin(); itr != m_lSummonedAddGuids.end(); ++itr) { if (Creature* pAdd = m_creature->GetMap()->GetCreature(*itr)) { if (bDespawn) pAdd->ForcedDespawn(); else { pAdd->SetDeathState(JUST_DIED); pAdd->SetHealth(0); } } } m_lSummonedAddGuids.clear(); }
void JustDied(Unit* pKiller) { 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(); }
void JustReachedHome() { if (m_pInstance) { m_pInstance->SetData(TYPE_SELIN, FAIL); for (GUIDList::const_iterator itr = m_lCrystalGuids.begin(); itr != m_lCrystalGuids.end(); ++itr) { if (Creature* pCrystal = m_creature->GetMap()->GetCreature(*itr)) { if (!pCrystal->isAlive()) pCrystal->Respawn(); // Let MaNGOS handle setting death state, etc. // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here. pCrystal->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } } } }
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() { 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 InitSentinelsNear(Unit* pTarget) { if (!m_lAssistList.empty()) { for(GUIDList::const_iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr) { if (*itr == m_creature->GetObjectGuid()) continue; if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr)) { if (pBuddy->isAlive()) pBuddy->AI()->AttackStart(pTarget); } } return; } std::list<Creature*> lAssistList; GetCreatureListWithEntryInGrid(lAssistList, m_creature, m_creature->GetEntry(), 80.0f); if (lAssistList.empty()) return; for(std::list<Creature*>::iterator iter = lAssistList.begin(); iter != lAssistList.end(); ++iter) { m_lAssistList.push_back((*iter)->GetObjectGuid()); if ((*iter)->GetObjectGuid() == m_creature->GetObjectGuid()) continue; (*iter)->AI()->AttackStart(pTarget); } if (m_lAssistList.size() != MAX_BUDDY) error_log("SSC: npc_anubisath_sentinel found too few/too many buddies, expected %u.", MAX_BUDDY); }
void SelectNearestCrystal() { if (m_lCrystalGuids.empty()) return; m_crystalGuid.Clear(); Creature* pCrystal = NULL; Creature* pCrystalChosen = NULL; for (GUIDList::const_iterator itr = m_lCrystalGuids.begin(); itr != m_lCrystalGuids.end(); ++itr) { pCrystal = m_creature->GetMap()->GetCreature(*itr); if (pCrystal && pCrystal->isAlive()) { // select nearest if (!pCrystalChosen || m_creature->GetDistanceOrder(pCrystal, pCrystalChosen, false)) { m_crystalGuid = pCrystal->GetObjectGuid(); pCrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell. } } } if (pCrystalChosen) { DoScriptText(SAY_ENERGY, m_creature); DoScriptText(EMOTE_CRYSTAL, m_creature); pCrystalChosen->CastSpell(pCrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true); float x, y, z; // coords that we move to, close to the crystal. pCrystalChosen->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius(), CONTACT_DISTANCE); m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, x, y, z); m_bDrainingCrystal = true; } }
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() || m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) return; if (m_uiMark_Count >= 100) if (m_uiEnrage_Timer < uiDiff) { m_creature->InterruptNonMeleeSpells(false); DoCast(m_creature, SPELL_BERSERK, true); m_uiEnrage_Timer = 300000; } else m_uiEnrage_Timer -= uiDiff; // Mark of Blaumeux if (m_uiMark_Timer < uiDiff) { DoCastSpellIfCan(m_creature,SPELL_MARK_OF_BLAUMEUX,CAST_TRIGGERED); m_uiMark_Timer = 15000; m_uiMark_Count++; } else m_uiMark_Timer -= uiDiff; // Shield Wall - All 4 horsemen will shield wall at 50% hp and 20% hp for 20 seconds if (m_bShieldWall1 && m_creature->GetHealthPercent() < 50.0f) { if (m_bShieldWall1) { DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); m_bShieldWall1 = false; } } else if (m_bShieldWall2 && m_creature->GetHealthPercent() < 20.0f) { if (m_bShieldWall2) { DoCastSpellIfCan(m_creature,SPELL_SHIELDWALL); m_bShieldWall2 = false; } } // Void Zone if (m_uiVoidZone_Timer < uiDiff) { // get random player in 45yard range (maybe this can be done easier?) ThreatList const& tList = m_creature->getThreatManager().getThreatList(); if(!tList.empty()) { GUIDList lClosePlayerList; lClosePlayerList.clear(); for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr) if(Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid())) if (m_creature->GetDistance2d(pUnit) < 45.f) lClosePlayerList.push_back(pUnit->GetGUID()); if(!lClosePlayerList.empty()) { GUIDList::iterator i = lClosePlayerList.begin(); advance(i, (rand() % lClosePlayerList.size())); if(Player* pTarget = m_creature->GetMap()->GetPlayer(*i)) DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_VOIDZONE : H_SPELL_VOIDZONE, CAST_TRIGGERED); } } m_uiVoidZone_Timer = 12000; } else m_uiVoidZone_Timer -= uiDiff; if (m_uiShadowBolt_Timer < uiDiff) { // cast on closest player ThreatList const& tList = m_creature->getThreatManager().getThreatList(); if (!tList.empty()) { Unit* pTarget = m_creature->GetMap()->GetUnit((*tList.begin())->getUnitGuid()); for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr) if (Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid())) if (pTarget && m_creature->GetDistance2d(pUnit) < m_creature->GetDistance2d(pTarget)) pTarget = pUnit; if (pTarget && m_creature->GetDistance2d(pTarget)< 45.0f) DoCast(pTarget, m_bIsRegularMode ? SPELL_SHADOW_BOLT : H_SPELL_SHADOW_BOLT, true); else DoCast(m_creature, SPELL_UNYIELDING_PAIN, true); } m_uiShadowBolt_Timer = 2000; } else m_uiShadowBolt_Timer -= uiDiff; DoMeleeAttackIfReady(); }
void UpdateAI(const uint32 uiDiff) { 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; } /* Doesn't happen in wotlk version any more 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(); }