diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 96cddf952..11a8e6c57 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -222,6 +222,9 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE, "SELECT ID, ItemBonusTreeGroupID, DstItemBonusTreeID, Type, Value, " + "MythicPlusSeasonID, PvPSeasonID, SrcItemBonusTreeID FROM challenge_mode_item_bonus_override WHERE (`VerifiedBuild` > 0) = ?"); + // CharBaseInfo.db2 + PrepareStatement(HotfixStatements.SEL_CHAR_BASE_INFO, "SELECT ID, RaceID, ClassID, OtherFactionRaceID FROM char_base_info WHERE (`VerifiedBuild` > 0) = ?"); + // CharTitles.db2 PrepareStatement(HotfixStatements.SEL_CHAR_TITLES, "SELECT ID, Name, Name1, MaskID, Flags FROM char_titles WHERE (`VerifiedBuild` > 0) = ?"); PrepareStatement(HotfixStatements.SEL_CHAR_TITLES_LOCALE, "SELECT ID, Name_lang, Name1_lang FROM char_titles_locale WHERE (`VerifiedBuild` > 0) = ?" + @@ -1706,6 +1709,8 @@ namespace Framework.Database SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE, + SEL_CHAR_BASE_INFO, + SEL_CHAR_TITLES, SEL_CHAR_TITLES_LOCALE, diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index b7e2d1d72..3a0e74bf3 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -95,6 +95,7 @@ namespace Game.DataStorage CfgCategoriesStorage = ReadDB2("Cfg_Categories.db2", HotfixStatements.SEL_CFG_CATEGORIES, HotfixStatements.SEL_CFG_CATEGORIES_LOCALE); CfgRegionsStorage = ReadDB2("Cfg_Regions.db2", HotfixStatements.SEL_CFG_REGIONS); ChallengeModeItemBonusOverrideStorage = ReadDB2("ChallengeModeItemBonusOverride.db2", HotfixStatements.SEL_CHALLENGE_MODE_ITEM_BONUS_OVERRIDE); + CharBaseInfoStorage = ReadDB2("CharBaseInfo.db2", HotfixStatements.SEL_CHAR_BASE_INFO); CharTitlesStorage = ReadDB2("CharTitles.db2", HotfixStatements.SEL_CHAR_TITLES, HotfixStatements.SEL_CHAR_TITLES_LOCALE); CharacterLoadoutStorage = ReadDB2("CharacterLoadout.db2", HotfixStatements.SEL_CHARACTER_LOADOUT); CharacterLoadoutItemStorage = ReadDB2("CharacterLoadoutItem.db2", HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM); @@ -532,6 +533,7 @@ namespace Game.DataStorage public static DB6Storage CfgCategoriesStorage; public static DB6Storage CfgRegionsStorage; public static DB6Storage ChallengeModeItemBonusOverrideStorage; + public static DB6Storage CharBaseInfoStorage; public static DB6Storage CharTitlesStorage; public static DB6Storage CharacterLoadoutStorage; public static DB6Storage CharacterLoadoutItemStorage; diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index af4761b82..9fa861010 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -113,6 +113,8 @@ namespace Game.DataStorage foreach (var broadcastTextDuration in BroadcastTextDurationStorage.Values) _broadcastTextDurations[(broadcastTextDuration.BroadcastTextID, (CascLocaleBit)broadcastTextDuration.Locale)] = broadcastTextDuration.Duration; + foreach (var (_, charBaseInfo) in CharBaseInfoStorage) + _charBaseInfoByRaceAndClass[(charBaseInfo.RaceID, charBaseInfo.ClassID)] = charBaseInfo; foreach (var uiDisplay in ChrClassUIDisplayStorage.Values) { @@ -989,6 +991,11 @@ namespace Game.DataStorage return _broadcastTextDurations.LookupByKey((broadcastTextId, SharedConst.WowLocaleToCascLocaleBit[(int)locale])); } + public CharBaseInfoRecord GetCharBaseInfo(Race race, Class class_) + { + return _charBaseInfoByRaceAndClass.LookupByKey((race, class_)); + } + public ChrClassUIDisplayRecord GetUiDisplayForClass(Class unitClass) { Cypher.Assert(unitClass < Class.Max); @@ -2272,6 +2279,7 @@ namespace Game.DataStorage MultiMap _azeritePowers = new(); Dictionary<(uint azeriteUnlockSetId, ItemContext itemContext), byte[]> _azeriteTierUnlockLevels = new(); Dictionary<(int broadcastTextId, CascLocaleBit cascLocaleBit), int> _broadcastTextDurations = new(); + Dictionary<(sbyte, sbyte), CharBaseInfoRecord> _charBaseInfoByRaceAndClass = new(); ChrClassUIDisplayRecord[] _uiDisplayByClass = new ChrClassUIDisplayRecord[(int)Class.Max]; uint[][] _powersByClass = new uint[(int)Class.Max][]; MultiMap _chrCustomizationChoicesByOption = new(); diff --git a/Source/Game/DataStorage/Structs/C_Records.cs b/Source/Game/DataStorage/Structs/C_Records.cs index 99c37bb96..ec4276c50 100644 --- a/Source/Game/DataStorage/Structs/C_Records.cs +++ b/Source/Game/DataStorage/Structs/C_Records.cs @@ -43,6 +43,14 @@ namespace Game.DataStorage public uint SrcItemBonusTreeID; } + public sealed class CharBaseInfoRecord + { + public uint Id; + public sbyte RaceID; + public sbyte ClassID; + public int OtherFactionRaceID; + } + public sealed class CharTitlesRecord { public uint Id; diff --git a/Source/Scripts/Spells/Generic.cs b/Source/Scripts/Spells/Generic.cs index d1fd430f5..6b4e91383 100644 --- a/Source/Scripts/Spells/Generic.cs +++ b/Source/Scripts/Spells/Generic.cs @@ -357,35 +357,6 @@ namespace Scripts.Spells.Generic { List RacialSkills = new(); - Dictionary RaceInfo = new() - { - { Race.Human , new[] { Race.Undead, Race.BloodElf } }, - { Race.Orc , new[] { Race.Dwarf } }, - { Race.Dwarf , new[] { Race.Orc, Race.Undead, Race.Tauren } }, - { Race.NightElf , new[] { Race.Troll, Race.BloodElf } }, - { Race.Undead , new[] { Race.Human } }, - { Race.Tauren , new[] { Race.Draenei, Race.NightElf } }, - { Race.Gnome , new[] { Race.Goblin, Race.BloodElf } }, - { Race.Troll , new[] { Race.NightElf, Race.Human, Race.Draenei } }, - { Race.Goblin , new[] { Race.Gnome, Race.Dwarf } }, - { Race.BloodElf , new[] { Race.Human, Race.NightElf } }, - { Race.Draenei , new[] { Race.Tauren, Race.Orc } }, - { Race.Worgen , new[] { Race.Troll } }, - { Race.PandarenNeutral , new[] { Race.PandarenNeutral } }, - { Race.PandarenAlliance , new[] { Race.PandarenHorde, Race.PandarenNeutral } }, - { Race.PandarenHorde , new[] { Race.PandarenAlliance, Race.PandarenNeutral } }, - { Race.Nightborne , new[] { Race.NightElf, Race.Human } }, - { Race.HighmountainTauren , new[] { Race.Draenei, Race.NightElf } }, - { Race.VoidElf , new[] { Race.Troll, Race.BloodElf } }, - { Race.LightforgedDraenei , new[] { Race.Tauren, Race.Orc } }, - { Race.ZandalariTroll , new[] { Race.KulTiran, Race.Human } }, - { Race.KulTiran , new[] { Race.ZandalariTroll } }, - { Race.DarkIronDwarf , new[] { Race.MagharOrc, Race.Orc } }, - { Race.Vulpera , new[] { Race.MechaGnome, Race.DarkIronDwarf } }, - { Race.MagharOrc , new[] { Race.DarkIronDwarf } }, - { Race.MechaGnome , new[] { Race.Vulpera } }, - }; - Dictionary RaceDisplayIds = new() { { Race.Human , new uint[] { 55239, 55238 } }, @@ -417,11 +388,9 @@ namespace Scripts.Spells.Generic Race GetReplacementRace(Race nativeRace, Class playerClass) { - var otherRaces = RaceInfo.LookupByKey(nativeRace); - if (!otherRaces.Empty()) - foreach (Race race in otherRaces) - if (ObjectMgr.GetPlayerInfo(race, playerClass) != null) - return race; + CharBaseInfoRecord charBaseInfo = DB2Mgr.GetCharBaseInfo(nativeRace, playerClass); + if (charBaseInfo != null && ObjectMgr.GetPlayerInfo((Race)charBaseInfo.OtherFactionRaceID, playerClass) != null) + return (Race)charBaseInfo.OtherFactionRaceID; return Race.None; } @@ -437,16 +406,6 @@ namespace Scripts.Spells.Generic public override bool Validate(SpellInfo spellInfo) { - foreach (var (race, otherRaces) in RaceInfo) - { - if (!CliDB.ChrRacesStorage.ContainsKey(race)) - return false; - - foreach (Race otherRace in otherRaces) - if (!CliDB.ChrRacesStorage.ContainsKey(otherRace)) - return false; - } - foreach (var (race, displayIds) in RaceDisplayIds) { if (!CliDB.ChrRacesStorage.ContainsKey(race))