From 515aeca570e879a7fa12a1773436a2a0597979b2 Mon Sep 17 00:00:00 2001
From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com>
Date: Sat, 28 Feb 2026 18:12:52 -0500
Subject: [PATCH] feat(Core/Globals): Dynamically calculate max race and
racemasks from DBC data. (#24665)
---
.../game/Achievements/AchievementMgr.cpp | 5 +-
src/server/game/Conditions/ConditionMgr.cpp | 5 +-
src/server/game/Entities/Player/RaceMgr.cpp | 77 +++++++++++++++++++
src/server/game/Entities/Player/RaceMgr.h | 54 +++++++++++++
src/server/game/Globals/ObjectMgr.cpp | 53 +++++++------
src/server/game/Globals/ObjectMgr.h | 2 +-
src/server/game/Handlers/CharacterHandler.cpp | 5 +-
src/server/game/Mails/ServerMailMgr.cpp | 3 +-
src/server/game/Spells/SpellMgr.cpp | 3 +-
src/server/game/World/World.cpp | 4 +
.../scripts/Northrend/zone_wintergrasp.cpp | 5 +-
src/server/scripts/Pet/pet_generic.cpp | 52 +++++++------
src/server/shared/DataStores/DBCStructure.h | 4 +-
src/server/shared/DataStores/DBCfmt.h | 2 +-
src/server/shared/SharedDefines.h | 22 ++----
15 files changed, 221 insertions(+), 75 deletions(-)
create mode 100644 src/server/game/Entities/Player/RaceMgr.cpp
create mode 100644 src/server/game/Entities/Player/RaceMgr.h
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 2451aac3d..a3823112b 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -39,6 +39,7 @@
#include "MapMgr.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "RaceMgr.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "SpellMgr.h"
@@ -115,7 +116,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
criteria->ID, criteria->requiredType, dataType, classRace.class_id);
return false;
}
- if (classRace.race_id && ((1 << (classRace.race_id - 1)) & RACEMASK_ALL_PLAYABLE) == 0)
+ if (classRace.race_id && ((1 << (classRace.race_id - 1)) & sRaceMgr->GetPlayableRaceMask()) == 0)
{
LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: {} Type: {}) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({}) has non-existing race in value2 ({}), ignored.",
criteria->ID, criteria->requiredType, dataType, classRace.race_id);
@@ -275,7 +276,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
criteria->ID, criteria->requiredType, dataType, classRace.class_id);
return false;
}
- if (classRace.race_id && ((1 << (classRace.race_id - 1)) & RACEMASK_ALL_PLAYABLE) == 0)
+ if (classRace.race_id && ((1 << (classRace.race_id - 1)) & sRaceMgr->GetPlayableRaceMask()) == 0)
{
LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: {} Type: {}) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({}) has non-existing race in value2 ({}), ignored.",
criteria->ID, criteria->requiredType, dataType, classRace.race_id);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 688820001..213ee742f 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -24,6 +24,7 @@
#include "ObjectMgr.h"
#include "Pet.h"
#include "Player.h"
+#include "RaceMgr.h"
#include "ReputationMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
@@ -2082,9 +2083,9 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
}
case CONDITION_RACE:
{
- if (!(cond->ConditionValue1 & RACEMASK_ALL_PLAYABLE))
+ if (!(cond->ConditionValue1 & sRaceMgr->GetPlayableRaceMask()))
{
- LOG_ERROR("sql.sql", "Race condition has non existing racemask ({}), skipped", cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
+ LOG_ERROR("sql.sql", "Race condition has non existing racemask ({}), skipped", cond->ConditionValue1 & ~sRaceMgr->GetPlayableRaceMask());
return false;
}
diff --git a/src/server/game/Entities/Player/RaceMgr.cpp b/src/server/game/Entities/Player/RaceMgr.cpp
new file mode 100644
index 000000000..b1ac288cb
--- /dev/null
+++ b/src/server/game/Entities/Player/RaceMgr.cpp
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#include "RaceMgr.h"
+#include "AccountMgr.h"
+#include "DatabaseEnv.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+#include "Util.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+
+uint8 RaceMgr::_maxRaces = 0;
+
+uint32 RaceMgr::_playableRaceMask = 0;
+uint32 RaceMgr::_allianceRaceMask = 0;
+uint32 RaceMgr::_hordeRaceMask = 0;
+
+RaceMgr::RaceMgr()
+{
+}
+
+RaceMgr::~RaceMgr()
+{
+}
+
+RaceMgr* RaceMgr::instance()
+{
+ static RaceMgr instance;
+ return &instance;
+}
+
+void RaceMgr::LoadRaces()
+{
+ SetMaxRaces(0 + 1);
+ _playableRaceMask = 0;
+ _hordeRaceMask = 0;
+ _allianceRaceMask = 0;
+
+ for (auto const& raceEntry : sChrRacesStore)
+ {
+ if (!raceEntry)
+ continue;
+
+ uint8 alliance = raceEntry->alliance;
+ uint8 raceId = raceEntry->RaceID;
+
+ if (raceEntry->Flags & CHRRACES_FLAGS_NOT_PLAYABLE)
+ continue;
+
+ if (GetMaxRaces() <= raceId)
+ SetMaxRaces(raceId + 1);
+
+ uint32 raceBit = (1 << (raceId - 1));
+
+ _playableRaceMask |= raceBit;
+
+ if (alliance == ALLIANCE_HORDE)
+ _hordeRaceMask |= raceBit;
+ else if (alliance == ALLIANCE_ALLIANCE)
+ _allianceRaceMask |= raceBit;
+ }
+}
diff --git a/src/server/game/Entities/Player/RaceMgr.h b/src/server/game/Entities/Player/RaceMgr.h
new file mode 100644
index 000000000..239e69070
--- /dev/null
+++ b/src/server/game/Entities/Player/RaceMgr.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+#ifndef __ACORE_RACEMGR_H
+#define __ACORE_RACEMGR_H
+
+#include "DatabaseEnv.h"
+#include "ObjectGuid.h"
+#include "SharedDefines.h"
+#include