diff options
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 361 |
1 files changed, 178 insertions, 183 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 8bd7173f44f..a9987ae6954 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -223,10 +223,6 @@ ObjectMgr::ObjectMgr(): _voidItemId(1), DBCLocaleIndex(LOCALE_enUS) { - for (uint8 i = 0; i < MAX_CLASSES; ++i) - - for (uint8 j = 0; j < MAX_RACES; ++j) - _playerInfo[j][i] = nullptr; } ObjectMgr* ObjectMgr::instance() @@ -237,31 +233,6 @@ ObjectMgr* ObjectMgr::instance() ObjectMgr::~ObjectMgr() { - for (QuestMap::iterator i = _questTemplates.begin(); i != _questTemplates.end(); ++i) - delete i->second; - - for (PetLevelInfoContainer::iterator i = _petInfoStore.begin(); i != _petInfoStore.end(); ++i) - delete[] i->second; - - for (int race = 0; race < MAX_RACES; ++race) - { - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) - { - if (_playerInfo[race][class_]) - delete[] _playerInfo[race][class_]->levelInfo; - delete _playerInfo[race][class_]; - } - } - - for (CacheVendorItemContainer::iterator itr = _cacheVendorItemStore.begin(); itr != _cacheVendorItemStore.end(); ++itr) - itr->second.Clear(); - - for (DungeonEncounterContainer::iterator itr =_dungeonEncounterStore.begin(); itr != _dungeonEncounterStore.end(); ++itr) - for (DungeonEncounterList::iterator encounterItr = itr->second.begin(); encounterItr != itr->second.end(); ++encounterItr) - delete *encounterItr; - - for (AccessRequirementContainer::iterator itr = _accessRequirementStore.begin(); itr != _accessRequirementStore.end(); ++itr) - delete itr->second; } void ObjectMgr::AddLocaleString(std::string&& value, LocaleConstant localeConstant, std::vector<std::string>& data) @@ -390,7 +361,7 @@ void ObjectMgr::LoadCreatureTemplates() // 69 70 71 72 73 74 75 76 // "RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, " // 77 - // "ScriptName FROM creature_template WHERE entry = ? OR 1 = ?"); + // "ScriptName FROM creature_template WHERE entry = ? OR 1 = ? ORDER BY entry DESC"); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEMPLATE); stmt->setUInt32(0, 0); @@ -403,29 +374,35 @@ void ObjectMgr::LoadCreatureTemplates() return; } - _creatureTemplateStore.reserve(result->GetRowCount()); + uint32 count = 0; + + uint32 const maxCreatureId = (*result)[0].GetUInt32(); + _creatureTemplateStore.resize(maxCreatureId + 1); do { Field* fields = result->Fetch(); LoadCreatureTemplate(fields); - } - while (result->NextRow()); + + ++count; + } while (result->NextRow()); // We load the creature models after loading but before checking LoadCreatureTemplateModels(); // Checking needs to be done after loading because of the difficulty self referencing - for (CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.begin(); itr != _creatureTemplateStore.end(); ++itr) - CheckCreatureTemplate(&itr->second); + for (auto const& creatureTemplate : _creatureTemplateStore) + if (creatureTemplate) + CheckCreatureTemplate(creatureTemplate.get()); - TC_LOG_INFO("server.loading", ">> Loaded %u creature definitions in %u ms", uint32(_creatureTemplateStore.size()), GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u creature definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } void ObjectMgr::LoadCreatureTemplate(Field* fields) { uint32 entry = fields[0].GetUInt32(); - CreatureTemplate& creatureTemplate = _creatureTemplateStore[entry]; + _creatureTemplateStore[entry] = std::make_unique<CreatureTemplate>(); + CreatureTemplate& creatureTemplate = *_creatureTemplateStore[entry].get(); creatureTemplate.Entry = entry; @@ -686,8 +663,8 @@ void ObjectMgr::LoadCreatureScalingData() uint32 entry = fields[0].GetUInt32(); Difficulty difficulty = Difficulty(fields[1].GetUInt8()); - auto itr = _creatureTemplateStore.find(entry); - if (itr == _creatureTemplateStore.end()) + CreatureTemplate const* creatureTemplate = GetCreatureTemplate(entry); + if (!creatureTemplate) { TC_LOG_ERROR("sql.sql", "Creature template (Entry: %u) does not exist but has a record in `creature_template_scaling`", entry); continue; @@ -700,7 +677,7 @@ void ObjectMgr::LoadCreatureScalingData() creatureLevelScaling.DeltaLevelMax = fields[5].GetInt16(); creatureLevelScaling.ContentTuningID = fields[6].GetInt32(); - itr->second.scalingStore[difficulty] = creatureLevelScaling; + const_cast<CreatureTemplate*>(creatureTemplate)->scalingStore[difficulty] = creatureLevelScaling; ++count; } while (result->NextRow()); @@ -3018,13 +2995,17 @@ void ObjectMgr::LoadItemTemplates() uint32 oldMSTime = getMSTime(); uint32 sparseCount = 0; + uint32 const maxItemId = sItemSparseStore.GetNumRows(); + _itemTemplateStore.resize(maxItemId + 1); + for (ItemSparseEntry const* sparse : sItemSparseStore) { ItemEntry const* db2Data = sItemStore.LookupEntry(sparse->ID); if (!db2Data) continue; - ItemTemplate& itemTemplate = _itemTemplateStore[sparse->ID]; + _itemTemplateStore[sparse->ID] = std::make_unique<ItemTemplate>(); + ItemTemplate& itemTemplate = *_itemTemplateStore[sparse->ID].get(); itemTemplate.BasicData = db2Data; itemTemplate.ExtendedData = sparse; @@ -3101,11 +3082,11 @@ void ObjectMgr::LoadItemTemplates() // Load item effects (spells) for (ItemEffectEntry const* effectEntry : sItemEffectStore) { - auto itemItr = _itemTemplateStore.find(effectEntry->ParentItemID); - if (itemItr == _itemTemplateStore.end()) + ItemTemplate const* itemTemplate = GetItemTemplate(effectEntry->ParentItemID); + if (!itemTemplate) continue; - itemItr->second.Effects.push_back(effectEntry); + const_cast<ItemTemplate*>(itemTemplate)->Effects.push_back(effectEntry); } TC_LOG_INFO("server.loading", ">> Loaded %u item templates in %u ms", sparseCount, GetMSTimeDiffToNow(oldMSTime)); @@ -3123,7 +3104,8 @@ void ObjectMgr::LoadItemTemplateAddon() { Field* fields = result->Fetch(); uint32 itemId = fields[0].GetUInt32(); - if (!GetItemTemplate(itemId)) + ItemTemplate* itemTemplate = const_cast<ItemTemplate*>(GetItemTemplate(itemId)); + if (!itemTemplate) { TC_LOG_ERROR("sql.sql", "Item %u specified in `item_template_addon` does not exist, skipped.", itemId); continue; @@ -3136,13 +3118,12 @@ void ObjectMgr::LoadItemTemplateAddon() TC_LOG_ERROR("sql.sql", "Minimum money loot specified in `item_template_addon` for item %u was greater than maximum amount, swapping.", itemId); std::swap(minMoneyLoot, maxMoneyLoot); } - ItemTemplate& itemTemplate = _itemTemplateStore[itemId]; - itemTemplate.FlagsCu = fields[1].GetUInt32(); - itemTemplate.FoodType = fields[2].GetUInt8(); - itemTemplate.MinMoneyLoot = minMoneyLoot; - itemTemplate.MaxMoneyLoot = maxMoneyLoot; - itemTemplate.SpellPPMRate = fields[5].GetFloat(); - itemTemplate.RandomBonusListTemplateId = fields[6].GetUInt32(); + itemTemplate->FlagsCu = fields[1].GetUInt32(); + itemTemplate->FoodType = fields[2].GetUInt8(); + itemTemplate->MinMoneyLoot = minMoneyLoot; + itemTemplate->MaxMoneyLoot = maxMoneyLoot; + itemTemplate->SpellPPMRate = fields[5].GetFloat(); + itemTemplate->RandomBonusListTemplateId = fields[6].GetUInt32(); ++count; } while (result->NextRow()); } @@ -3161,13 +3142,14 @@ void ObjectMgr::LoadItemScriptNames() { Field* fields = result->Fetch(); uint32 itemId = fields[0].GetUInt32(); - if (!GetItemTemplate(itemId)) + ItemTemplate* itemTemplate = const_cast<ItemTemplate*>(GetItemTemplate(itemId)); + if (!itemTemplate) { TC_LOG_ERROR("sql.sql", "Item %u specified in `item_script_names` does not exist, skipped.", itemId); continue; } - _itemTemplateStore[itemId].ScriptId = GetScriptId(fields[1].GetString()); + itemTemplate->ScriptId = GetScriptId(fields[1].GetString()); ++count; } while (result->NextRow()); } @@ -3177,10 +3159,7 @@ void ObjectMgr::LoadItemScriptNames() ItemTemplate const* ObjectMgr::GetItemTemplate(uint32 entry) const { - ItemTemplateContainer::const_iterator itr = _itemTemplateStore.find(entry); - if (itr != _itemTemplateStore.end()) - return &(itr->second); - return nullptr; + return entry < _itemTemplateStore.size() ? _itemTemplateStore[entry].get() : nullptr; } void ObjectMgr::LoadVehicleTemplateAccessories() @@ -3360,21 +3339,19 @@ void ObjectMgr::LoadPetLevelInfo() continue; } - PetLevelInfo*& pInfoMapEntry = _petInfoStore[creature_id]; + auto& pInfoMapEntry = _petInfoStore[creature_id]; if (!pInfoMapEntry) - pInfoMapEntry = new PetLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; + pInfoMapEntry = std::make_unique<PetLevelInfo[]>(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); // data for level 1 stored in [0] array element, ... - PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level-1]; + PetLevelInfo* pLevelInfo = &pInfoMapEntry[current_level - 1]; pLevelInfo->health = fields[2].GetUInt16(); pLevelInfo->mana = fields[3].GetUInt16(); pLevelInfo->armor = fields[9].GetUInt32(); - for (int i = 0; i < MAX_STATS; i++) - { - pLevelInfo->stats[i] = fields[i+4].GetUInt16(); - } + for (uint8 i = 0; i < MAX_STATS; i++) + pLevelInfo->stats[i] = fields[i + 4].GetUInt16(); ++count; } @@ -3383,13 +3360,13 @@ void ObjectMgr::LoadPetLevelInfo() // Fill gaps and check integrity for (PetLevelInfoContainer::iterator itr = _petInfoStore.begin(); itr != _petInfoStore.end(); ++itr) { - PetLevelInfo* pInfo = itr->second; + auto& pInfo = itr->second; // fatal error if no level 1 data if (!pInfo || pInfo[0].health == 0) { TC_LOG_ERROR("sql.sql", "Creature %u does not have pet stats data for Level 1!", itr->first); - exit(1); + ABORT(); } // fill level gaps @@ -3411,11 +3388,11 @@ PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level) if (level > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) level = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); - PetLevelInfoContainer::const_iterator itr = _petInfoStore.find(creature_id); + auto itr = _petInfoStore.find(creature_id); if (itr == _petInfoStore.end()) return nullptr; - return &itr->second[level-1]; // data for level 1 stored in [0] array element, ... + return &itr->second[level - 1]; // data for level 1 stored in [0] array element, ... } void ObjectMgr::PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint32 itemId, int32 count) @@ -3454,7 +3431,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { TC_LOG_ERROR("server.loading", ">> Loaded 0 player create definitions. DB table `playercreateinfo` is empty."); - exit(1); + ABORT(); } else { @@ -3512,7 +3489,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - PlayerInfo* info = new PlayerInfo(); + std::unique_ptr<PlayerInfo> info = std::make_unique<PlayerInfo>(); info->mapId = mapId; info->areaId = areaId; info->positionX = positionX; @@ -3521,7 +3498,7 @@ void ObjectMgr::LoadPlayerInfo() info->orientation = orientation; info->displayId_m = maleModel->DisplayID; info->displayId_f = femaleModel->DisplayID; - _playerInfo[current_race][current_class] = info; + _playerInfo[current_race][current_class] = std::move(info); ++count; } @@ -3553,7 +3530,7 @@ void ObjectMgr::LoadPlayerInfo() if (!characterLoadout->RaceMask.HasRace(raceIndex)) continue; - if (PlayerInfo* playerInfo = _playerInfo[raceIndex][characterLoadout->ChrClassID]) + if (auto& playerInfo = _playerInfo[raceIndex][characterLoadout->ChrClassID]) { for (ItemTemplate const* itemTemplate : *items) { @@ -3666,7 +3643,7 @@ void ObjectMgr::LoadPlayerInfo() if (rcInfo->RaceMask.HasRace(raceIndex)) for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex) if (rcInfo->ClassMask == -1 || ((1 << (classIndex - 1)) & rcInfo->ClassMask)) - if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) + if (auto& info = _playerInfo[raceIndex][classIndex]) info->skills.push_back(rcInfo); TC_LOG_INFO("server.loading", ">> Loaded player create skills in %u ms", GetMSTimeDiffToNow(oldMSTime)); @@ -3714,7 +3691,7 @@ void ObjectMgr::LoadPlayerInfo() { if (classMask == 0 || ((1 << (classIndex - 1)) & classMask)) { - if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) + if (auto& info = _playerInfo[raceIndex][classIndex]) { info->customSpells.push_back(spellId); ++count; @@ -3774,7 +3751,7 @@ void ObjectMgr::LoadPlayerInfo() { if (classMask == 0 || ((1 << (classIndex - 1)) & classMask)) { - if (PlayerInfo* info = _playerInfo[raceIndex][classIndex]) + if (auto& info = _playerInfo[raceIndex][classIndex]) { info->castSpells.push_back(spellId); ++count; @@ -3823,7 +3800,7 @@ void ObjectMgr::LoadPlayerInfo() continue; } - if (PlayerInfo* info = _playerInfo[current_race][current_class]) + if (auto& info = _playerInfo[current_race][current_class]) info->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt16(), fields[3].GetUInt32(), fields[4].GetUInt16())); ++count; @@ -3851,7 +3828,7 @@ void ObjectMgr::LoadPlayerInfo() if (!raceStatsResult) { TC_LOG_ERROR("server.loading", ">> Loaded 0 race stats definitions. DB table `player_racestats` is empty."); - exit(1); + ABORT(); } do @@ -3876,7 +3853,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { TC_LOG_ERROR("server.loading", ">> Loaded 0 level stats definitions. DB table `player_classlevelstats` is empty."); - exit(1); + ABORT(); } uint32 count = 0; @@ -3905,13 +3882,13 @@ void ObjectMgr::LoadPlayerInfo() for (std::size_t race = 0; race < raceStatModifiers.size(); ++race) { - if (PlayerInfo* info = _playerInfo[race][current_class]) + if (auto& info = _playerInfo[race][current_class]) { if (!info->levelInfo) - info->levelInfo = new PlayerLevelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)]; + info->levelInfo = std::make_unique<PlayerLevelInfo[]>(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); PlayerLevelInfo& levelInfo = info->levelInfo[current_level - 1]; - for (int i = 0; i < MAX_STATS; ++i) + for (uint8 i = 0; i < MAX_STATS; ++i) levelInfo.stats[i] = fields[i + 2].GetUInt16() + raceStatModifiers[race].StatModifier[i]; } } @@ -3921,19 +3898,19 @@ void ObjectMgr::LoadPlayerInfo() while (result->NextRow()); // Fill gaps and check integrity - for (int race = 0; race < MAX_RACES; ++race) + for (uint8 race = 0; race < MAX_RACES; ++race) { // skip non existed races if (!sChrRacesStore.LookupEntry(race)) continue; - for (int class_ = 0; class_ < MAX_CLASSES; ++class_) + for (uint8 class_ = 0; class_ < MAX_CLASSES; ++class_) { // skip non existed classes if (!sChrClassesStore.LookupEntry(class_)) continue; - PlayerInfo* info = _playerInfo[race][class_]; + auto& info = _playerInfo[race][class_]; if (!info) continue; @@ -3959,7 +3936,7 @@ void ObjectMgr::LoadPlayerInfo() if (!info->levelInfo || info->levelInfo[0].stats[0] == 0) { TC_LOG_ERROR("sql.sql", "Race %i Class %i Level 1 does not have stats data!", race, class_); - exit(1); + ABORT(); } // fill level gaps @@ -4057,12 +4034,12 @@ void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, Play if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES) return; - PlayerInfo const* pInfo = _playerInfo[race][class_]; + auto const& pInfo = _playerInfo[race][class_]; if (!pInfo) return; if (level <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - *info = pInfo->levelInfo[level-1]; + *info = pInfo->levelInfo[level - 1]; else BuildPlayerLevelInfo(race, class_, level, info); } @@ -4070,10 +4047,10 @@ void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, Play void ObjectMgr::BuildPlayerLevelInfo(uint8 race, uint8 _class, uint8 level, PlayerLevelInfo* info) const { // base data (last known level) - *info = _playerInfo[race][_class]->levelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)-1]; + *info = _playerInfo[race][_class]->levelInfo[sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) - 1]; // if conversion from uint32 to uint8 causes unexpected behaviour, change lvl to uint32 - for (uint8 lvl = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)-1; lvl < level; ++lvl) + for (uint8 lvl = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) - 1; lvl < level; ++lvl) { switch (_class) { @@ -4139,9 +4116,6 @@ void ObjectMgr::LoadQuests() { uint32 oldMSTime = getMSTime(); - // For reload case - for (auto itr = _questTemplates.begin(); itr != _questTemplates.end(); ++itr) - delete itr->second; _questTemplates.clear(); _questTemplatesAutoPush.clear(); _questObjectives.clear(); @@ -4179,13 +4153,18 @@ void ObjectMgr::LoadQuests() "AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, TreasurePickerID, Expansion, ManagedWorldStateID, QuestSessionBonus, " //107 108 109 110 111 112 113 114 115 "LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog" - " FROM quest_template"); + " FROM quest_template ORDER BY ID DESC"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 quests definitions. DB table `quest_template` is empty."); return; } + uint32 const maxQuestId = (*result)[0].GetUInt32(); + _questTemplates.resize(maxQuestId + 1); + + uint32 count = 0; + // create multimap previous quest for each existed quest // some quests can have many previous maps set by NextQuestId in previous quest // for example set of race quests can lead to single not race specific quest @@ -4193,10 +4172,11 @@ void ObjectMgr::LoadQuests() { Field* fields = result->Fetch(); - Quest* newQuest = new Quest(fields); - _questTemplates[newQuest->GetQuestId()] = newQuest; + std::unique_ptr<Quest> newQuest = std::make_unique<Quest>(fields); + _questTemplates[newQuest->GetQuestId()] = std::move(newQuest); + ++count; if (newQuest->IsAutoPush()) - _questTemplatesAutoPush.push_back(newQuest); + _questTemplatesAutoPush.push_back(newQuest.get()); // BROKEN BUT WILL BE FIXED IN THE REVERT CHERRY-PICK } while (result->NextRow()); struct QuestLoaderHelper @@ -4255,9 +4235,11 @@ void ObjectMgr::LoadQuests() Field* fields = result->Fetch(); uint32 questId = fields[0].GetUInt32(); - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - (itr->second->*loader.LoaderFunction)(fields); + if (questId < _questTemplates.size() && _questTemplates[questId]) + { + Quest* const quest = _questTemplates[questId].get(); + (quest->*loader.LoaderFunction)(fields); + } else TC_LOG_ERROR("server.loading", "Table `%s` has data for quest %u but such quest does not exist", loader.TableName, questId); } while (result->NextRow()); @@ -4296,22 +4278,23 @@ void ObjectMgr::LoadQuests() uint32 questId = fields[2].GetUInt32(); // Do not throw error here because error for non existing quest is thrown while loading quest objectives. we do not need duplication - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - itr->second->LoadQuestObjectiveVisualEffect(fields); + Quest const* quest = GetQuestTemplate(questId); + if (quest) + const_cast<Quest*>(quest)->LoadQuestObjectiveVisualEffect(fields); } while (result->NextRow()); } std::map<uint32, uint32> usedMailTemplates; // Post processing - for (QuestMap::iterator iter = _questTemplates.begin(); iter != _questTemplates.end(); ++iter) + for (auto& qinfo : _questTemplates) { - // skip post-loading checks for disabled quests - if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, nullptr)) + if (!qinfo) continue; - Quest* qinfo = iter->second; + // skip post-loading checks for disabled quests + if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, qinfo->GetQuestId(), nullptr)) + continue; // additional quest integrity checks (GO, creature_template and items must be loaded already) @@ -4799,10 +4782,9 @@ void ObjectMgr::LoadQuests() usedMailTemplates.emplace(qinfo->_rewardMailTemplateId, qinfo->GetQuestId()); } - if (qinfo->_nextQuestInChain) + if (uint32 nextQuestInChain = qinfo->_nextQuestInChain) { - auto qNextItr = _questTemplates.find(qinfo->_nextQuestInChain); - if (qNextItr == _questTemplates.end()) + if (nextQuestInChain >= _questTemplates.size() || !_questTemplates[nextQuestInChain]) { TC_LOG_ERROR("sql.sql", "Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work.", qinfo->GetQuestId(), qinfo->_nextQuestInChain, qinfo->_nextQuestInChain); @@ -4886,19 +4868,18 @@ void ObjectMgr::LoadQuests() } // fill additional data stores - if (qinfo->_prevQuestID) + if (uint32 prevQuestId = std::abs(qinfo->_prevQuestID)) { - if (_questTemplates.find(abs(qinfo->GetPrevQuestId())) == _questTemplates.end()) + if (prevQuestId >= _questTemplates.size() || !_questTemplates[prevQuestId]) TC_LOG_ERROR("sql.sql", "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId()); } - if (qinfo->_nextQuestID) + if (uint32 nextQuestId = qinfo->_nextQuestID) { - auto qNextItr = _questTemplates.find(qinfo->_nextQuestID); - if (qNextItr == _questTemplates.end()) + if (nextQuestId >= _questTemplates.size() || !_questTemplates[nextQuestId]) TC_LOG_ERROR("sql.sql", "Quest %d has NextQuestId %u, but no such quest", qinfo->GetQuestId(), qinfo->_nextQuestID); else - qNextItr->second->DependentPreviousQuests.push_back(qinfo->GetQuestId()); + _questTemplates[nextQuestId]->DependentPreviousQuests.push_back(qinfo->GetQuestId()); } if (qinfo->_exclusiveGroup) @@ -4940,7 +4921,7 @@ void ObjectMgr::LoadQuests() if (Quest const* quest = GetQuestTemplate(paragonReputation->QuestID)) const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_REPEATABLE); - TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " quests definitions in %u ms", _questTemplates.size(), GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u quests definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } void ObjectMgr::LoadQuestStartersAndEnders() @@ -5493,10 +5474,14 @@ void ObjectMgr::LoadEventScripts() std::set<uint32> evt_scripts; // Load all possible script entries from gameobjects - GameObjectTemplateContainer const* gotc = sObjectMgr->GetGameObjectTemplates(); - for (GameObjectTemplateContainer::const_iterator itr = gotc->begin(); itr != gotc->end(); ++itr) - if (uint32 eventId = itr->second.GetEventScriptId()) + for (auto const& gameObjectTemplate : _gameObjectTemplateStore) + { + if (!gameObjectTemplate) + continue; + + if (uint32 eventId = gameObjectTemplate->GetEventScriptId()) evt_scripts.insert(eventId); + } // Load all possible script entries from spells for (SpellNameEntry const* spellNameEntry : sSpellNameStore) @@ -5858,7 +5843,7 @@ void ObjectMgr::LoadInstanceEncounters() continue; } - std::map<uint32, std::pair<uint32, DungeonEncounterEntry const*>>::const_iterator itr = dungeonLastBosses.find(lastEncounterDungeon); + auto itr = dungeonLastBosses.find(lastEncounterDungeon); if (lastEncounterDungeon) { if (itr != dungeonLastBosses.end()) @@ -5914,14 +5899,14 @@ void ObjectMgr::LoadInstanceEncounters() if (sDB2Manager.GetMapDifficultyData(dungeonEncounter->MapID, Difficulty(difficulty->ID))) { DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR64(dungeonEncounter->MapID, difficulty->ID)]; - encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); + encounters.push_back(std::make_unique<DungeonEncounter>(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); } } } else { DungeonEncounterList& encounters = _dungeonEncounterStore[MAKE_PAIR64(dungeonEncounter->MapID, dungeonEncounter->DifficultyID)]; - encounters.push_back(new DungeonEncounter(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); + encounters.push_back(std::make_unique<DungeonEncounter>(dungeonEncounter, EncounterCreditType(creditType), creditEntry, lastEncounterDungeon)); } ++count; @@ -6451,6 +6436,11 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt return mountModel.CreatureDisplayID; } +Quest const* ObjectMgr::GetQuestTemplate(uint32 quest_id) const +{ + return quest_id < _questTemplates.size() ? _questTemplates[quest_id].get() : nullptr; +} + void ObjectMgr::LoadGraveyardZones() { uint32 oldMSTime = getMSTime(); @@ -6721,7 +6711,7 @@ AccessRequirement const* ObjectMgr::GetAccessRequirement(uint32 mapid, Difficult { AccessRequirementContainer::const_iterator itr = _accessRequirementStore.find(MAKE_PAIR64(mapid, difficulty)); if (itr != _accessRequirementStore.end()) - return itr->second; + return itr->second.get(); return nullptr; } @@ -6859,13 +6849,7 @@ void ObjectMgr::LoadAccessRequirements() { uint32 oldMSTime = getMSTime(); - if (!_accessRequirementStore.empty()) - { - for (AccessRequirementContainer::iterator itr = _accessRequirementStore.begin(); itr != _accessRequirementStore.end(); ++itr) - delete itr->second; - - _accessRequirementStore.clear(); // need for reload case - } + _accessRequirementStore.clear(); // need for reload case // 0 1 2 3 4 5 6 7 8 9 QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement"); @@ -6898,7 +6882,9 @@ void ObjectMgr::LoadAccessRequirements() uint64 requirement_ID = MAKE_PAIR64(mapid, difficulty); - AccessRequirement* ar = new AccessRequirement(); + auto& ar = _accessRequirementStore[requirement_ID]; + ar = std::make_unique<AccessRequirement>(); + ar->levelMin = fields[2].GetUInt8(); ar->levelMax = fields[3].GetUInt8(); ar->item = fields[4].GetUInt32(); @@ -6954,8 +6940,6 @@ void ObjectMgr::LoadAccessRequirements() ar->achievement = 0; } } - - _accessRequirementStore[requirement_ID] = ar; ++count; } while (result->NextRow()); @@ -7236,9 +7220,12 @@ void ObjectMgr::LoadGameObjectTemplate() { uint32 oldMSTime = getMSTime(); + uint32 const maxdb2GameObjectId = sGameObjectsStore.GetNumRows(); + _gameObjectTemplateStore.resize(maxdb2GameObjectId + 1); for (GameObjectsEntry const* db2go : sGameObjectsStore) { - GameObjectTemplate& go = _gameObjectTemplateStore[db2go->ID]; + _gameObjectTemplateStore[db2go->ID] = std::make_unique<GameObjectTemplate>(); + GameObjectTemplate& go = *_gameObjectTemplateStore[db2go->ID].get(); go.entry = db2go->ID; go.type = db2go->TypeID; go.displayId = db2go->DisplayID; @@ -7258,7 +7245,7 @@ void ObjectMgr::LoadGameObjectTemplate() "Data13, Data14, Data15, Data16, Data17, Data18, Data19, Data20, Data21, Data22, Data23, Data24, Data25, Data26, Data27, Data28, " // 37 38 39 40 41 42 43 44 "Data29, Data30, Data31, Data32, Data33, ContentTuningId, AIName, ScriptName " - "FROM gameobject_template"); + "FROM gameobject_template ORDER BY entry DESC"); if (!result) { @@ -7266,7 +7253,9 @@ void ObjectMgr::LoadGameObjectTemplate() return; } - _gameObjectTemplateStore.reserve(result->GetRowCount()); + uint32 const maxGameObjectId = (*result)[0].GetUInt32(); + if (maxGameObjectId > maxdb2GameObjectId) + _gameObjectTemplateStore.resize(maxGameObjectId + 1); uint32 count = 0; do { @@ -7274,7 +7263,8 @@ void ObjectMgr::LoadGameObjectTemplate() uint32 entry = fields[0].GetUInt32(); - GameObjectTemplate& got = _gameObjectTemplateStore[entry]; + _gameObjectTemplateStore[entry] = std::make_unique<GameObjectTemplate>(); + GameObjectTemplate& got = *_gameObjectTemplateStore[entry].get(); got.entry = entry; got.type = uint32(fields[1].GetUInt8()); got.displayId = fields[2].GetUInt32(); @@ -7934,7 +7924,7 @@ void ObjectMgr::LoadQuestPOI() { uint32 oldMSTime = getMSTime(); - _questPOIStore.clear(); // need for reload case + _questPOIStore.clear(); // need for reload case uint32 count = 0; @@ -8063,13 +8053,15 @@ void ObjectMgr::LoadNPCSpellClickSpells() // all spellclick data loaded, now we check if there are creatures with NPC_FLAG_SPELLCLICK but with no data // NOTE: It *CAN* be the other way around: no spellclick flag but with spellclick data, in case of creature-only vehicle accessories - CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates(); - for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr) + for (auto const& creatureTemplate : _creatureTemplateStore) { - if ((itr->second.npcflag & UNIT_NPC_FLAG_SPELLCLICK) && _spellClickInfoStore.find(itr->second.Entry) == _spellClickInfoStore.end()) + if (!creatureTemplate) + continue; + + if ((creatureTemplate->npcflag & UNIT_NPC_FLAG_SPELLCLICK) && _spellClickInfoStore.find(creatureTemplate->Entry) == _spellClickInfoStore.end()) { - TC_LOG_ERROR("sql.sql", "npc_spellclick_spells: Creature template %u has UNIT_NPC_FLAG_SPELLCLICK but no data in spellclick table! Removing flag", itr->second.Entry); - const_cast<CreatureTemplate*>(&itr->second)->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; + TC_LOG_ERROR("sql.sql", "npc_spellclick_spells: Creature template %u has UNIT_NPC_FLAG_SPELLCLICK but no data in spellclick table! Removing flag", creatureTemplate->Entry); + const_cast<CreatureTemplate*>(creatureTemplate.get())->npcflag &= ~UNIT_NPC_FLAG_SPELLCLICK; } } @@ -8128,7 +8120,7 @@ void ObjectMgr::LoadQuestRelationsHelper(QuestRelations& map, QuestRelationsReve uint32 quest = result->Fetch()[1].GetUInt32(); uint32 poolId = result->Fetch()[2].GetUInt32(); - if (_questTemplates.find(quest) == _questTemplates.end()) + if (quest >= _questTemplates.size() || !_questTemplates[quest]) { TC_LOG_ERROR("sql.sql", "Table `%s`: Quest %u listed for entry %u does not exist.", table.c_str(), quest, id); continue; @@ -8397,7 +8389,7 @@ void ObjectMgr::LoadGameObjectForQuests() _gameObjectForQuestStore.clear(); // need for reload case - if (sObjectMgr->GetGameObjectTemplates()->empty()) + if (_gameObjectTemplateStore.empty()) { TC_LOG_INFO("server.loading", ">> Loaded 0 GameObjects for quests"); return; @@ -8406,42 +8398,43 @@ void ObjectMgr::LoadGameObjectForQuests() uint32 count = 0; // collect GO entries for GO that must activated - GameObjectTemplateContainer const* gotc = sObjectMgr->GetGameObjectTemplates(); - for (GameObjectTemplateContainer::const_iterator itr = gotc->begin(); itr != gotc->end(); ++itr) + for (auto const& gameObjectTemplate : _gameObjectTemplateStore) { - switch (itr->second.type) + if (!gameObjectTemplate) + continue; + + switch (gameObjectTemplate->type) { case GAMEOBJECT_TYPE_QUESTGIVER: - _gameObjectForQuestStore.insert(itr->second.entry); + _gameObjectForQuestStore.insert(gameObjectTemplate->entry); ++count; break; case GAMEOBJECT_TYPE_CHEST: { // scan GO chest with loot including quest items - uint32 loot_id = (itr->second.GetLootId()); - + uint32 lootId = gameObjectTemplate->GetLootId(); // find quest loot for GO - if (itr->second.chest.questID || LootTemplates_Gameobject.HaveQuestLootFor(loot_id)) + if (gameObjectTemplate->chest.questID || LootTemplates_Gameobject.HaveQuestLootFor(lootId)) { - _gameObjectForQuestStore.insert(itr->second.entry); + _gameObjectForQuestStore.insert(gameObjectTemplate->entry); ++count; } break; } case GAMEOBJECT_TYPE_GENERIC: { - if (itr->second.generic.questID > 0) //quests objects + if (gameObjectTemplate->generic.questID > 0) //quests objects { - _gameObjectForQuestStore.insert(itr->second.entry); + _gameObjectForQuestStore.insert(gameObjectTemplate->entry); ++count; } break; } case GAMEOBJECT_TYPE_GOOBER: { - if (itr->second.goober.questID > 0) //quests objects + if (gameObjectTemplate->goober.questID > 0) //quests objects { - _gameObjectForQuestStore.insert(itr->second.entry); + _gameObjectForQuestStore.insert(gameObjectTemplate->entry); ++count; } break; @@ -8607,7 +8600,7 @@ int32 ObjectMgr::GetBaseReputationOf(FactionEntry const* factionEntry, uint8 rac uint32 classMask = 1 << (playerClass - 1); - for (int i = 0; i < 4; i++) + for (uint8 i = 0; i < 4; ++i) { if ((!factionEntry->ReputationClassMask[i] || factionEntry->ReputationClassMask[i] & classMask) && @@ -9022,7 +9015,7 @@ void ObjectMgr::LoadCreatureTrainers() TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " default trainers in %u ms", _creatureDefaultTrainers.size(), GetMSTimeDiffToNow(oldMSTime)); } -int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *skip_vendors) +uint32 ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, std::set<uint32> *skip_vendors) { // find all items from the reference vendor WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_NPC_VENDOR_REF); @@ -9551,14 +9544,16 @@ void ObjectMgr::LoadCreatureClassLevelStats() } while (result->NextRow()); - CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates(); - for (auto itr = ctc->begin(); itr != ctc->end(); ++itr) + for (auto const& creatureTemplate : _creatureTemplateStore) { - std::pair<int16, int16> levels = itr->second.GetMinMaxLevel(); + if (!creatureTemplate) + continue; + + std::pair<int16, int16> levels = creatureTemplate->GetMinMaxLevel(); for (int16 lvl = levels.first; lvl <= levels.second; ++lvl) { - if (_creatureBaseStatsStore.find(MAKE_PAIR16(lvl, itr->second.unit_class)) == _creatureBaseStatsStore.end()) - TC_LOG_ERROR("sql.sql", "Missing base stats for creature class %u level %u", itr->second.unit_class, lvl); + if (_creatureBaseStatsStore.find(MAKE_PAIR16(lvl, creatureTemplate->unit_class)) == _creatureBaseStatsStore.end()) + TC_LOG_ERROR("sql.sql", "Missing base stats for creature class %u level %u", creatureTemplate->unit_class, lvl); } } @@ -9985,11 +9980,7 @@ TerrainSwapInfo const* ObjectMgr::GetTerrainSwapInfo(uint32 terrainSwapId) const GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) const { - GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry); - if (itr != _gameObjectTemplateStore.end()) - return &(itr->second); - - return nullptr; + return entry < _gameObjectTemplateStore.size() ? _gameObjectTemplateStore[entry].get() : nullptr; } GameObjectTemplateAddon const* ObjectMgr::GetGameObjectTemplateAddon(uint32 entry) const @@ -10003,11 +9994,12 @@ GameObjectTemplateAddon const* ObjectMgr::GetGameObjectTemplateAddon(uint32 entr CreatureTemplate const* ObjectMgr::GetCreatureTemplate(uint32 entry) const { - CreatureTemplateContainer::const_iterator itr = _creatureTemplateStore.find(entry); - if (itr != _creatureTemplateStore.end()) - return &(itr->second); + return entry < _creatureTemplateStore.size() ? _creatureTemplateStore[entry].get() : nullptr; +} - return nullptr; +QuestPOIData const* ObjectMgr::GetQuestPOIData(int32 QuestID) +{ + return Trinity::Containers::MapGetValuePtr(_questPOIStore, QuestID); } VehicleTemplate const* ObjectMgr::GetVehicleTemplate(Vehicle* veh) const @@ -10034,7 +10026,7 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con DungeonEncounterList const* ObjectMgr::GetDungeonEncounterList(uint32 mapId, Difficulty difficulty) const { - DungeonEncounterContainer::const_iterator itr = _dungeonEncounterStore.find(MAKE_PAIR64(mapId, difficulty)); + auto itr = _dungeonEncounterStore.find(MAKE_PAIR64(mapId, difficulty)); if (itr != _dungeonEncounterStore.end()) return &itr->second; return nullptr; @@ -10046,10 +10038,10 @@ PlayerInfo const* ObjectMgr::GetPlayerInfo(uint32 race, uint32 class_) const return nullptr; if (class_ >= MAX_CLASSES) return nullptr; - PlayerInfo const* info = _playerInfo[race][class_]; + auto const& info = _playerInfo[race][class_]; if (!info) return nullptr; - return info; + return info.get(); } void ObjectMgr::LoadRaceAndClassExpansionRequirements() @@ -10359,18 +10351,21 @@ void ObjectMgr::InitializeQueriesData(QueryDataGroup mask) // Initialize Query data for creatures if (mask & QUERY_DATA_CREATURES) - for (auto& creaturePair : _creatureTemplateStore) - creaturePair.second.InitializeQueryData(); + for (auto const& creatureTemplate : _creatureTemplateStore) + if (creatureTemplate) + creatureTemplate->InitializeQueryData(); // Initialize Query Data for gameobjects if (mask & QUERY_DATA_GAMEOBJECTS) - for (auto& gameobjectPair : _gameObjectTemplateStore) - gameobjectPair.second.InitializeQueryData(); + for (auto const& gameObjectTemplate : _gameObjectTemplateStore) + if (gameObjectTemplate) + gameObjectTemplate->InitializeQueryData(); // Initialize Query Data for quests if (mask & QUERY_DATA_QUESTS) - for (auto& questPair : _questTemplates) - questPair.second->InitializeQueryData(); + for (auto const& questTemplate : _questTemplates) + if (questTemplate) + questTemplate->InitializeQueryData(); // Initialize Quest POI data if (mask & QUERY_DATA_POIS) |