// Function to search for new rookery egg in range void DoFindNewEgg() { GameObjectList lEggsInRange; GetGameObjectListWithEntryInGrid(lEggsInRange, m_creature, GO_ROOKERY_EGG, 20.0f); if (lEggsInRange.empty()) // No GO found return; lEggsInRange.sort(ObjectDistanceOrder(m_creature)); GameObject* pNearestEgg = nullptr; // Always need to find new ones for (GameObjectList::const_iterator itr = lEggsInRange.begin(); itr != lEggsInRange.end(); ++itr) { if (!((*itr)->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE))) { pNearestEgg = *itr; break; } } if (!pNearestEgg) return; float fX, fY, fZ; pNearestEgg->GetContactPoint(m_creature, fX, fY, fZ, 1.0f); m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, fX, fY, fZ); m_bIsMovementActive = true; }
void SummonAdds(bool bRightSide, uint32 uiSummonEntry) { std::list<Creature*> lSummonList; m_pInstance->GetGothSummonPointCreatures(lSummonList, bRightSide); if (lSummonList.empty()) return; uint8 uiCount = 2; switch(uiSummonEntry) { case NPC_UNREL_TRAINEE: lSummonList.sort(ObjectDistanceOrder(m_creature)); break; case NPC_UNREL_DEATH_KNIGHT: case NPC_UNREL_RIDER: uiCount = 1; lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); break; } for(std::list<Creature*>::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) { if (uiCount == 0) break; m_creature->SummonCreature(uiSummonEntry, (*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); --uiCount; } }
bool CanUseFingerOfDeath() { // First we check if our current victim is in melee range or not. Unit* victim = m_creature->getVictim(); if (victim && m_creature->IsWithinDistInMap(victim, m_creature->GetAttackDistance(victim))) return false; std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList(); if (m_threatlist.empty()) return false; std::list<Unit*> targets; std::list<HostilReference*>::iterator itr = m_threatlist.begin(); for(; itr != m_threatlist.end(); ++itr) { Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); if (pUnit && pUnit->isAlive()) targets.push_back(pUnit); } if (targets.empty()) return false; targets.sort(ObjectDistanceOrder(m_creature)); Unit* target = targets.front(); if (target) { if (!m_creature->IsWithinDistInMap(target, m_creature->GetAttackDistance(target))) return true; // Cast Finger of Death else // This target is closest, he is our new tank m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim())); } return false; }
// Function to search for new tubber in range void DoFindNewTubber() { std::list<GameObject*> lTubbersInRange; GetGameObjectListWithEntryInGrid(lTubbersInRange, m_creature, GO_BLUELEAF_TUBBER, 40.0f); if (lTubbersInRange.empty()) return; lTubbersInRange.sort(ObjectDistanceOrder(m_creature)); GameObject* pNearestTubber = nullptr; // Always need to find new ones for (std::list<GameObject*>::const_iterator itr = lTubbersInRange.begin(); itr != lTubbersInRange.end(); ++itr) { if (!(*itr)->isSpawned() && (*itr)->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND) && (*itr)->IsWithinLOSInMap(m_creature)) { pNearestTubber = *itr; break; } } if (!pNearestTubber) return; m_targetTubberGuid = pNearestTubber->GetObjectGuid(); float fX, fY, fZ; pNearestTubber->GetContactPoint(m_creature, fX, fY, fZ); m_creature->GetMotionMaster()->MovePoint(1, fX, fY, fZ); m_bIsMovementActive = true; }
uint64 SelectNearbyShallowGrave() { Unit *searcher = instance->GetUnit(ObjectGuid(m_uiGraveyardSearcherGuid)); // Get the list of usable graves (not used already by players) std::list<GameObject*> lGravesInRange; for (GuidList::const_iterator itr = m_lShallowGravesGuidList.begin(); itr != m_lShallowGravesGuidList.end(); ++itr) { GameObject* pGo = searcher->GetMap()->GetGameObject(*itr); // Go spawned and no looting in process if (pGo && pGo->isSpawned() && pGo->getLootState() == GO_READY) { lGravesInRange.push_back(pGo); } } if (lGravesInRange.empty()) { return 0; } // Sort the graves lGravesInRange.sort(ObjectDistanceOrder(searcher)); return (*lGravesInRange.begin())->GetObjectGuid().GetRawValue(); }
void UpdateAI(const uint32 uiDiff) override { if (m_uiStartTimer) { if (m_uiStartTimer <= uiDiff) { // get all the ogres in range std::list<Creature*> lOgreList; for (uint8 i = 0; i < countof(aOgreEntries); ++i) GetCreatureListWithEntryInGrid(lOgreList, m_creature, aOgreEntries[i], 30.0f); if (lOgreList.empty()) { m_uiStartTimer = 5000; return; } // sort by distance and get only the closest lOgreList.sort(ObjectDistanceOrder(m_creature)); std::list<Creature*>::const_iterator ogreItr = lOgreList.begin(); Creature* pOgre = NULL; do { if ((*ogreItr)->isAlive() && !(*ogreItr)->HasAura(SPELL_INTOXICATION)) pOgre = *ogreItr; ++ogreItr; } while (!pOgre && ogreItr != lOgreList.end()); if (!pOgre) { m_uiStartTimer = 5000; return; } // Move ogre to the point float fX, fY, fZ; pOgre->GetMotionMaster()->MoveIdle(); pOgre->SetWalk(false, true); m_creature->GetContactPoint(pOgre, fX, fY, fZ); pOgre->GetMotionMaster()->MovePoint(0, fX, fY, fZ); switch (urand(0, 2)) { case 0: DoScriptText(SAY_BREW_1, pOgre); break; case 1: DoScriptText(SAY_BREW_2, pOgre); break; case 2: DoScriptText(SAY_BREW_3, pOgre); break; } m_selectedOgreGuid = pOgre->GetObjectGuid(); m_uiStartTimer = 0; m_bHasValidOgre = true; } else m_uiStartTimer -= uiDiff; } }
void CastFixate() { ThreatList const& tList = m_creature->getThreatManager().getThreatList(); if (tList.empty()) return; // No point continuing if empty threatlist. std::list<Unit*> targets; for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr) { Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid()); // Only alive players if (pUnit && pUnit->isAlive() && (pUnit->GetTypeId() == TYPEID_PLAYER)) targets.push_back(pUnit); } if (targets.empty()) return; // No targets added for some reason. No point continuing. targets.sort(ObjectDistanceOrder(m_creature)); // Sort players by distance. targets.resize(1); // Only need closest target. Unit* target = targets.front(); // Get the first target. // Add threat equivalent to threat on victim. m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim())); DoCastSpellIfCan(target, SPELL_FIXATE); }
void UpdateAI(const uint32 uiDiff) override { if (m_uiStartTimer) { if (m_uiStartTimer <= uiDiff) { // get all the bats list in range; note: this will compare the 2D distance std::list<Creature*> lBatsList; GetCreatureListWithEntryInGrid(lBatsList, m_creature, NPC_DARKCLAW_BAT, 10.0f); if (lBatsList.empty()) { m_uiStartTimer = 5000; return; } // sort by distance and get only the closest lBatsList.sort(ObjectDistanceOrder(m_creature)); std::list<Creature*>::const_iterator batItr = lBatsList.begin(); Creature* pBat = NULL; do { // check for alive and out of combat only if ((*batItr)->isAlive() && !(*batItr)->getVictim()) pBat = *batItr; ++batItr; } while (!pBat && batItr != lBatsList.end()); if (!pBat) { m_uiStartTimer = 5000; return; } // Move bat to the point float fX, fY, fZ; pBat->SetWalk(false); pBat->GetMotionMaster()->Clear(); m_creature->GetContactPoint(pBat, fX, fY, fZ); pBat->GetMotionMaster()->MovePoint(0, fX, fY, fZ); m_selectedBatGuid = pBat->GetObjectGuid(); m_uiStartTimer = 0; m_bHasValidBat = true; } else m_uiStartTimer -= uiDiff; } }
void PrepareSummonPlaces() { std::list<Creature*> lSummonList; m_pInstance->GetGothSummonPointCreatures(lSummonList, true); if (lSummonList.empty()) { return; } // Trainees and Rider uint8 index = 0; uint8 uiTraineeCount = 3; lSummonList.sort(ObjectDistanceOrder(m_creature)); for (std::list<Creature*>::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) { if (*itr) { if (uiTraineeCount == 0) { break; } if (index == 1) { m_lRiderSummonPosGuids.push_back((*itr)->GetObjectGuid()); } else { m_lTraineeSummonPosGuids.push_back((*itr)->GetObjectGuid()); --uiTraineeCount; } index++; } } // DeathKnights uint8 uiDeathKnightCount = 2; lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); for (std::list<Creature*>::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) { if (*itr) { if (uiDeathKnightCount == 0) { break; } m_lDeathKnightSummonPosGuids.push_back((*itr)->GetObjectGuid()); --uiDeathKnightCount; } } }
// 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 SetMyForge() { std::list<GameObject *> lGOList; uint32 uiGOBellow = 0; uint32 uiGOFire = 0; for (uint8 i = 0; i < MAX_FORGE; ++i) { switch(i) { case 0: uiGOBellow = GO_BELLOW_1; break; case 1: uiGOBellow = GO_BELLOW_2; break; case 2: uiGOBellow = GO_BELLOW_3; break; } if (GameObject* pGOTemp = m_pInstance->GetSingleGameObjectFromStorage(uiGOBellow)) lGOList.push_back(pGOTemp); } if (!lGOList.empty()) { if (lGOList.size() != MAX_FORGE) error_log("SSC: mob_dragonflayer_forge_master expected %u in lGOList, but does not match.", MAX_FORGE); lGOList.sort(ObjectDistanceOrder(m_creature)); if (lGOList.front()->getLootState() == GO_READY) lGOList.front()->UseDoorOrButton(DAY); else if (lGOList.front()->getLootState() == GO_ACTIVATED) lGOList.front()->ResetDoorOrButton(); switch(lGOList.front()->GetEntry()) { case GO_BELLOW_1: uiGOFire = GO_FORGEFIRE_1; m_uiForgeEncounterId = TYPE_BELLOW_1; break; case GO_BELLOW_2: uiGOFire = GO_FORGEFIRE_2; m_uiForgeEncounterId = TYPE_BELLOW_2; break; case GO_BELLOW_3: uiGOFire = GO_FORGEFIRE_3; m_uiForgeEncounterId = TYPE_BELLOW_3; break; } if (GameObject* pGOTemp = m_pInstance->GetSingleGameObjectFromStorage(uiGOFire)) { if (pGOTemp->getLootState() == GO_READY) pGOTemp->UseDoorOrButton(DAY); else if (pGOTemp->getLootState() == GO_ACTIVATED) pGOTemp->ResetDoorOrButton(); } } }
GameObject* SelectNextEgg() { std::list<GameObject*> lEggs; GetGameObjectListWithEntryInGrid(lEggs, me, GO_EGG, DEFAULT_VISIBILITY_INSTANCE); if (lEggs.empty()) debug_log("SD2: boss_marli, no Eggs with the entry %i were found", GO_EGG); else { lEggs.sort(ObjectDistanceOrder(me)); for(std::list<GameObject*>::iterator iter = lEggs.begin(); iter != lEggs.end(); ++iter) { if ((*iter)->GetGoState() == (GO_STATE_READY)) return (*iter); } } return NULL; }
void JustSummoned(Creature* pSummoned) override { if (pSummoned->GetEntry() == NPC_TECAHUNA) { m_tecahunaGuid = pSummoned->GetObjectGuid(); // sort the mummies based on the distance std::list<Creature*> lBunniesInRange; GetCreatureListWithEntryInGrid(lBunniesInRange, m_creature, NPC_MUMMY_EFFECT_BUNNY, 50.0f); lBunniesInRange.sort(ObjectDistanceOrder(pSummoned)); for (std::list<Creature*>::const_iterator itr = lBunniesInRange.begin(); itr != lBunniesInRange.end(); ++itr) m_lImmolationBunnyGuids.push_back((*itr)->GetObjectGuid()); } else if (pSummoned->GetEntry() == NPC_ANCIENT_DRAKKARI_KING) pSummoned->AI()->AttackStart(m_creature); }
Creature* instance_uldaman::GetClosestDwarfNotInCombat(Creature* pSearcher) { std::list<Creature*> lTemp; for (GuidList::const_iterator itr = m_lWardens.begin(); itr != m_lWardens.end(); ++itr) { Creature* pTemp = instance->GetCreature(*itr); if (pTemp && pTemp->IsAlive() && !pTemp->getVictim()) lTemp.push_back(pTemp); } if (lTemp.empty()) return NULL; lTemp.sort(ObjectDistanceOrder(pSearcher)); return lTemp.front(); }
void PrepareSummonPlaces() { CreatureList lSummonList; m_pInstance->GetGothSummonPointCreatures(lSummonList, true); if (lSummonList.empty()) return; // Trainees and Rider uint8 index = 0; uint8 uiTraineeCount = 3; lSummonList.sort(ObjectDistanceOrder(m_creature)); for (auto& itr : lSummonList) { if (itr) { if (uiTraineeCount == 0) break; if (index == 1) m_lRiderSummonPosGuids.push_back(itr->GetObjectGuid()); else { m_lTraineeSummonPosGuids.push_back(itr->GetObjectGuid()); --uiTraineeCount; } index++; } } // DeathKnights uint8 uiDeathKnightCount = 2; lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); for (auto& itr : lSummonList) { if (itr) { if (uiDeathKnightCount == 0) break; m_lDeathKnightSummonPosGuids.push_back(itr->GetObjectGuid()); --uiDeathKnightCount; } } }
// Function to search for new tubber in range void DoFindNewCrystal(Player* pMaster) { GameObjectList lCrystalsInRange; for (unsigned int i : aGOList) { GetGameObjectListWithEntryInGrid(lCrystalsInRange, m_creature, i, 40.0f); // If a crystal was found in range, stop the search here, else try with another GO if (!lCrystalsInRange.empty()) break; } if (lCrystalsInRange.empty()) // Definely no GO found { m_creature->PlayDirectSound(SOUND_GROWL); return; } lCrystalsInRange.sort(ObjectDistanceOrder(m_creature)); GameObject* pNearestCrystal = nullptr; // Always need to find new ones for (GameObjectList::const_iterator itr = lCrystalsInRange.begin(); itr != lCrystalsInRange.end(); ++itr) { if ((*itr)->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND)) { pNearestCrystal = *itr; break; } } if (!pNearestCrystal) { m_creature->PlayDirectSound(SOUND_GROWL); return; } float fX, fY, fZ; pNearestCrystal->GetContactPoint(m_creature, fX, fY, fZ, 3.0f); m_creature->SetWalk(false); m_creature->GetMotionMaster()->MovePoint(1, fX, fY, fZ); m_bIsMovementActive = true; }
Creature* instance_naxxramas::GetClosestAnchorForGoth(Creature* pSource, bool bRightSide) { std::list<Creature* > lList; for (UNORDERED_MAP<uint64, GothTrigger>::iterator itr = m_mGothTriggerMap.begin(); itr != m_mGothTriggerMap.end(); ++itr) { if (!itr->second.bIsAnchorHigh) continue; if (itr->second.bIsRightSide != bRightSide) continue; if (Creature* pCreature = instance->GetCreature(itr->first)) lList.push_back(pCreature); } if (!lList.empty()) { lList.sort(ObjectDistanceOrder(pSource)); return lList.front(); } return NULL; }
Creature* instance_uldaman::GetClosestDwarfNotInCombat(Creature* pSearcher, uint32 uiPhase) { std::list<Creature*> lTemp; for (GuidList::const_iterator itr = m_lWardens.begin(); itr != m_lWardens.end(); ++itr) { Creature* pTemp = instance->GetCreature(*itr); if (pTemp && pTemp->isAlive() && !pTemp->getVictim()) { switch (uiPhase) { case PHASE_ARCHA_1: if (pTemp->GetEntry() != NPC_CUSTODIAN && pTemp->GetEntry() != NPC_HALLSHAPER) continue; break; case PHASE_ARCHA_2: if (pTemp->GetEntry() != NPC_GUARDIAN) continue; break; case PHASE_ARCHA_3: if (pTemp->GetEntry() != NPC_VAULT_WARDER) continue; break; } lTemp.push_back(pTemp); } } if (lTemp.empty()) return NULL; lTemp.sort(ObjectDistanceOrder(pSearcher)); return lTemp.front(); }
void CheckPlayers() { ThreatList const& tList = m_creature->getThreatManager().getThreatList(); if (tList.empty()) return; // No threat list. Don't continue. std::list<Unit*> lTargets; for (ThreatList::const_iterator itr = tList.begin(); itr != tList.end(); ++itr) { Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); if (pUnit && pUnit->isAlive()) lTargets.push_back(pUnit); } lTargets.sort(ObjectDistanceOrder(m_creature)); Unit* pTarget = lTargets.front(); if (pTarget && m_creature->IsWithinDistInMap(pTarget, m_creature->GetAttackDistance(pTarget))) { DoCastSpellIfCan(pTarget, SPELL_ATROPHY); m_creature->AI()->AttackStart(pTarget); } }
void SummonAdds(bool bRightSide, uint32 uiSummonEntry) { std::list<Creature*> lSummonList; m_pInstance->GetGothSummonPointCreatures(lSummonList, bRightSide); if (lSummonList.empty()) return; uint8 uiCount = 2; switch(uiSummonEntry) { case NPC_UNREL_TRAINEE: lSummonList.sort(ObjectDistanceOrder(m_creature)); break; case NPC_UNREL_DEATH_KNIGHT: case NPC_UNREL_RIDER: uiCount = 1; lSummonList.sort(ObjectDistanceOrderReversed(m_creature)); break; } for(std::list<Creature*>::iterator itr = lSummonList.begin(); itr != lSummonList.end(); ++itr) { if (uiCount == 0) break; if(Creature* pAdds = m_creature->SummonCreature(uiSummonEntry, (*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000)) { m_pInstance->lGothikLiveAdds.push_back(pAdds->GetGUID() ); if (Unit* pVictim = m_pInstance->SelectRandomTargetOnSide(true, *pAdds) ) pAdds->AI()->AttackStart(pVictim); --uiCount; } } }
void instance_karazhan::DoPrepareChessEvent() { // Allow all the chess pieces to init start position for (GuidList::const_iterator itr = m_lChessPiecesAlliance.begin(); itr != m_lChessPiecesAlliance.end(); ++itr) { if (Creature* pChessPiece = instance->GetCreature(*itr)) { Creature* pSquare = GetClosestCreatureWithEntry(pChessPiece, NPC_SQUARE_BLACK, 2.0f); if (!pSquare) pSquare = GetClosestCreatureWithEntry(pChessPiece, NPC_SQUARE_WHITE, 2.0f); if (!pSquare) { script_error_log("Instance Karazhan: ERROR Failed to properly load the Chess square for %s.", pChessPiece->GetGuidStr().c_str()); return; } // send event which will prepare the current square pChessPiece->AI()->SendAIEvent(AI_EVENT_CUSTOM_B, pSquare, pChessPiece); } } for (GuidList::const_iterator itr = m_lChessPiecesHorde.begin(); itr != m_lChessPiecesHorde.end(); ++itr) { if (Creature* pChessPiece = instance->GetCreature(*itr)) { Creature* pSquare = GetClosestCreatureWithEntry(pChessPiece, NPC_SQUARE_BLACK, 2.0f); if (!pSquare) pSquare = GetClosestCreatureWithEntry(pChessPiece, NPC_SQUARE_WHITE, 2.0f); if (!pSquare) { script_error_log("Instance Karazhan: ERROR Failed to properly load the Chess square for %s.", pChessPiece->GetGuidStr().c_str()); return; } // send event which will prepare the current square pChessPiece->AI()->SendAIEvent(AI_EVENT_CUSTOM_B, pSquare, pChessPiece); } } // add silence debuff Map::PlayerList const& players = instance->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { if (Player* pPlayer = itr->getSource()) pPlayer->CastSpell(pPlayer, SPELL_GAME_IN_SESSION, TRIGGERED_OLD_TRIGGERED); } m_uiAllianceStalkerCount = 0; m_uiHordeStalkerCount = 0; m_vHordeStalkers.clear(); m_vAllianceStalkers.clear(); // sort stalkers depending on side std::list<Creature*> lStalkers; for (GuidList::const_iterator itr = m_lChessHordeStalkerList.begin(); itr != m_lChessHordeStalkerList.end(); ++itr) { if (Creature* pTemp = instance->GetCreature(*itr)) lStalkers.push_back(pTemp); } if (lStalkers.empty()) { script_error_log("Instance Karazhan: ERROR Failed to properly load the horde side stalkers for the Chess Event."); return; } // get the proper statusBar npc Creature* pStatusBar = instance->GetCreature(m_HordeStatusGuid); if (!pStatusBar) return; lStalkers.sort(ObjectDistanceOrder(pStatusBar)); for (std::list<Creature*>::const_iterator itr = lStalkers.begin(); itr != lStalkers.end(); ++itr) m_vHordeStalkers.push_back((*itr)->GetObjectGuid()); lStalkers.clear(); for (GuidList::const_iterator itr = m_lChessAllianceStalkerList.begin(); itr != m_lChessAllianceStalkerList.end(); ++itr) { if (Creature* pTemp = instance->GetCreature(*itr)) lStalkers.push_back(pTemp); } if (lStalkers.empty()) { script_error_log("Instance Karazhan: ERROR Failed to properly load the alliance side stalkers for the Chess Event."); return; } // get the proper statusBar npc pStatusBar = instance->GetCreature(m_AllianceStatusGuid); if (!pStatusBar) return; lStalkers.sort(ObjectDistanceOrder(pStatusBar)); for (std::list<Creature*>::const_iterator itr = lStalkers.begin(); itr != lStalkers.end(); ++itr) m_vAllianceStalkers.push_back((*itr)->GetObjectGuid()); }