aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/hotfixes/master/2024_03_28_00_hotfixes.sql12
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp4
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h3
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h13
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp11
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DB2Structure.h8
-rw-r--r--src/server/game/Server/Packets/HotfixPackets.h3
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp54
9 files changed, 59 insertions, 50 deletions
diff --git a/sql/updates/hotfixes/master/2024_03_28_00_hotfixes.sql b/sql/updates/hotfixes/master/2024_03_28_00_hotfixes.sql
new file mode 100644
index 00000000000..e0e8a296116
--- /dev/null
+++ b/sql/updates/hotfixes/master/2024_03_28_00_hotfixes.sql
@@ -0,0 +1,12 @@
+--
+-- Table structure for table `char_base_info`
+--
+DROP TABLE IF EXISTS `char_base_info`;
+CREATE TABLE `char_base_info` (
+ `ID` int unsigned NOT NULL DEFAULT '0',
+ `RaceID` tinyint NOT NULL DEFAULT '0',
+ `ClassID` tinyint NOT NULL DEFAULT '0',
+ `OtherFactionRaceID` int NOT NULL DEFAULT '0',
+ `VerifiedBuild` int NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`,`VerifiedBuild`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 2c33390af10..4e5bec49b13 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -305,6 +305,10 @@ void HotfixDatabaseConnection::DoPrepareStatements()
"MythicPlusSeasonID, PvPSeasonID, SrcItemBonusTreeID FROM challenge_mode_item_bonus_override WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE, "SELECT MAX(ID) + 1 FROM challenge_mode_item_bonus_override", CONNECTION_SYNCH);
+ // CharBaseInfo.db2
+ PrepareStatement(HOTFIX_SEL_CHAR_BASE_INFO, "SELECT ID, RaceID, ClassID, OtherFactionRaceID FROM char_base_info WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
+ PREPARE_MAX_ID_STMT(HOTFIX_SEL_CHAR_BASE_INFO, "SELECT MAX(ID) + 1 FROM char_base_info", CONNECTION_SYNCH);
+
// CharTitles.db2
PrepareStatement(HOTFIX_SEL_CHAR_TITLES, "SELECT ID, Name, Name1, MaskID, Flags FROM char_titles WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH);
PREPARE_MAX_ID_STMT(HOTFIX_SEL_CHAR_TITLES, "SELECT MAX(ID) + 1 FROM char_titles", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index 45600062398..7b1b6804571 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -192,6 +192,9 @@ enum HotfixDatabaseStatements : uint32
HOTFIX_SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE,
HOTFIX_SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE_MAX_ID,
+ HOTFIX_SEL_CHAR_BASE_INFO,
+ HOTFIX_SEL_CHAR_BASE_INFO_MAX_ID,
+
HOTFIX_SEL_CHAR_TITLES,
HOTFIX_SEL_CHAR_TITLES_MAX_ID,
HOTFIX_SEL_CHAR_TITLES_LOCALE,
diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h
index 7f52e54274c..b363192dfdf 100644
--- a/src/server/game/DataStores/DB2LoadInfo.h
+++ b/src/server/game/DataStores/DB2LoadInfo.h
@@ -841,6 +841,19 @@ struct ChallengeModeItemBonusOverrideLoadInfo
static constexpr DB2LoadInfo Instance{ Fields, 8, &ChallengeModeItemBonusOverrideMeta::Instance, HOTFIX_SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE };
};
+struct CharBaseInfoLoadInfo
+{
+ static constexpr DB2FieldMeta Fields[4] =
+ {
+ { false, FT_INT, "ID" },
+ { true, FT_BYTE, "RaceID" },
+ { true, FT_BYTE, "ClassID" },
+ { true, FT_INT, "OtherFactionRaceID" },
+ };
+
+ static constexpr DB2LoadInfo Instance{ Fields, 4, &CharBaseInfoMeta::Instance, HOTFIX_SEL_CHAR_BASE_INFO };
+};
+
struct CharTitlesLoadInfo
{
static constexpr DB2FieldMeta Fields[5] =
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 8bd70407d92..2a30e0974a0 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -88,6 +88,7 @@ DB2Storage<BroadcastTextDurationEntry> sBroadcastTextDurationStore("Bro
DB2Storage<Cfg_CategoriesEntry> sCfgCategoriesStore("Cfg_Categories.db2", &CfgCategoriesLoadInfo::Instance);
DB2Storage<Cfg_RegionsEntry> sCfgRegionsStore("Cfg_Regions.db2", &CfgRegionsLoadInfo::Instance);
DB2Storage<ChallengeModeItemBonusOverrideEntry> sChallengeModeItemBonusOverrideStore("ChallengeModeItemBonusOverride.db2", &ChallengeModeItemBonusOverrideLoadInfo::Instance);
+DB2Storage<CharBaseInfoEntry> sCharBaseInfoStore("CharBaseInfo.db2", &CharBaseInfoLoadInfo::Instance);
DB2Storage<CharTitlesEntry> sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance);
DB2Storage<CharacterLoadoutEntry> sCharacterLoadoutStore("CharacterLoadout.db2", &CharacterLoadoutLoadInfo::Instance);
DB2Storage<CharacterLoadoutItemEntry> sCharacterLoadoutItemStore("CharacterLoadoutItem.db2", &CharacterLoadoutItemLoadInfo::Instance);
@@ -450,6 +451,7 @@ namespace
std::unordered_map<uint32 /*azeritePowerSetId*/, std::vector<AzeritePowerSetMemberEntry const*>> _azeritePowers;
std::unordered_map<std::pair<uint32 /*azeriteUnlockSetId*/, ItemContext>, std::array<uint8, MAX_AZERITE_EMPOWERED_TIER>> _azeriteTierUnlockLevels;
std::unordered_map<std::pair<int32 /*broadcastTextId*/, CascLocaleBit /*cascLocaleBit*/>, int32> _broadcastTextDurations;
+ std::unordered_map<std::pair<uint8, uint8>, CharBaseInfoEntry const*> _charBaseInfoByRaceAndClass;
std::array<ChrClassUIDisplayEntry const*, MAX_CLASSES> _uiDisplayByClass;
std::array<std::array<uint32, MAX_POWERS>, MAX_CLASSES> _powersByClass;
std::unordered_map<uint32 /*chrCustomizationOptionId*/, std::vector<ChrCustomizationChoiceEntry const*>> _chrCustomizationChoicesByOption;
@@ -688,6 +690,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
LOAD_DB2(sCfgCategoriesStore);
LOAD_DB2(sCfgRegionsStore);
LOAD_DB2(sChallengeModeItemBonusOverrideStore);
+ LOAD_DB2(sCharBaseInfoStore);
LOAD_DB2(sCharTitlesStore);
LOAD_DB2(sCharacterLoadoutStore);
LOAD_DB2(sCharacterLoadoutItemStore);
@@ -1078,6 +1081,9 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
for (BroadcastTextDurationEntry const* broadcastTextDuration : sBroadcastTextDurationStore)
_broadcastTextDurations[{ broadcastTextDuration->BroadcastTextID, CascLocaleBit(broadcastTextDuration->Locale) }] = broadcastTextDuration->Duration;
+ for (CharBaseInfoEntry const* charBaseInfo : sCharBaseInfoStore)
+ _charBaseInfoByRaceAndClass[{ charBaseInfo->RaceID, charBaseInfo->ClassID }] = charBaseInfo;
+
for (ChrClassUIDisplayEntry const* uiDisplay : sChrClassUIDisplayStore)
{
ASSERT(uiDisplay->ChrClassesID < MAX_CLASSES);
@@ -2026,6 +2032,11 @@ int32 const* DB2Manager::GetBroadcastTextDuration(int32 broadcastTextId, LocaleC
return Trinity::Containers::MapGetValuePtr(_broadcastTextDurations, { broadcastTextId, WowLocaleToCascLocaleBit[locale] });
}
+CharBaseInfoEntry const* DB2Manager::GetCharBaseInfo(Races race, Classes class_)
+{
+ return Trinity::Containers::MapGetValuePtr(_charBaseInfoByRaceAndClass, { race, class_ });
+}
+
ChrClassUIDisplayEntry const* DB2Manager::GetUiDisplayForClass(Classes unitClass) const
{
ASSERT(unitClass < MAX_CLASSES);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 97c8dc502a4..fda324418ca 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -437,6 +437,7 @@ public:
uint32 GetRequiredAzeriteLevelForAzeritePowerTier(uint32 azeriteUnlockSetId, ItemContext context, uint32 tier) const;
static char const* GetBroadcastTextValue(BroadcastTextEntry const* broadcastText, LocaleConstant locale = DEFAULT_LOCALE, uint8 gender = GENDER_MALE, bool forceGender = false);
int32 const* GetBroadcastTextDuration(int32 broadcastTextId, LocaleConstant locale = DEFAULT_LOCALE) const;
+ static CharBaseInfoEntry const* GetCharBaseInfo(Races race, Classes class_);
ChrClassUIDisplayEntry const* GetUiDisplayForClass(Classes unitClass) const;
static char const* GetClassName(uint8 class_, LocaleConstant locale = DEFAULT_LOCALE);
uint32 GetPowerIndexByClass(Powers power, uint32 classId) const;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 2b1243dbb8f..4afcdbb0635 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -582,6 +582,14 @@ struct ChallengeModeItemBonusOverrideEntry
uint32 SrcItemBonusTreeID;
};
+struct CharBaseInfoEntry
+{
+ uint32 ID;
+ int8 RaceID;
+ int8 ClassID;
+ int32 OtherFactionRaceID;
+};
+
struct CharTitlesEntry
{
uint32 ID;
diff --git a/src/server/game/Server/Packets/HotfixPackets.h b/src/server/game/Server/Packets/HotfixPackets.h
index 7d85637bf26..7c4ab389348 100644
--- a/src/server/game/Server/Packets/HotfixPackets.h
+++ b/src/server/game/Server/Packets/HotfixPackets.h
@@ -18,10 +18,9 @@
#ifndef HotfixPackets_h__
#define HotfixPackets_h__
-#include "Packet.h"
#include "Common.h"
#include "DB2Stores.h"
-#include "ObjectGuid.h"
+#include "Packet.h"
namespace WorldPackets
{
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 323b3c175fa..ff12c258c5e 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -408,37 +408,6 @@ class spell_gen_bandage : public SpellScript
// 193970 - Mercenary Shapeshift
class spell_gen_battleground_mercenary_shapeshift : public AuraScript
{
- using OtherFactionRacePriorityList = std::array<Races, 3>;
-
- inline static std::unordered_map<Races, OtherFactionRacePriorityList> const RaceInfo =
- {
- { RACE_HUMAN, { RACE_UNDEAD_PLAYER, RACE_BLOODELF } },
- { RACE_ORC, { RACE_DWARF } },
- { RACE_DWARF, { RACE_ORC, RACE_UNDEAD_PLAYER, RACE_TAUREN } },
- { RACE_NIGHTELF, { RACE_TROLL, RACE_BLOODELF } },
- { RACE_UNDEAD_PLAYER, { RACE_HUMAN } },
- { RACE_TAUREN, { RACE_DRAENEI, RACE_NIGHTELF } },
- { RACE_GNOME, { RACE_GOBLIN, RACE_BLOODELF } },
- { RACE_TROLL, { RACE_NIGHTELF, RACE_HUMAN, RACE_DRAENEI } },
- { RACE_GOBLIN, { RACE_GNOME, RACE_DWARF } },
- { RACE_BLOODELF, { RACE_HUMAN, RACE_NIGHTELF } },
- { RACE_DRAENEI, { RACE_TAUREN, RACE_ORC } },
- { RACE_WORGEN, { RACE_TROLL } },
- { RACE_PANDAREN_NEUTRAL, { RACE_PANDAREN_NEUTRAL } },
- { RACE_PANDAREN_ALLIANCE, { RACE_PANDAREN_HORDE, RACE_PANDAREN_NEUTRAL } },
- { RACE_PANDAREN_HORDE, { RACE_PANDAREN_ALLIANCE, RACE_PANDAREN_NEUTRAL } },
- { RACE_NIGHTBORNE, { RACE_NIGHTELF, RACE_HUMAN } },
- { RACE_HIGHMOUNTAIN_TAUREN, { RACE_DRAENEI, RACE_NIGHTELF } },
- { RACE_VOID_ELF, { RACE_TROLL, RACE_BLOODELF } },
- { RACE_LIGHTFORGED_DRAENEI, { RACE_TAUREN, RACE_ORC } },
- { RACE_ZANDALARI_TROLL, { RACE_KUL_TIRAN, RACE_HUMAN } },
- { RACE_KUL_TIRAN, { RACE_ZANDALARI_TROLL } },
- { RACE_DARK_IRON_DWARF, { RACE_MAGHAR_ORC, RACE_ORC } },
- { RACE_VULPERA, { RACE_MECHAGNOME, RACE_DARK_IRON_DWARF /*guessed, for shamans*/ } },
- { RACE_MAGHAR_ORC, { RACE_DARK_IRON_DWARF } },
- { RACE_MECHAGNOME, { RACE_VULPERA } },
- };
-
inline static std::unordered_map<Races, std::array<uint32, 2>> const RaceDisplayIds =
{
{ RACE_HUMAN, { 55239, 55238 } },
@@ -472,10 +441,9 @@ class spell_gen_battleground_mercenary_shapeshift : public AuraScript
static Races GetReplacementRace(Races nativeRace, Classes playerClass)
{
- if (OtherFactionRacePriorityList const* otherRaces = Trinity::Containers::MapGetValuePtr(RaceInfo, nativeRace))
- for (Races race : *otherRaces)
- if (sObjectMgr->GetPlayerInfo(race, playerClass))
- return race;
+ if (CharBaseInfoEntry const* charBaseInfo = DB2Manager::GetCharBaseInfo(nativeRace, playerClass))
+ if (sObjectMgr->GetPlayerInfo(charBaseInfo->OtherFactionRaceID, playerClass))
+ return Races(charBaseInfo->OtherFactionRaceID);
return RACE_NONE;
}
@@ -490,16 +458,6 @@ class spell_gen_battleground_mercenary_shapeshift : public AuraScript
bool Validate(SpellInfo const* /*spellInfo*/) override
{
- for (auto const& [race, otherRaces] : RaceInfo)
- {
- if (!sChrRacesStore.LookupEntry(race))
- return false;
-
- for (Races otherRace : otherRaces)
- if (!sChrRacesStore.LookupEntry(otherRace))
- return false;
- }
-
for (auto const& [race, displayIds] : RaceDisplayIds)
{
if (!sChrRacesStore.LookupEntry(race))
@@ -518,7 +476,7 @@ class spell_gen_battleground_mercenary_shapeshift : public AuraScript
return true;
}
- void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes mode)
+ void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes mode) const
{
Unit* owner = GetUnitOwner();
Races otherFactionRace = GetReplacementRace(Races(owner->GetRace()), Classes(owner->GetClass()));
@@ -532,7 +490,7 @@ class spell_gen_battleground_mercenary_shapeshift : public AuraScript
UpdateRacials(Races(owner->GetRace()), otherFactionRace);
}
- void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const
{
Unit* owner = GetUnitOwner();
Races otherFactionRace = GetReplacementRace(Races(owner->GetRace()), Classes(owner->GetClass()));
@@ -542,7 +500,7 @@ class spell_gen_battleground_mercenary_shapeshift : public AuraScript
UpdateRacials(otherFactionRace, Races(owner->GetRace()));
}
- void UpdateRacials(Races oldRace, Races newRace)
+ void UpdateRacials(Races oldRace, Races newRace) const
{
Player* player = GetUnitOwner()->ToPlayer();
if (!player)