aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Globals/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp217
1 files changed, 125 insertions, 92 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 4a3f3ee4464..03ecfec1d82 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3036,6 +3036,12 @@ uint32 FillMaxDurability(uint32 itemClass, uint32 itemSubClass, uint32 inventory
0.00f, // INVTYPE_RANGEDRIGHT
0.00f, // INVTYPE_QUIVER
0.00f, // INVTYPE_RELIC
+ 0.00f, // INVTYPE_PROFESSION_TOOL
+ 0.00f, // INVTYPE_PROFESSION_GEAR
+ 0.00f, // INVTYPE_EQUIPABLE_SPELL_OFFENSIVE
+ 0.00f, // INVTYPE_EQUIPABLE_SPELL_UTILITY
+ 0.00f, // INVTYPE_EQUIPABLE_SPELL_DEFENSIVE
+ 0.00f, // INVTYPE_EQUIPABLE_SPELL_MOBILITY
};
static float const weaponMultipliers[MAX_ITEM_SUBCLASS_WEAPON] =
@@ -3743,17 +3749,18 @@ PetLevelInfo const* ObjectMgr::GetPetLevelInfo(uint32 creature_id, uint8 level)
void ObjectMgr::PlayerCreateInfoAddItemHelper(uint32 race_, uint32 class_, uint32 itemId, int32 count)
{
- if (!_playerInfo[race_][class_])
+ std::unique_ptr<PlayerInfo>* playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race_), Classes(class_) });
+ if (!playerInfo)
return;
if (count > 0)
- _playerInfo[race_][class_]->item.emplace_back(itemId, count);
+ playerInfo->get()->item.emplace_back(itemId, count);
else
{
if (count < -1)
TC_LOG_ERROR("sql.sql", "Invalid count %i specified on item %u be removed from original player create info (use -1)!", count, itemId);
- PlayerCreateInfoItems& items = _playerInfo[race_][class_]->item;
+ PlayerCreateInfoItems& items = playerInfo->get()->item;
auto erased = std::remove_if(items.begin(), items.end(), [itemId](PlayerCreateInfoItem const& item) { return item.item_id == itemId; });
if (erased == items.end())
@@ -3888,7 +3895,7 @@ void ObjectMgr::LoadPlayerInfo()
introSceneId, current_class, current_race);
}
- _playerInfo[current_race][current_class] = std::move(info);
+ _playerInfo[{ Races(current_race), Classes(current_class) }] = std::move(info);
++count;
}
@@ -3920,8 +3927,10 @@ void ObjectMgr::LoadPlayerInfo()
if (!characterLoadout->RaceMask.HasRace(raceIndex))
continue;
- if (auto& playerInfo = _playerInfo[raceIndex][characterLoadout->ChrClassID])
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(raceIndex), Classes(characterLoadout->ChrClassID) }))
{
+ playerInfo->get()->itemContext = ItemContext(characterLoadout->ItemContext);
+
for (ItemTemplate const* itemTemplate : *items)
{
// BuyCount by default
@@ -3946,7 +3955,7 @@ void ObjectMgr::LoadPlayerInfo()
count = itemTemplate->GetMaxStackSize();
}
- playerInfo->item.emplace_back(itemTemplate->GetId(), count);
+ playerInfo->get()->item.emplace_back(itemTemplate->GetId(), count);
}
}
}
@@ -4033,8 +4042,8 @@ 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 (auto& info = _playerInfo[raceIndex][classIndex])
- info->skills.push_back(rcInfo);
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(raceIndex), Classes(classIndex) }))
+ playerInfo->get()->skills.push_back(rcInfo);
TC_LOG_INFO("server.loading", ">> Loaded player create skills in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
@@ -4081,9 +4090,9 @@ void ObjectMgr::LoadPlayerInfo()
{
if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
{
- if (auto& info = _playerInfo[raceIndex][classIndex])
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(raceIndex), Classes(classIndex) }))
{
- info->customSpells.push_back(spellId);
+ playerInfo->get()->customSpells.push_back(spellId);
++count;
}
// We need something better here, the check is not accounting for spells used by multiple races/classes but not all of them.
@@ -4148,9 +4157,9 @@ void ObjectMgr::LoadPlayerInfo()
{
if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
{
- if (auto& info = _playerInfo[raceIndex][classIndex])
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(raceIndex), Classes(classIndex) }))
{
- info->castSpells[playerCreateMode].push_back(spellId);
+ playerInfo->get()->castSpells[playerCreateMode].push_back(spellId);
++count;
}
}
@@ -4197,8 +4206,8 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
- if (auto& info = _playerInfo[current_race][current_class])
- info->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt16(), fields[3].GetUInt32(), fields[4].GetUInt16()));
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(current_race), Classes(current_class) }))
+ playerInfo->get()->action.push_back(PlayerCreateInfoAction(fields[2].GetUInt16(), fields[3].GetUInt32(), fields[4].GetUInt16()));
++count;
}
@@ -4279,12 +4288,12 @@ void ObjectMgr::LoadPlayerInfo()
for (std::size_t race = 0; race < raceStatModifiers.size(); ++race)
{
- if (auto& info = _playerInfo[race][current_class])
+ if (auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race), Classes(current_class) }))
{
- if (!info->levelInfo)
- info->levelInfo = std::make_unique<PlayerLevelInfo[]>(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
+ if (!playerInfo->get()->levelInfo)
+ playerInfo->get()->levelInfo = std::make_unique<PlayerLevelInfo[]>(sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
- PlayerLevelInfo& levelInfo = info->levelInfo[current_level - 1];
+ PlayerLevelInfo& levelInfo = playerInfo->get()->levelInfo[current_level - 1];
for (uint8 i = 0; i < MAX_STATS; ++i)
levelInfo.stats[i] = fields[i + 2].GetUInt16() + raceStatModifiers[race].StatModifier[i];
}
@@ -4307,8 +4316,8 @@ void ObjectMgr::LoadPlayerInfo()
if (!sChrClassesStore.LookupEntry(class_))
continue;
- auto& info = _playerInfo[race][class_];
- if (!info)
+ auto const& playerInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race), Classes(class_) });
+ if (!playerInfo)
continue;
// skip expansion races if not playing with expansion
@@ -4330,7 +4339,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
// fatal error if no level 1 data
- if (!info->levelInfo || info->levelInfo[0].stats[0] == 0)
+ if (!playerInfo->get()->levelInfo || playerInfo->get()->levelInfo[0].stats[0] == 0)
{
TC_LOG_ERROR("sql.sql", "Race %i Class %i Level 1 does not have stats data!", race, class_);
ABORT();
@@ -4339,10 +4348,10 @@ void ObjectMgr::LoadPlayerInfo()
// fill level gaps
for (uint8 level = 1; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level)
{
- if (info->levelInfo[level].stats[0] == 0)
+ if (playerInfo->get()->levelInfo[level].stats[0] == 0)
{
TC_LOG_ERROR("sql.sql", "Race %i Class %i Level %i does not have stats data. Using stats data of level %i.", race, class_, level + 1, level);
- info->levelInfo[level] = info->levelInfo[level - 1];
+ playerInfo->get()->levelInfo[level] = playerInfo->get()->levelInfo[level - 1];
}
}
}
@@ -4431,12 +4440,12 @@ void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, Play
if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES)
return;
- auto const& pInfo = _playerInfo[race][class_];
+ auto const& pInfo = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race), Classes(class_) });
if (!pInfo)
return;
if (level <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
- *info = pInfo->levelInfo[level - 1];
+ *info = pInfo->get()->levelInfo[level - 1];
else
BuildPlayerLevelInfo(race, class_, level, info);
}
@@ -4444,7 +4453,7 @@ 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 = ASSERT_NOTNULL(Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race), Classes(_class) }))->get()->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)
@@ -4614,7 +4623,19 @@ void ObjectMgr::LoadQuests()
{ "QuestId, RewardMailSenderEntry", "quest_mail_sender", "", "mail sender entries", &Quest::LoadQuestMailSender },
// 0 1 2 3 4 5 6 7 8 9
- { "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }
+ { "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective },
+
+ // 0 1 2 3 4
+ { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_description_conditional", "ORDER BY OrderIndex", "conditional details", &Quest::LoadConditionalConditionalQuestDescription },
+
+ // 0 1 2 3 4
+ { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_request_items_conditional", "ORDER BY OrderIndex", "conditional request items", &Quest::LoadConditionalConditionalRequestItemsText },
+
+ // 0 1 2 3 4
+ { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_offer_reward_conditional", "ORDER BY OrderIndex", "conditional reward", &Quest::LoadConditionalConditionalOfferRewardText },
+
+ // 0 1 2 3 4
+ { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_completion_log_conditional", "ORDER BY OrderIndex", "conditional completion log", &Quest::LoadConditionalConditionalQuestCompletionLog }
};
for (QuestLoaderHelper const& loader : QuestLoaderHelpers)
@@ -9462,7 +9483,7 @@ void ObjectMgr::LoadCreatureTrainers()
Trinity::IteratorPair<GossipMenuItemsContainer::const_iterator> gossipMenuItems = GetGossipMenuItemsMapBounds(gossipMenuId);
auto gossipOptionItr = std::find_if(gossipMenuItems.begin(), gossipMenuItems.end(), [gossipOptionId](std::pair<uint32 const, GossipMenuItems> const& entry)
{
- return entry.second.OptionID == gossipOptionId;
+ return entry.second.OrderIndex == gossipOptionId;
});
if (gossipOptionItr == gossipMenuItems.end())
{
@@ -9627,8 +9648,10 @@ void ObjectMgr::LoadGossipMenuItems()
_gossipMenuItemsStore.clear();
QueryResult result = WorldDatabase.Query(
- // 0 1 2 3 4 5 6 7 8 9 10 11
- "SELECT MenuID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, ActionMenuID, ActionPoiID, BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID "
+ // 0 1 2 3 4 5 6 7 8 9 10
+ "SELECT MenuID, GossipOptionID, OptionID, OptionNpc, OptionText, OptionBroadcastTextID, Language, Flags, ActionMenuID, ActionPoiID, GossipNpcOptionID, "
+ //11 12 13 14 15 16
+ "BoxCoded, BoxMoney, BoxText, BoxBroadcastTextID, SpellID, OverrideIconID "
"FROM gossip_menu_option ORDER BY MenuID, OptionID");
if (!result)
@@ -9637,6 +9660,10 @@ void ObjectMgr::LoadGossipMenuItems()
return;
}
+ std::unordered_map<int32, int32> optionToNpcOption;
+ for (GossipNPCOptionEntry const* npcOption : sGossipNPCOptionStore)
+ optionToNpcOption[npcOption->GossipOptionID] = npcOption->ID;
+
do
{
Field* fields = result->Fetch();
@@ -9644,21 +9671,31 @@ void ObjectMgr::LoadGossipMenuItems()
GossipMenuItems gMenuItem;
gMenuItem.MenuID = fields[0].GetUInt32();
- gMenuItem.OptionID = fields[1].GetUInt32();
- gMenuItem.OptionNpc = GossipOptionNpc(fields[2].GetUInt8());
- gMenuItem.OptionText = fields[3].GetString();
- gMenuItem.OptionBroadcastTextID = fields[4].GetUInt32();
- gMenuItem.Language = fields[5].GetUInt32();
- gMenuItem.ActionMenuID = fields[6].GetUInt32();
- gMenuItem.ActionPoiID = fields[7].GetUInt32();
- gMenuItem.BoxCoded = fields[8].GetBool();
- gMenuItem.BoxMoney = fields[9].GetUInt32();
- gMenuItem.BoxText = fields[10].GetString();
- gMenuItem.BoxBroadcastTextID = fields[11].GetUInt32();
+ gMenuItem.GossipOptionID = fields[1].GetInt32();
+ gMenuItem.OrderIndex = fields[2].GetUInt32();
+ gMenuItem.OptionNpc = GossipOptionNpc(fields[3].GetUInt8());
+ gMenuItem.OptionText = fields[4].GetString();
+ gMenuItem.OptionBroadcastTextID = fields[5].GetUInt32();
+ gMenuItem.Language = fields[6].GetUInt32();
+ gMenuItem.Flags = GossipOptionFlags(fields[7].GetInt32());
+ gMenuItem.ActionMenuID = fields[8].GetUInt32();
+ gMenuItem.ActionPoiID = fields[9].GetUInt32();
+ if (!fields[10].IsNull())
+ gMenuItem.GossipNpcOptionID = fields[10].GetInt32();
+
+ gMenuItem.BoxCoded = fields[11].GetBool();
+ gMenuItem.BoxMoney = fields[12].GetUInt32();
+ gMenuItem.BoxText = fields[13].GetString();
+ gMenuItem.BoxBroadcastTextID = fields[14].GetUInt32();
+ if (!fields[15].IsNull())
+ gMenuItem.SpellID = fields[15].GetInt32();
+
+ if (!fields[16].IsNull())
+ gMenuItem.OverrideIconID = fields[16].GetInt32();
if (gMenuItem.OptionNpc >= GossipOptionNpc::Count)
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has unknown NPC option id %u. Replacing with GossipOptionNpc::None", gMenuItem.MenuID, gMenuItem.OptionID, AsUnderlyingType(gMenuItem.OptionNpc));
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has unknown NPC option id %u. Replacing with GossipOptionNpc::None", gMenuItem.MenuID, gMenuItem.OrderIndex, AsUnderlyingType(gMenuItem.OptionNpc));
gMenuItem.OptionNpc = GossipOptionNpc::None;
}
@@ -9666,20 +9703,20 @@ void ObjectMgr::LoadGossipMenuItems()
{
if (!sBroadcastTextStore.LookupEntry(gMenuItem.OptionBroadcastTextID))
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible OptionBroadcastTextID %u, ignoring.", gMenuItem.MenuID, gMenuItem.OptionID, gMenuItem.OptionBroadcastTextID);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible OptionBroadcastTextID %u, ignoring.", gMenuItem.MenuID, gMenuItem.OrderIndex, gMenuItem.OptionBroadcastTextID);
gMenuItem.OptionBroadcastTextID = 0;
}
}
if (gMenuItem.Language && !sLanguagesStore.LookupEntry(gMenuItem.Language))
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing Language %u, ignoring", gMenuItem.MenuID, gMenuItem.OptionID, gMenuItem.Language);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing Language %u, ignoring", gMenuItem.MenuID, gMenuItem.OrderIndex, gMenuItem.Language);
gMenuItem.Language = 0;
}
if (gMenuItem.ActionMenuID && gMenuItem.OptionNpc != GossipOptionNpc::None)
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u can not use ActionMenuID for GossipOptionNpc different from GossipOptionNpc::None, ignoring", gMenuItem.MenuID, gMenuItem.OptionID);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u can not use ActionMenuID for GossipOptionNpc different from GossipOptionNpc::None, ignoring", gMenuItem.MenuID, gMenuItem.OrderIndex);
gMenuItem.ActionMenuID = 0;
}
@@ -9687,25 +9724,47 @@ void ObjectMgr::LoadGossipMenuItems()
{
if (gMenuItem.OptionNpc != GossipOptionNpc::None)
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u can not use ActionPoiID for GossipOptionNpc different from GossipOptionNpc::None, ignoring", gMenuItem.MenuID, gMenuItem.OptionID);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u can not use ActionPoiID for GossipOptionNpc different from GossipOptionNpc::None, ignoring", gMenuItem.MenuID, gMenuItem.OrderIndex);
gMenuItem.ActionPoiID = 0;
}
else if (!GetPointOfInterest(gMenuItem.ActionPoiID))
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing ActionPoiID %u, ignoring", gMenuItem.MenuID, gMenuItem.OptionID, gMenuItem.ActionPoiID);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing ActionPoiID %u, ignoring", gMenuItem.MenuID, gMenuItem.OrderIndex, gMenuItem.ActionPoiID);
gMenuItem.ActionPoiID = 0;
}
}
+ if (gMenuItem.GossipNpcOptionID)
+ {
+ if (!sGossipNPCOptionStore.LookupEntry(*gMenuItem.GossipNpcOptionID))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing GossipNPCOption %u, ignoring",
+ gMenuItem.MenuID, gMenuItem.OrderIndex, *gMenuItem.GossipNpcOptionID);
+ gMenuItem.GossipNpcOptionID.reset();
+ }
+ }
+ else if (int32 const* npcOptionId = Trinity::Containers::MapGetValuePtr(optionToNpcOption, gMenuItem.GossipOptionID))
+ gMenuItem.GossipNpcOptionID = *npcOptionId;
+
if (gMenuItem.BoxBroadcastTextID)
{
if (!sBroadcastTextStore.LookupEntry(gMenuItem.BoxBroadcastTextID))
{
- TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible BoxBroadcastTextID %u, ignoring.", gMenuItem.MenuID, gMenuItem.OptionID, gMenuItem.BoxBroadcastTextID);
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u has non-existing or incompatible BoxBroadcastTextID %u, ignoring.", gMenuItem.MenuID, gMenuItem.OrderIndex, gMenuItem.BoxBroadcastTextID);
gMenuItem.BoxBroadcastTextID = 0;
}
}
+ if (gMenuItem.SpellID)
+ {
+ if (!sSpellMgr->GetSpellInfo(*gMenuItem.SpellID, DIFFICULTY_NONE))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `gossip_menu_option` for menu %u, id %u use non-existing Spell %u, ignoring",
+ gMenuItem.MenuID, gMenuItem.OrderIndex, *gMenuItem.SpellID);
+ gMenuItem.SpellID.reset();
+ }
+ }
+
_gossipMenuItemsStore.insert(GossipMenuItemsContainer::value_type(gMenuItem.MenuID, gMenuItem));
} while (result->NextRow());
@@ -9755,44 +9814,6 @@ void ObjectMgr::LoadGossipMenuAddon()
TC_LOG_INFO("server.loading", ">> Loaded %u gossip_menu_addon IDs in %u ms", uint32(_gossipMenuAddonStore.size()), GetMSTimeDiffToNow(oldMSTime));
}
-void ObjectMgr::LoadGossipMenuItemAddon()
-{
- uint32 oldMSTime = getMSTime();
-
- _gossipMenuItemAddonStore.clear();
-
- // 0 1 2
- QueryResult result = WorldDatabase.Query("SELECT MenuID, OptionId, GarrTalentTreeID FROM gossip_menu_option_addon");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 gossip_menu_option_addon IDs. DB table `gossip_menu_option_addon` is empty!");
- return;
- }
-
- do
- {
- Field* fields = result->Fetch();
-
- uint32 menuId = fields[0].GetUInt32();
- uint32 optionId = fields[1].GetUInt32();
- GossipMenuItemAddon& addon = _gossipMenuItemAddonStore[{ menuId, optionId }];
- if (!fields[2].IsNull())
- {
- addon.GarrTalentTreeID = fields[2].GetInt32();
-
- if (!sGarrTalentTreeStore.LookupEntry(*addon.GarrTalentTreeID))
- {
- TC_LOG_ERROR("sql.sql", "Table gossip_menu_option_addon: MenuID %u OptionID %u is using non-existing GarrTalentTree %d",
- menuId, optionId, *addon.GarrTalentTreeID);
- addon.GarrTalentTreeID.reset();
- }
- }
- } while (result->NextRow());
-
- TC_LOG_INFO("server.loading", ">> Loaded %u gossip_menu_option_addon IDs in %u ms", uint32(_gossipMenuItemAddonStore.size()), GetMSTimeDiffToNow(oldMSTime));
-}
-
Trainer::Trainer const* ObjectMgr::GetTrainer(uint32 trainerId) const
{
return Trinity::Containers::MapGetValuePtr(_trainers, trainerId);
@@ -10594,10 +10615,10 @@ PlayerInfo const* ObjectMgr::GetPlayerInfo(uint32 race, uint32 class_) const
return nullptr;
if (class_ >= MAX_CLASSES)
return nullptr;
- auto const& info = _playerInfo[race][class_];
+ auto const& info = Trinity::Containers::MapGetValuePtr(_playerInfo, { Races(race), Classes(class_) });
if (!info)
return nullptr;
- return info.get();
+ return info->get();
}
void ObjectMgr::LoadRaceAndClassExpansionRequirements()
@@ -10659,6 +10680,8 @@ void ObjectMgr::LoadRaceAndClassExpansionRequirements()
if (result)
{
std::map<uint8, std::map<uint8, std::pair<uint8, uint8>>> temp;
+ std::array<uint8, MAX_CLASSES> minRequirementForClass = { };
+ minRequirementForClass.fill(MAX_ACCOUNT_EXPANSIONS);
uint32 count = 0;
do
{
@@ -10700,6 +10723,7 @@ void ObjectMgr::LoadRaceAndClassExpansionRequirements()
}
temp[raceID][classID] = { activeExpansionLevel, accountExpansionLevel };
+ minRequirementForClass[classID] = std::min(minRequirementForClass[classID], activeExpansionLevel);
++count;
}
@@ -10707,19 +10731,18 @@ void ObjectMgr::LoadRaceAndClassExpansionRequirements()
for (auto&& race : temp)
{
- _classExpansionRequirementStore.emplace_back();
+ RaceClassAvailability& raceClassAvailability = _classExpansionRequirementStore.emplace_back();
- RaceClassAvailability& raceClassAvailability = _classExpansionRequirementStore.back();
raceClassAvailability.RaceID = race.first;
for (auto&& class_ : race.second)
{
- raceClassAvailability.Classes.emplace_back();
+ ClassAvailability& classAvailability = raceClassAvailability.Classes.emplace_back();
- ClassAvailability& classAvailability = raceClassAvailability.Classes.back();
classAvailability.ClassID = class_.first;
classAvailability.ActiveExpansionLevel = class_.second.first;
classAvailability.AccountExpansionLevel = class_.second.second;
+ classAvailability.MinActiveExpansionLevel = minRequirementForClass[class_.first];
}
}
@@ -10804,6 +10827,16 @@ ClassAvailability const* ObjectMgr::GetClassExpansionRequirement(uint8 raceId, u
return &(*classItr);
}
+ClassAvailability const* ObjectMgr::GetClassExpansionRequirementFallback(uint8 classId) const
+{
+ for (RaceClassAvailability const& raceClassAvailability : _classExpansionRequirementStore)
+ for (ClassAvailability const& classAvailability : raceClassAvailability.Classes)
+ if (classAvailability.ClassID == classId)
+ return &classAvailability;
+
+ return nullptr;
+}
+
PlayerChoice const* ObjectMgr::GetPlayerChoice(int32 choiceId) const
{
return Trinity::Containers::MapGetValuePtr(_playerChoices, choiceId);