feat(Core/Globals): Dynamically calculate max race and racemasks from DBC data. (#24665)

This commit is contained in:
Benjamin Jackson
2026-02-28 18:12:52 -05:00
committed by GitHub
parent 85b224bcef
commit 515aeca570
15 changed files with 221 additions and 75 deletions

View File

@@ -38,6 +38,7 @@
#include "MapMgr.h"
#include "Pet.h"
#include "PoolMgr.h"
#include "RaceMgr.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "Spell.h"
@@ -308,8 +309,6 @@ ObjectMgr::ObjectMgr():
for (uint8 i = 0; i < MAX_CLASSES; ++i)
{
_playerClassInfo[i] = nullptr;
for (uint8 j = 0; j < MAX_RACES; ++j)
_playerInfo[j][i] = nullptr;
}
}
@@ -329,7 +328,7 @@ ObjectMgr::~ObjectMgr()
delete _playerClassInfo[class_];
}
for (int race = 0; race < MAX_RACES; ++race)
for (int race = 0; race < sRaceMgr->GetMaxRaces(); ++race)
{
for (int class_ = 0; class_ < MAX_CLASSES; ++class_)
{
@@ -3492,7 +3491,7 @@ void ObjectMgr::LoadItemTemplates()
if (!(itemTemplate.AllowableClass & CLASSMASK_ALL_PLAYABLE))
LOG_ERROR("sql.sql", "Item (Entry: {}) does not have any playable classes ({}) in `AllowableClass` and can't be equipped or used.", entry, itemTemplate.AllowableClass);
if (!(itemTemplate.AllowableRace & RACEMASK_ALL_PLAYABLE))
if (!(itemTemplate.AllowableRace & sRaceMgr->GetPlayableRaceMask()))
LOG_ERROR("sql.sql", "Item (Entry: {}) does not have any playable races ({}) in `AllowableRace` and can't be equipped or used.", entry, itemTemplate.AllowableRace);
}
}
@@ -4252,6 +4251,14 @@ void ObjectMgr::LoadPlayerInfo()
{
// Load playercreate
{
if (_playerInfo.empty() || _playerInfo.size() != sRaceMgr->GetMaxRaces())
{
_playerInfo.clear();
_playerInfo.resize(sRaceMgr->GetMaxRaces());
for (auto& classVec : _playerInfo)
classVec.resize(MAX_CLASSES, nullptr);
}
uint32 oldMSTime = getMSTime();
// 0 1 2 3 4 5 6
QueryResult result = WorldDatabase.Query("SELECT race, class, map, zone, position_x, position_y, position_z, orientation FROM playercreateinfo");
@@ -4279,7 +4286,7 @@ void ObjectMgr::LoadPlayerInfo()
float positionZ = fields[6].Get<float>();
float orientation = fields[7].Get<float>();
if (current_race >= MAX_RACES)
if (current_race >= sRaceMgr->GetMaxRaces())
{
LOG_ERROR("sql.sql", "Wrong race {} in `playercreateinfo` table, ignoring.", current_race);
continue;
@@ -4357,7 +4364,7 @@ void ObjectMgr::LoadPlayerInfo()
Field* fields = result->Fetch();
uint32 current_race = fields[0].Get<uint8>();
if (current_race >= MAX_RACES)
if (current_race >= sRaceMgr->GetMaxRaces())
{
LOG_ERROR("sql.sql", "Wrong race {} in `playercreateinfo_item` table, ignoring.", current_race);
continue;
@@ -4389,7 +4396,7 @@ void ObjectMgr::LoadPlayerInfo()
if (!current_race || !current_class)
{
uint32 min_race = current_race ? current_race : 1;
uint32 max_race = current_race ? current_race + 1 : MAX_RACES;
uint32 max_race = current_race ? current_race + 1 : sRaceMgr->GetMaxRaces();
uint32 min_class = current_class ? current_class : 1;
uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES;
for (uint32 r = min_race; r < max_race; ++r)
@@ -4437,7 +4444,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
if (raceMask != 0 && !(raceMask & sRaceMgr->GetPlayableRaceMask()))
{
LOG_ERROR("sql.sql", "Wrong race mask {} in `playercreateinfo_skills` table, ignoring.", raceMask);
continue;
@@ -4455,7 +4462,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
for (uint32 raceIndex = RACE_HUMAN; raceIndex < sRaceMgr->GetMaxRaces(); ++raceIndex)
{
if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
{
@@ -4504,7 +4511,7 @@ void ObjectMgr::LoadPlayerInfo()
uint32 classMask = fields[1].Get<uint32>();
uint32 spellId = fields[2].Get<uint32>();
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
if (raceMask != 0 && !(raceMask & sRaceMgr->GetPlayableRaceMask()))
{
LOG_ERROR("sql.sql", "Wrong race mask {} in `playercreateinfo_spell_custom` table, ignoring.", raceMask);
continue;
@@ -4516,7 +4523,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
for (uint32 raceIndex = RACE_HUMAN; raceIndex < sRaceMgr->GetMaxRaces(); ++raceIndex)
{
if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
{
@@ -4562,7 +4569,7 @@ void ObjectMgr::LoadPlayerInfo()
uint32 classMask = fields[1].Get<uint32>();
uint32 spellId = fields[2].Get<uint32>();
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
if (raceMask != 0 && !(raceMask & sRaceMgr->GetPlayableRaceMask()))
{
LOG_ERROR("sql.sql", "Wrong race mask {} in `playercreateinfo_cast_spell` table, ignoring.", raceMask);
continue;
@@ -4574,7 +4581,7 @@ void ObjectMgr::LoadPlayerInfo()
continue;
}
for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
for (uint32 raceIndex = RACE_HUMAN; raceIndex < sRaceMgr->GetMaxRaces(); ++raceIndex)
{
if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
{
@@ -4620,7 +4627,7 @@ void ObjectMgr::LoadPlayerInfo()
Field* fields = result->Fetch();
uint32 current_race = fields[0].Get<uint8>();
if (current_race >= MAX_RACES)
if (current_race >= sRaceMgr->GetMaxRaces())
{
LOG_ERROR("sql.sql", "Wrong race {} in `playercreateinfo_action` table, ignoring.", current_race);
continue;
@@ -4652,7 +4659,9 @@ void ObjectMgr::LoadPlayerInfo()
int16 StatModifier[MAX_STATS];
};
std::array<RaceStats, MAX_RACES> raceStatModifiers;
std::vector<RaceStats> raceStatModifiers;
raceStatModifiers.resize(sRaceMgr->GetMaxRaces());
uint32 oldMSTime = getMSTime();
@@ -4671,7 +4680,7 @@ void ObjectMgr::LoadPlayerInfo()
Field* fields = raceStatsResult->Fetch();
uint32 current_race = fields[0].Get<uint8>();
if (current_race >= MAX_RACES)
if (current_race >= sRaceMgr->GetMaxRaces())
{
LOG_ERROR("sql.sql", "Wrong race {} in `player_race_stats` table, ignoring.", current_race);
continue;
@@ -4745,7 +4754,7 @@ void ObjectMgr::LoadPlayerInfo()
} while (result->NextRow());
// Fill gaps and check integrity
for (int race = 0; race < MAX_RACES; ++race)
for (int race = RACE_HUMAN; race < sRaceMgr->GetMaxRaces(); ++race)
{
// skip non existed races
if (!sChrRacesStore.LookupEntry(race))
@@ -4884,7 +4893,7 @@ void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint8 level, PlayerClassL
void ObjectMgr::GetPlayerLevelInfo(uint32 race, uint32 class_, uint8 level, PlayerLevelInfo* info) const
{
if (level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES)
if (level < 1 || race >= sRaceMgr->GetMaxRaces() || class_ >= MAX_CLASSES)
return;
PlayerInfo const* pInfo = _playerInfo[race][class_];
@@ -5253,10 +5262,10 @@ void ObjectMgr::LoadQuests()
qinfo->RequiredClasses = 0;
}
}
// AllowableRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race
// AllowableRaces, can be 0/PlayableRaceMask to allow any race
if (qinfo->AllowableRaces)
{
if (!(qinfo->AllowableRaces & RACEMASK_ALL_PLAYABLE))
if (!(qinfo->AllowableRaces & sRaceMgr->GetPlayableRaceMask()))
{
LOG_ERROR("sql.sql", "Quest {} does not contain any playable races in `AllowableRaces` ({}), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->AllowableRaces);
qinfo->AllowableRaces = 0;
@@ -9677,7 +9686,7 @@ void ObjectMgr::LoadMailLevelRewards()
continue;
}
if (!(raceMask & RACEMASK_ALL_PLAYABLE))
if (!(raceMask & sRaceMgr->GetPlayableRaceMask()))
{
LOG_ERROR("sql.sql", "Table `mail_level_reward` have raceMask ({}) for level {} that not include any player races, ignoring.", raceMask, level);
continue;
@@ -10774,7 +10783,7 @@ VehicleAccessoryList const* ObjectMgr::GetVehicleAccessoryList(Vehicle* veh) con
PlayerInfo const* ObjectMgr::GetPlayerInfo(uint32 race, uint32 class_) const
{
if (race >= MAX_RACES)
if (race >= sRaceMgr->GetMaxRaces())
return nullptr;
if (class_ >= MAX_CLASSES)
return nullptr;