TrinityCore
DB2Stores.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "DB2Stores.h"
19#include "Containers.h"
20#include "DB2LoadInfo.h"
21#include "DatabaseEnv.h"
22#include "Hash.h"
23#include "ItemTemplate.h"
24#include "IteratorPair.h"
25#include "Log.h"
26#include "MapUtils.h"
27#include "Random.h"
28#include "Regex.h"
29#include "Timer.h"
30#include "Util.h"
31#include "World.h"
32#include <algorithm>
33#include <array>
34#include <bitset>
35#include <boost/filesystem/directory.hpp>
36#include <boost/filesystem/operations.hpp>
37#include <numeric>
38#include <cctype>
39#include <cmath>
40
390
396
398
399typedef std::map<uint32 /*hash*/, DB2StorageBase*> StorageMap;
400typedef std::unordered_map<uint32 /*areaGroupId*/, std::vector<uint32/*areaId*/>> AreaGroupMemberContainer;
401typedef std::unordered_map<uint32, std::vector<ArtifactPowerEntry const*>> ArtifactPowersContainer;
402typedef std::unordered_map<uint32, std::vector<uint32>> ArtifactPowerLinksContainer;
405typedef std::unordered_map<uint32 /*curveID*/, std::vector<DBCPosition2D>> CurvePointsContainer;
407typedef std::unordered_map<uint32, std::vector<uint32>> FactionTeamContainer;
408typedef std::unordered_map<uint32, HeirloomEntry const*> HeirloomItemsContainer;
409typedef std::unordered_map<uint32 /*glyphPropertiesId*/, std::vector<uint32>> GlyphBindableSpellsContainer;
410typedef std::unordered_map<uint32 /*glyphPropertiesId*/, std::vector<ChrSpecialization>> GlyphRequiredSpecsContainer;
411typedef std::unordered_map<uint32 /*itemId*/, ItemChildEquipmentEntry const*> ItemChildEquipmentContainer;
414typedef std::unordered_map<uint32 /*itemId | appearanceMod << 24*/, ItemModifiedAppearanceEntry const*> ItemModifiedAppearanceByItemContainer;
415typedef std::unordered_map<uint32, std::vector<ItemSetSpellEntry const*>> ItemSetSpellContainer;
416typedef std::unordered_map<uint32, std::vector<ItemSpecOverrideEntry const*>> ItemSpecOverridesContainer;
417typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficultyEntry const*>> MapDifficultyContainer;
418typedef std::unordered_map<uint32, DB2Manager::MountTypeXCapabilitySet> MountCapabilitiesByTypeContainer;
419typedef std::unordered_map<uint32, DB2Manager::MountXDisplayContainer> MountDisplaysCointainer;
420typedef std::unordered_map<uint32, std::array<std::vector<NameGenEntry const*>, 2>> NameGenContainer;
422typedef std::unordered_map<uint32, std::vector<uint32>> PhaseGroupContainer;
424typedef std::unordered_map<uint32, std::pair<std::vector<QuestPackageItemEntry const*>, std::vector<QuestPackageItemEntry const*>>> QuestPackageItemContainer;
427typedef std::unordered_map<uint32, std::vector<SpellPowerEntry const*>> SpellPowerContainer;
428typedef std::unordered_map<uint32, std::unordered_map<uint32, std::vector<SpellPowerEntry const*>>> SpellPowerDifficultyContainer;
431typedef std::unordered_set<uint32> ToyItemIdsContainer;
434typedef std::pair<uint32 /*tableHash*/, int32 /*recordId*/> HotfixBlobKey;
435typedef std::map<HotfixBlobKey, std::vector<uint8>> HotfixBlobMap;
436using AllowedHotfixOptionalData = std::pair<uint32 /*optional data key*/, bool(*)(std::vector<uint8> const& data) /*validator*/>;
437
438namespace
439{
440 struct UiMapBounds
441 {
442 // these coords are mixed when calculated and used... its a mess
443 float Bounds[4];
444 bool IsUiAssignment;
445 bool IsUiLink;
446 };
447
448 StorageMap _stores;
449 DB2Manager::HotfixContainer _hotfixData;
450 std::array<HotfixBlobMap, TOTAL_LOCALES> _hotfixBlob;
451 std::unordered_multimap<uint32 /*tableHash*/, AllowedHotfixOptionalData> _allowedHotfixOptionalData;
452 std::array<std::map<HotfixBlobKey, std::vector<DB2Manager::HotfixOptionalData>>, TOTAL_LOCALES> _hotfixOptionalData;
453
454 AreaGroupMemberContainer _areaGroupMembers;
455 ArtifactPowersContainer _artifactPowers;
456 ArtifactPowerLinksContainer _artifactPowerLinks;
457 ArtifactPowerRanksContainer _artifactPowerRanks;
458 std::unordered_map<uint32 /*itemId*/, AzeriteEmpoweredItemEntry const*> _azeriteEmpoweredItems;
459 std::unordered_map<std::pair<uint32 /*azeriteEssenceId*/, uint32 /*rank*/>, AzeriteEssencePowerEntry const*> _azeriteEssencePowersByIdAndRank;
460 std::vector<AzeriteItemMilestonePowerEntry const*> _azeriteItemMilestonePowers;
461 std::array<AzeriteItemMilestonePowerEntry const*, MAX_AZERITE_ESSENCE_SLOT> _azeriteItemMilestonePowerByEssenceSlot;
462 std::unordered_map<uint32 /*azeritePowerSetId*/, std::vector<AzeritePowerSetMemberEntry const*>> _azeritePowers;
463 std::unordered_map<std::pair<uint32 /*azeriteUnlockSetId*/, ItemContext>, std::array<uint8, MAX_AZERITE_EMPOWERED_TIER>> _azeriteTierUnlockLevels;
464 std::unordered_map<std::pair<uint32 /*broadcastTextId*/, CascLocaleBit /*cascLocaleBit*/>, int32> _broadcastTextDurations;
465 std::unordered_map<std::pair<uint8, uint8>, CharBaseInfoEntry const*> _charBaseInfoByRaceAndClass;
466 std::array<ChrClassUIDisplayEntry const*, MAX_CLASSES> _uiDisplayByClass;
467 std::array<std::array<uint32, MAX_POWERS>, MAX_CLASSES> _powersByClass;
468 std::unordered_map<uint32 /*chrCustomizationOptionId*/, std::vector<ChrCustomizationChoiceEntry const*>> _chrCustomizationChoicesByOption;
469 std::unordered_map<std::pair<uint8, uint8>, ChrModelEntry const*> _chrModelsByRaceAndGender;
470 std::map<std::tuple<uint8 /*race*/, uint8/*gender*/, uint8/*shapeshift*/>, ShapeshiftFormModelData> _chrCustomizationChoicesForShapeshifts;
471 std::unordered_map<std::pair<uint8 /*race*/, uint8/*gender*/>, std::vector<ChrCustomizationOptionEntry const*>> _chrCustomizationOptionsByRaceAndGender;
472 std::unordered_map<uint32 /*chrCustomizationReqId*/, std::vector<std::pair<uint32 /*chrCustomizationOptionId*/, std::vector<uint32>>>> _chrCustomizationRequiredChoices;
473 ChrSpecializationByIndexContainer _chrSpecializationsByIndex;
474 std::unordered_map<int32, ConditionalChrModelEntry const*> _conditionalChrModelsByChrModelId;
475 std::unordered_map<uint32 /*contentTuningId*/, std::vector<ConditionalContentTuningEntry const*>> _conditionalContentTuning;
476 std::unordered_set<std::pair<uint32, int32>> _contentTuningLabels;
477 std::unordered_map<uint32 /*creatureDifficultyId*/, std::vector<int32>> _creatureLabels;
478 std::unordered_multimap<uint32, CurrencyContainerEntry const*> _currencyContainers;
479 CurvePointsContainer _curvePoints;
480 EmotesTextSoundContainer _emoteTextSounds;
481 std::unordered_map<std::pair<uint32 /*level*/, int32 /*expansion*/>, ExpectedStatEntry const*> _expectedStatsByLevel;
482 std::unordered_map<uint32 /*contentTuningId*/, std::vector<ContentTuningXExpectedEntry const*>> _expectedStatModsByContentTuning;
483 FactionTeamContainer _factionTeams;
484 std::unordered_map<uint32, std::set<FriendshipRepReactionEntry const*, DB2Manager::FriendshipRepReactionEntryComparator>> _friendshipRepReactions;
485 HeirloomItemsContainer _heirlooms;
486 std::unordered_map<uint32 /*gameobjectId*/, std::vector<int32>> _gameobjectLabels;
487 GlyphBindableSpellsContainer _glyphBindableSpells;
488 GlyphRequiredSpecsContainer _glyphRequiredSpecs;
489 ItemChildEquipmentContainer _itemChildEquipment;
490 ItemClassByOldEnumContainer _itemClassByOldEnum;
491 std::unordered_set<uint32> _itemsWithCurrencyCost;
492 ItemLimitCategoryConditionContainer _itemCategoryConditions;
493 ItemModifiedAppearanceByItemContainer _itemModifiedAppearancesByItem;
494 ItemSetSpellContainer _itemSetSpells;
495 ItemSpecOverridesContainer _itemSpecOverrides;
496 std::vector<JournalTierEntry const*> _journalTiersByIndex;
497 MapDifficultyContainer _mapDifficulties;
498 std::unordered_map<uint32, DB2Manager::MapDifficultyConditionsContainer> _mapDifficultyConditions;
499 std::unordered_map<uint32, MountEntry const*> _mountsBySpellId;
500 MountCapabilitiesByTypeContainer _mountCapabilitiesByType;
501 MountDisplaysCointainer _mountDisplays;
502 NameGenContainer _nameGenData;
503 NameValidationRegexContainer _nameValidators;
504 std::unordered_map<uint32, ParagonReputationEntry const*> _paragonReputations;
505 std::unordered_map<uint32 /*pathID*/, PathDb2> _paths;
506 PhaseGroupContainer _phasesByGroup;
507 PowerTypesContainer _powerTypes;
508 std::unordered_map<uint32, uint8> _pvpItemBonus;
509 PvpTalentSlotUnlockEntry const* _pvpTalentSlotUnlock[MAX_PVP_TALENT_SLOTS];
510 std::unordered_map<uint32, std::vector<QuestLineXQuestEntry const*>> _questsByQuestLine;
511 QuestPackageItemContainer _questPackages;
512 std::unordered_map<uint32, std::vector<RewardPackXCurrencyTypeEntry const*>> _rewardPackCurrencyTypes;
513 std::unordered_map<uint32, std::vector<RewardPackXItemEntry const*>> _rewardPackItems;
514 std::unordered_map<uint32, std::vector<SkillLineEntry const*>> _skillLinesByParentSkillLine;
515 std::unordered_map<uint32, std::vector<SkillLineAbilityEntry const*>> _skillLineAbilitiesBySkillupSkill;
516 SkillRaceClassInfoContainer _skillRaceClassInfoBySkill;
517 std::unordered_map<std::pair<int32, int32>, SoulbindConduitRankEntry const*> _soulbindConduitRanks;
518 SpecializationSpellsContainer _specializationSpellsBySpec;
519 std::unordered_set<std::pair<int32, uint32>> _specsBySpecSet;
520 std::unordered_set<uint8> _spellFamilyNames;
521 SpellProcsPerMinuteModContainer _spellProcsPerMinuteMods;
522 std::unordered_map<int32, std::vector<SpellVisualMissileEntry const*>> _spellVisualMissilesBySet;
523 TalentsByPosition _talentsByPosition;
524 std::unordered_map<std::pair<uint32, uint32>, TaxiPathEntry const*> _taxiPaths;
526 std::unordered_map<uint32, TransmogIllusionEntry const*> _transmogIllusionsByEnchantmentId;
527 std::unordered_map<uint32, std::vector<TransmogSetEntry const*>> _transmogSetsByItemModifiedAppearance;
528 std::unordered_map<uint32, std::vector<TransmogSetItemEntry const*>> _transmogSetItemsByTransmogSet;
529 std::unordered_map<int32, UiMapBounds> _uiMapBounds;
530 std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByMap[MAX_UI_MAP_SYSTEM];
531 std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByArea[MAX_UI_MAP_SYSTEM];
532 std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByWmoDoodadPlacement[MAX_UI_MAP_SYSTEM];
533 std::unordered_multimap<int32, UiMapAssignmentEntry const*> _uiMapAssignmentByWmoGroup[MAX_UI_MAP_SYSTEM];
534 std::unordered_set<int32> _uiMapPhases;
535 WMOAreaTableLookupContainer _wmoAreaTableLookup;
536 std::unordered_map<uint32, std::unordered_set<uint32>> _pvpStatIdsByMap;
537}
538
539void LoadDB2(std::bitset<TOTAL_LOCALES>& availableDb2Locales, std::vector<std::string>& errlist, StorageMap& stores, DB2StorageBase* storage, std::string const& db2Path,
540 LocaleConstant defaultLocale, std::size_t cppRecordSize)
541{
542 // validate structure
543 {
544 DB2LoadInfo const* loadInfo = storage->GetLoadInfo();
545 std::string clientMetaString, ourMetaString;
546 for (std::size_t i = 0; i < loadInfo->Meta->FieldCount; ++i)
547 {
548 for (std::size_t j = 0; j < loadInfo->Meta->Fields[i].ArraySize; ++j)
549 {
550 if (i >= loadInfo->Meta->FileFieldCount && int32(i) == loadInfo->Meta->ParentIndexField)
551 {
552 clientMetaString += char(FT_INT);
553 continue;
554 }
555
556 clientMetaString += char(loadInfo->Meta->Fields[i].Type);
557 }
558 }
559
560 for (std::size_t i = loadInfo->Meta->HasIndexFieldInData() ? 0 : 1; i < loadInfo->FieldCount; ++i)
561 ourMetaString += char(loadInfo->Fields[i].Type);
562
563 ASSERT(clientMetaString == ourMetaString,
564 "%s C++ structure fields %s do not match generated types from the client %s",
565 storage->GetFileName().c_str(), ourMetaString.c_str(), clientMetaString.c_str());
566
567 // compatibility format and C++ structure sizes
568 ASSERT(loadInfo->Meta->GetRecordSize() == cppRecordSize,
569 "Size of '%s' set by format string (%u) not equal size of C++ structure (" SZFMTD ").",
570 storage->GetFileName().c_str(), loadInfo->Meta->GetRecordSize(), cppRecordSize);
571 }
572
573 try
574 {
575 storage->Load(db2Path + localeNames[defaultLocale] + '/', defaultLocale);
576 }
577 catch (std::system_error const& e)
578 {
579 if (e.code() == std::errc::no_such_file_or_directory)
580 {
581 errlist.push_back(Trinity::StringFormat("File {}{}/{} does not exist", db2Path, localeNames[defaultLocale], storage->GetFileName()));
582 }
583 else
584 throw;
585 }
586 catch (std::exception const& e)
587 {
588 errlist.emplace_back(e.what());
589 return;
590 }
591
592 // load additional data and enUS strings from db
593 storage->LoadFromDB();
594
595 for (LocaleConstant i = LOCALE_enUS; i < TOTAL_LOCALES; i = LocaleConstant(i + 1))
596 {
597 if (defaultLocale == i || !availableDb2Locales[i])
598 continue;
599
600 try
601 {
602 storage->LoadStringsFrom((db2Path + localeNames[i] + '/'), i);
603 }
604 catch (std::system_error const& e)
605 {
606 if (e.code() != std::errc::no_such_file_or_directory)
607 throw;
608
609 // locale db2 files are optional, do not error if nothing is found
610 }
611 catch (std::exception const& e)
612 {
613 errlist.emplace_back(e.what());
614 }
615 }
616
617 for (LocaleConstant i = LOCALE_koKR; i < TOTAL_LOCALES; i = LocaleConstant(i + 1))
618 if (availableDb2Locales[i])
619 storage->LoadStringsFromDB(i);
620
621 stores[storage->GetTableHash()] = storage;
622}
623
625{
626 static DB2Manager instance;
627 return instance;
628}
629
630uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaultLocale)
631{
632 uint32 oldMSTime = getMSTime();
633
634 std::string db2Path = dataPath + "dbc/";
635
636 std::vector<std::string> loadErrors;
637 std::bitset<TOTAL_LOCALES> availableDb2Locales = [&]()
638 {
639 std::bitset<TOTAL_LOCALES> foundLocales;
640 boost::filesystem::directory_iterator db2PathItr(db2Path), end;
641 while (db2PathItr != end)
642 {
643 LocaleConstant locale = GetLocaleByName(db2PathItr->path().filename().string());
644 if (IsValidLocale(locale) && (sWorld->getBoolConfig(CONFIG_LOAD_LOCALES) || locale == defaultLocale))
645 foundLocales[locale] = true;
646
647 ++db2PathItr;
648 }
649 return foundLocales;
650 }();
651
652 if (!availableDb2Locales[defaultLocale])
653 return 0;
654
655 auto LOAD_DB2 = [&]<typename T>(DB2Storage<T>& store)
656 {
657 LoadDB2(availableDb2Locales, loadErrors, _stores, &store, db2Path, defaultLocale, sizeof(T));
658 };
659
660 LOAD_DB2(sAchievementStore);
662 LOAD_DB2(sAdventureJournalStore);
663 LOAD_DB2(sAdventureMapPOIStore);
664 LOAD_DB2(sAnimationDataStore);
665 LOAD_DB2(sAnimKitStore);
666 LOAD_DB2(sAreaGroupMemberStore);
667 LOAD_DB2(sAreaTableStore);
668 LOAD_DB2(sAreaTriggerStore);
670 LOAD_DB2(sArmorLocationStore);
671 LOAD_DB2(sArtifactStore);
672 LOAD_DB2(sArtifactAppearanceStore);
674 LOAD_DB2(sArtifactCategoryStore);
675 LOAD_DB2(sArtifactPowerStore);
676 LOAD_DB2(sArtifactPowerLinkStore);
678 LOAD_DB2(sArtifactPowerRankStore);
679 LOAD_DB2(sArtifactTierStore);
680 LOAD_DB2(sArtifactUnlockStore);
681 LOAD_DB2(sAuctionHouseStore);
683 LOAD_DB2(sAzeriteEssenceStore);
685 LOAD_DB2(sAzeriteItemStore);
688 LOAD_DB2(sAzeriteLevelInfoStore);
689 LOAD_DB2(sAzeritePowerStore);
691 LOAD_DB2(sAzeriteTierUnlockStore);
694 LOAD_DB2(sBankBagSlotPricesStore);
695 LOAD_DB2(sBannedAddonsStore);
696 LOAD_DB2(sBarberShopStyleStore);
697 LOAD_DB2(sBattlePetAbilityStore);
700 LOAD_DB2(sBattlePetSpeciesStore);
702 LOAD_DB2(sBattlemasterListStore);
704 LOAD_DB2(sBroadcastTextStore);
706 LOAD_DB2(sCfgCategoriesStore);
707 LOAD_DB2(sCfgRegionsStore);
709 LOAD_DB2(sCharBaseInfoStore);
710 LOAD_DB2(sCharTitlesStore);
711 LOAD_DB2(sCharacterLoadoutStore);
713 LOAD_DB2(sChatChannelsStore);
714 LOAD_DB2(sChrClassUIDisplayStore);
715 LOAD_DB2(sChrClassesStore);
723 LOAD_DB2(sChrModelStore);
724 LOAD_DB2(sChrRaceXChrModelStore);
725 LOAD_DB2(sChrRacesStore);
726 LOAD_DB2(sChrSpecializationStore);
727 LOAD_DB2(sCinematicCameraStore);
728 LOAD_DB2(sCinematicSequencesStore);
731 LOAD_DB2(sContentTuningStore);
734 LOAD_DB2(sConversationLineStore);
735 LOAD_DB2(sCorruptionEffectsStore);
738 LOAD_DB2(sCreatureFamilyStore);
739 LOAD_DB2(sCreatureLabelStore);
740 LOAD_DB2(sCreatureModelDataStore);
741 LOAD_DB2(sCreatureTypeStore);
742 LOAD_DB2(sCriteriaStore);
743 LOAD_DB2(sCriteriaTreeStore);
744 LOAD_DB2(sCurrencyContainerStore);
745 LOAD_DB2(sCurrencyTypesStore);
746 LOAD_DB2(sCurveStore);
747 LOAD_DB2(sCurvePointStore);
749 LOAD_DB2(sDifficultyStore);
750 LOAD_DB2(sDungeonEncounterStore);
751 LOAD_DB2(sDurabilityCostsStore);
752 LOAD_DB2(sDurabilityQualityStore);
753 LOAD_DB2(sEmotesStore);
754 LOAD_DB2(sEmotesTextStore);
755 LOAD_DB2(sEmotesTextSoundStore);
756 LOAD_DB2(sExpectedStatStore);
757 LOAD_DB2(sExpectedStatModStore);
758 LOAD_DB2(sFactionStore);
759 LOAD_DB2(sFactionTemplateStore);
760 LOAD_DB2(sFlightCapabilityStore);
763 LOAD_DB2(sGameObjectsStore);
764 LOAD_DB2(sGameObjectArtKitStore);
766 LOAD_DB2(sGameObjectLabelStore);
767 LOAD_DB2(sGarrAbilityStore);
768 LOAD_DB2(sGarrBuildingStore);
770 LOAD_DB2(sGarrClassSpecStore);
771 LOAD_DB2(sGarrFollowerStore);
773 LOAD_DB2(sGarrMissionStore);
774 LOAD_DB2(sGarrPlotStore);
775 LOAD_DB2(sGarrPlotBuildingStore);
776 LOAD_DB2(sGarrPlotInstanceStore);
777 LOAD_DB2(sGarrSiteLevelStore);
779 LOAD_DB2(sGarrTalentTreeStore);
780 LOAD_DB2(sGemPropertiesStore);
781 LOAD_DB2(sGlobalCurveStore);
782 LOAD_DB2(sGlyphBindableSpellStore);
783 LOAD_DB2(sGlyphPropertiesStore);
784 LOAD_DB2(sGlyphRequiredSpecStore);
785 LOAD_DB2(sGossipNPCOptionStore);
787 LOAD_DB2(sGuildColorBorderStore);
788 LOAD_DB2(sGuildColorEmblemStore);
789 LOAD_DB2(sGuildPerkSpellsStore);
790 LOAD_DB2(sHeirloomStore);
791 LOAD_DB2(sHolidaysStore);
792 LOAD_DB2(sImportPriceArmorStore);
793 LOAD_DB2(sImportPriceQualityStore);
794 LOAD_DB2(sImportPriceShieldStore);
795 LOAD_DB2(sImportPriceWeaponStore);
796 LOAD_DB2(sItemAppearanceStore);
797 LOAD_DB2(sItemArmorQualityStore);
798 LOAD_DB2(sItemArmorShieldStore);
799 LOAD_DB2(sItemArmorTotalStore);
800 LOAD_DB2(sItemBagFamilyStore);
801 LOAD_DB2(sItemBonusStore);
804 LOAD_DB2(sItemBonusTreeStore);
805 LOAD_DB2(sItemBonusTreeNodeStore);
806 LOAD_DB2(sItemChildEquipmentStore);
807 LOAD_DB2(sItemClassStore);
809 LOAD_DB2(sItemCurrencyCostStore);
810 LOAD_DB2(sItemDamageAmmoStore);
811 LOAD_DB2(sItemDamageOneHandStore);
813 LOAD_DB2(sItemDamageTwoHandStore);
815 LOAD_DB2(sItemDisenchantLootStore);
816 LOAD_DB2(sItemEffectStore);
817 LOAD_DB2(sItemStore);
818 LOAD_DB2(sItemExtendedCostStore);
819 LOAD_DB2(sItemLevelSelectorStore);
822 LOAD_DB2(sItemLimitCategoryStore);
827 LOAD_DB2(sItemPriceBaseStore);
828 LOAD_DB2(sItemSearchNameStore);
829 LOAD_DB2(sItemSetStore);
830 LOAD_DB2(sItemSetSpellStore);
831 LOAD_DB2(sItemSparseStore);
832 LOAD_DB2(sItemSpecStore);
833 LOAD_DB2(sItemSpecOverrideStore);
834 LOAD_DB2(sItemXBonusTreeStore);
835 LOAD_DB2(sItemXItemEffectStore);
836 LOAD_DB2(sJournalEncounterStore);
838 LOAD_DB2(sJournalInstanceStore);
839 LOAD_DB2(sJournalTierStore);
840 LOAD_DB2(sKeychainStore);
841 LOAD_DB2(sKeystoneAffixStore);
842 LOAD_DB2(sLanguageWordsStore);
843 LOAD_DB2(sLanguagesStore);
844 LOAD_DB2(sLFGDungeonsStore);
845 LOAD_DB2(sLightStore);
846 LOAD_DB2(sLiquidTypeStore);
847 LOAD_DB2(sLocationStore);
848 LOAD_DB2(sLockStore);
849 LOAD_DB2(sMailTemplateStore);
850 LOAD_DB2(sMapStore);
851 LOAD_DB2(sMapChallengeModeStore);
852 LOAD_DB2(sMapDifficultyStore);
854 LOAD_DB2(sMawPowerStore);
855 LOAD_DB2(sModifierTreeStore);
856 LOAD_DB2(sMountCapabilityStore);
857 LOAD_DB2(sMountStore);
858 LOAD_DB2(sMountEquipmentStore);
860 LOAD_DB2(sMountXDisplayStore);
861 LOAD_DB2(sMovieStore);
862 LOAD_DB2(sMythicPlusSeasonStore);
863 LOAD_DB2(sNameGenStore);
864 LOAD_DB2(sNamesProfanityStore);
865 LOAD_DB2(sNamesReservedStore);
867 LOAD_DB2(sNumTalentsAtLevelStore);
868 LOAD_DB2(sOverrideSpellDataStore);
869 LOAD_DB2(sParagonReputationStore);
870 LOAD_DB2(sPathStore);
871 LOAD_DB2(sPathNodeStore);
872 LOAD_DB2(sPathPropertyStore);
873 LOAD_DB2(sPhaseStore);
874 LOAD_DB2(sPhaseXPhaseGroupStore);
875 LOAD_DB2(sPlayerConditionStore);
876 LOAD_DB2(sPowerDisplayStore);
877 LOAD_DB2(sPowerTypeStore);
878 LOAD_DB2(sPrestigeLevelInfoStore);
879 LOAD_DB2(sPVPDifficultyStore);
880 LOAD_DB2(sPVPItemStore);
881 LOAD_DB2(sPVPStatStore);
882 LOAD_DB2(sPvpSeasonStore);
883 LOAD_DB2(sPvpTalentStore);
884 LOAD_DB2(sPvpTalentCategoryStore);
886 LOAD_DB2(sPvpTierStore);
887 LOAD_DB2(sQuestFactionRewardStore);
888 LOAD_DB2(sQuestInfoStore);
889 LOAD_DB2(sQuestLineXQuestStore);
890 LOAD_DB2(sQuestMoneyRewardStore);
891 LOAD_DB2(sQuestPackageItemStore);
892 LOAD_DB2(sQuestSortStore);
893 LOAD_DB2(sQuestV2Store);
894 LOAD_DB2(sQuestXPStore);
895 LOAD_DB2(sRandPropPointsStore);
896 LOAD_DB2(sRewardPackStore);
898 LOAD_DB2(sRewardPackXItemStore);
899 LOAD_DB2(sScenarioStore);
900 LOAD_DB2(sScenarioStepStore);
901 LOAD_DB2(sSceneScriptStore);
903 LOAD_DB2(sSceneScriptPackageStore);
904 LOAD_DB2(sSceneScriptTextStore);
905 LOAD_DB2(sServerMessagesStore);
906 LOAD_DB2(sSkillLineStore);
907 LOAD_DB2(sSkillLineAbilityStore);
909 LOAD_DB2(sSkillRaceClassInfoStore);
911 LOAD_DB2(sSoundKitStore);
913 LOAD_DB2(sSpecSetMemberStore);
914 LOAD_DB2(sSpellAuraOptionsStore);
916 LOAD_DB2(sSpellCastTimesStore);
918 LOAD_DB2(sSpellCategoriesStore);
919 LOAD_DB2(sSpellCategoryStore);
920 LOAD_DB2(sSpellClassOptionsStore);
921 LOAD_DB2(sSpellCooldownsStore);
922 LOAD_DB2(sSpellDurationStore);
923 LOAD_DB2(sSpellEffectStore);
924 LOAD_DB2(sSpellEquippedItemsStore);
925 LOAD_DB2(sSpellEmpowerStore);
926 LOAD_DB2(sSpellEmpowerStageStore);
927 LOAD_DB2(sSpellFocusObjectStore);
928 LOAD_DB2(sSpellInterruptsStore);
932 LOAD_DB2(sSpellLabelStore);
933 LOAD_DB2(sSpellLearnSpellStore);
934 LOAD_DB2(sSpellLevelsStore);
935 LOAD_DB2(sSpellMiscStore);
936 LOAD_DB2(sSpellNameStore);
937 LOAD_DB2(sSpellPowerStore);
941 LOAD_DB2(sSpellRadiusStore);
942 LOAD_DB2(sSpellRangeStore);
943 LOAD_DB2(sSpellReagentsStore);
945 LOAD_DB2(sSpellScalingStore);
946 LOAD_DB2(sSpellShapeshiftStore);
949 LOAD_DB2(sSpellTotemsStore);
950 LOAD_DB2(sSpellVisualStore);
952 LOAD_DB2(sSpellVisualMissileStore);
953 LOAD_DB2(sSpellVisualKitStore);
954 LOAD_DB2(sSpellXSpellVisualStore);
955 LOAD_DB2(sSummonPropertiesStore);
956 LOAD_DB2(sTactKeyStore);
957 LOAD_DB2(sTalentStore);
958 LOAD_DB2(sTaxiNodesStore);
959 LOAD_DB2(sTaxiPathStore);
960 LOAD_DB2(sTaxiPathNodeStore);
961 LOAD_DB2(sTotemCategoryStore);
962 LOAD_DB2(sToyStore);
963 LOAD_DB2(sTraitCondStore);
964 LOAD_DB2(sTraitCostStore);
965 LOAD_DB2(sTraitCurrencyStore);
967 LOAD_DB2(sTraitDefinitionStore);
969 LOAD_DB2(sTraitEdgeStore);
970 LOAD_DB2(sTraitNodeStore);
971 LOAD_DB2(sTraitNodeEntryStore);
974 LOAD_DB2(sTraitNodeGroupStore);
981 LOAD_DB2(sTraitSubTreeStore);
982 LOAD_DB2(sTraitTreeStore);
983 LOAD_DB2(sTraitTreeLoadoutStore);
987 LOAD_DB2(sTransmogHolidayStore);
988 LOAD_DB2(sTransmogIllusionStore);
989 LOAD_DB2(sTransmogSetStore);
990 LOAD_DB2(sTransmogSetGroupStore);
991 LOAD_DB2(sTransmogSetItemStore);
992 LOAD_DB2(sTransportAnimationStore);
993 LOAD_DB2(sTransportRotationStore);
994 LOAD_DB2(sUiMapStore);
995 LOAD_DB2(sUiMapAssignmentStore);
996 LOAD_DB2(sUiMapLinkStore);
997 LOAD_DB2(sUiMapXMapArtStore);
998 LOAD_DB2(sUISplashScreenStore);
999 LOAD_DB2(sUnitConditionStore);
1000 LOAD_DB2(sUnitPowerBarStore);
1001 LOAD_DB2(sVehicleStore);
1002 LOAD_DB2(sVehicleSeatStore);
1003 LOAD_DB2(sVignetteStore);
1004 LOAD_DB2(sWMOAreaTableStore);
1005 LOAD_DB2(sWorldEffectStore);
1006 LOAD_DB2(sWorldMapOverlayStore);
1008
1009 // error checks
1010 if (!loadErrors.empty())
1011 {
1012 sLog->SetSynchronous(); // server will shut down after this, so set sync logging to prevent messages from getting lost
1013
1014 for (std::string const& error : loadErrors)
1015 TC_LOG_FATAL("misc", "{}", error);
1016
1017 return 0;
1018 }
1019
1020 // Check loaded DB2 files proper version
1021 if (!sAreaTableStore.LookupEntry(16108) || // last area added in 11.0.7 (58162)
1022 !sCharTitlesStore.LookupEntry(876) || // last char title added in 11.0.7 (58162)
1023 !sFlightCapabilityStore.LookupEntry(1) || // default flight capability (required)
1024 !sGemPropertiesStore.LookupEntry(4266) || // last gem property added in 11.0.7 (58162)
1025 !sItemStore.LookupEntry(235551) || // last item added in 11.0.7 (58162)
1026 !sItemExtendedCostStore.LookupEntry(9918) || // last item extended cost added in 11.0.7 (58162)
1027 !sMapStore.LookupEntry(2829) || // last map added in 11.0.7 (58162)
1028 !sSpellNameStore.LookupEntry(1218101)) // last spell added in 11.0.7 (58162)
1029 {
1030 TC_LOG_FATAL("misc", "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
1031 return 0;
1032 }
1033
1034 TC_LOG_INFO("server.loading", ">> Initialized {} DB2 data stores in {} ms", _stores.size(), GetMSTimeDiffToNow(oldMSTime));
1035
1036 return availableDb2Locales.to_ulong();
1037}
1038
1040{
1041 uint32 oldMSTime = getMSTime();
1042
1043 for (AreaGroupMemberEntry const* areaGroupMember : sAreaGroupMemberStore)
1044 _areaGroupMembers[areaGroupMember->AreaGroupID].push_back(areaGroupMember->AreaID);
1045
1046 for (AreaTableEntry const* areaTable : sAreaTableStore)
1047 {
1048 ASSERT(areaTable->AreaBit <= 0 || (size_t(areaTable->AreaBit / 64) < PLAYER_EXPLORED_ZONES_SIZE),
1049 "PLAYER_EXPLORED_ZONES_SIZE must be at least %d", (areaTable->AreaBit + 63) / 64);
1050 }
1051
1052 for (ArtifactPowerEntry const* artifactPower : sArtifactPowerStore)
1053 _artifactPowers[artifactPower->ArtifactID].push_back(artifactPower);
1054
1055 for (ArtifactPowerLinkEntry const* artifactPowerLink : sArtifactPowerLinkStore)
1056 {
1057 _artifactPowerLinks[artifactPowerLink->PowerA].push_back(artifactPowerLink->PowerB);
1058 _artifactPowerLinks[artifactPowerLink->PowerB].push_back(artifactPowerLink->PowerA);
1059 }
1060
1061 for (ArtifactPowerRankEntry const* artifactPowerRank : sArtifactPowerRankStore)
1062 _artifactPowerRanks[std::pair<uint32, uint8>{ artifactPowerRank->ArtifactPowerID, artifactPowerRank->RankIndex }] = artifactPowerRank;
1063
1064 for (AzeriteEmpoweredItemEntry const* azeriteEmpoweredItem : sAzeriteEmpoweredItemStore)
1065 _azeriteEmpoweredItems[azeriteEmpoweredItem->ItemID] = azeriteEmpoweredItem;
1066
1067 for (AzeriteEssencePowerEntry const* azeriteEssencePower : sAzeriteEssencePowerStore)
1068 _azeriteEssencePowersByIdAndRank[std::pair<uint32, uint32>{ azeriteEssencePower->AzeriteEssenceID, azeriteEssencePower->Tier }] = azeriteEssencePower;
1069
1070 for (AzeriteItemMilestonePowerEntry const* azeriteItemMilestonePower : sAzeriteItemMilestonePowerStore)
1071 _azeriteItemMilestonePowers.push_back(azeriteItemMilestonePower);
1072
1073 std::ranges::sort(_azeriteItemMilestonePowers, {}, &AzeriteItemMilestonePowerEntry::RequiredLevel);
1074
1075 {
1076 uint32 azeriteEssenceSlot = 0;
1077 for (AzeriteItemMilestonePowerEntry const* azeriteItemMilestonePower : _azeriteItemMilestonePowers)
1078 {
1079 AzeriteItemMilestoneType type = AzeriteItemMilestoneType(azeriteItemMilestonePower->Type);
1081 {
1082 ASSERT(azeriteEssenceSlot < MAX_AZERITE_ESSENCE_SLOT);
1083 _azeriteItemMilestonePowerByEssenceSlot[azeriteEssenceSlot] = azeriteItemMilestonePower;
1084 ++azeriteEssenceSlot;
1085 }
1086 }
1087 }
1088
1089 for (AzeritePowerSetMemberEntry const* azeritePowerSetMember : sAzeritePowerSetMemberStore)
1090 if (sAzeritePowerStore.LookupEntry(azeritePowerSetMember->AzeritePowerID))
1091 _azeritePowers[azeritePowerSetMember->AzeritePowerSetID].push_back(azeritePowerSetMember);
1092
1093 for (AzeriteTierUnlockEntry const* azeriteTierUnlock : sAzeriteTierUnlockStore)
1094 _azeriteTierUnlockLevels[std::pair<uint32, ItemContext>{ azeriteTierUnlock->AzeriteTierUnlockSetID, ItemContext(azeriteTierUnlock->ItemCreationContext) }][azeriteTierUnlock->Tier] = azeriteTierUnlock->AzeriteLevel;
1095
1096 for (BattlemasterListEntry const* battlemaster : sBattlemasterListStore)
1097 {
1098 if (battlemaster->MaxLevel < battlemaster->MinLevel)
1099 {
1100 TC_LOG_ERROR("db2.hotfix.battlemaster_list", "Battlemaster ({}) contains bad values for MinLevel ({}) and MaxLevel ({}). Swapping values.", battlemaster->ID, battlemaster->MinLevel, battlemaster->MaxLevel);
1101 std::swap(const_cast<BattlemasterListEntry*>(battlemaster)->MaxLevel, const_cast<BattlemasterListEntry*>(battlemaster)->MinLevel);
1102 }
1103 if (battlemaster->MaxPlayers < battlemaster->MinPlayers)
1104 {
1105 TC_LOG_ERROR("db2.hotfix.battlemaster_list", "Battlemaster ({}) contains bad values for MinPlayers ({}) and MaxPlayers ({}). Swapping values.", battlemaster->ID, battlemaster->MinPlayers, battlemaster->MaxPlayers);
1106 int8 minPlayers = battlemaster->MinPlayers;
1107 const_cast<BattlemasterListEntry*>(battlemaster)->MinPlayers = battlemaster->MaxPlayers;
1108 const_cast<BattlemasterListEntry*>(battlemaster)->MaxPlayers = minPlayers;
1109 }
1110 }
1111
1112 _broadcastTextDurations.reserve(sBroadcastTextDurationStore.GetNumRows());
1113 for (BroadcastTextDurationEntry const* broadcastTextDuration : sBroadcastTextDurationStore)
1114 _broadcastTextDurations[{ broadcastTextDuration->BroadcastTextID, CascLocaleBit(broadcastTextDuration->Locale) }] = broadcastTextDuration->Duration;
1115
1116 for (CharBaseInfoEntry const* charBaseInfo : sCharBaseInfoStore)
1117 _charBaseInfoByRaceAndClass[{ charBaseInfo->RaceID, charBaseInfo->ClassID }] = charBaseInfo;
1118
1119 for (ChrClassUIDisplayEntry const* uiDisplay : sChrClassUIDisplayStore)
1120 {
1121 ASSERT(uiDisplay->ChrClassesID < MAX_CLASSES);
1122 _uiDisplayByClass[uiDisplay->ChrClassesID] = uiDisplay;
1123 }
1124
1125 {
1126 std::set<ChrClassesXPowerTypesEntry const*, ChrClassesXPowerTypesEntryComparator> powers;
1128 powers.insert(power);
1129
1130 for (std::array<uint32, MAX_POWERS>& powersForClass : _powersByClass)
1131 powersForClass.fill(MAX_POWERS);
1132
1133 for (ChrClassesXPowerTypesEntry const* power : powers)
1134 {
1135 uint32 index = 0;
1136 for (uint32 j = 0; j < MAX_POWERS; ++j)
1137 if (_powersByClass[power->ClassID][j] != MAX_POWERS)
1138 ++index;
1139
1140 ASSERT(power->ClassID < MAX_CLASSES);
1141 ASSERT(power->PowerType < MAX_POWERS);
1142 _powersByClass[power->ClassID][power->PowerType] = index;
1143 }
1144 }
1145
1146 for (ChrCustomizationChoiceEntry const* customizationChoice : sChrCustomizationChoiceStore)
1147 _chrCustomizationChoicesByOption[customizationChoice->ChrCustomizationOptionID].push_back(customizationChoice);
1148
1149 std::unordered_multimap<uint32, std::pair<uint32, uint8>> shapeshiftFormByModel;
1150 std::unordered_map<uint32, ChrCustomizationDisplayInfoEntry const*> displayInfoByCustomizationChoice;
1151
1152 // build shapeshift form model lookup
1153 for (ChrCustomizationElementEntry const* customizationElement : sChrCustomizationElementStore)
1154 {
1155 if (ChrCustomizationDisplayInfoEntry const* customizationDisplayInfo = sChrCustomizationDisplayInfoStore.LookupEntry(customizationElement->ChrCustomizationDisplayInfoID))
1156 {
1157 if (ChrCustomizationChoiceEntry const* customizationChoice = sChrCustomizationChoiceStore.LookupEntry(customizationElement->ChrCustomizationChoiceID))
1158 {
1159 displayInfoByCustomizationChoice[customizationElement->ChrCustomizationChoiceID] = customizationDisplayInfo;
1160 if (ChrCustomizationOptionEntry const* customizationOption = sChrCustomizationOptionStore.LookupEntry(customizationChoice->ChrCustomizationOptionID))
1161 shapeshiftFormByModel.emplace(customizationOption->ChrModelID, std::make_pair(customizationOption->ID, uint8(customizationDisplayInfo->ShapeshiftFormID)));
1162 }
1163 }
1164 }
1165
1166 std::unordered_map<uint32, std::vector<ChrCustomizationOptionEntry const*>> customizationOptionsByModel;
1167 for (ChrCustomizationOptionEntry const* customizationOption : sChrCustomizationOptionStore)
1168 customizationOptionsByModel[customizationOption->ChrModelID].push_back(customizationOption);
1169
1171 {
1172 if (ChrCustomizationChoiceEntry const* customizationChoice = sChrCustomizationChoiceStore.LookupEntry(reqChoice->ChrCustomizationChoiceID))
1173 {
1174 std::vector<std::pair<uint32, std::vector<uint32>>>& requiredChoicesForReq = _chrCustomizationRequiredChoices[reqChoice->ChrCustomizationReqID];
1175 std::vector<uint32>* choices = nullptr;
1176 for (std::pair<uint32, std::vector<uint32>>& choicesForOption : requiredChoicesForReq)
1177 {
1178 if (choicesForOption.first == customizationChoice->ChrCustomizationOptionID)
1179 {
1180 choices = &choicesForOption.second;
1181 break;
1182 }
1183 }
1184 if (!choices)
1185 {
1186 std::pair<uint32, std::vector<uint32>>& choicesForReq = requiredChoicesForReq.emplace_back();
1187 choicesForReq.first = customizationChoice->ChrCustomizationOptionID;
1188 choices = &choicesForReq.second;
1189 }
1190 choices->push_back(reqChoice->ChrCustomizationChoiceID);
1191 }
1192 }
1193
1194 std::unordered_map<uint32, uint32> parentRaces;
1195 for (ChrRacesEntry const* chrRace : sChrRacesStore)
1196 if (chrRace->UnalteredVisualRaceID)
1197 parentRaces[chrRace->UnalteredVisualRaceID] = chrRace->ID;
1198
1199 for (ChrRaceXChrModelEntry const* raceModel : sChrRaceXChrModelStore)
1200 {
1201 if (ChrModelEntry const* model = sChrModelStore.LookupEntry(raceModel->ChrModelID))
1202 {
1203 _chrModelsByRaceAndGender[{ uint8(raceModel->ChrRacesID), uint8(raceModel->Sex) }] = model;
1204
1205 if (std::vector<ChrCustomizationOptionEntry const*> const* customizationOptionsForModel = Trinity::Containers::MapGetValuePtr(customizationOptionsByModel, model->ID))
1206 {
1207 std::vector<ChrCustomizationOptionEntry const*>& raceOptions = _chrCustomizationOptionsByRaceAndGender[{ uint8(raceModel->ChrRacesID), uint8(raceModel->Sex) }];
1208 raceOptions.insert(raceOptions.end(), customizationOptionsForModel->begin(), customizationOptionsForModel->end());
1209
1210 if (uint32 const* parentRace = Trinity::Containers::MapGetValuePtr(parentRaces, raceModel->ChrRacesID))
1211 {
1212 std::vector<ChrCustomizationOptionEntry const*>& parentRaceOptions = _chrCustomizationOptionsByRaceAndGender[{ uint8(*parentRace), uint8(raceModel->Sex) }];
1213 parentRaceOptions.insert(parentRaceOptions.end(), customizationOptionsForModel->begin(), customizationOptionsForModel->end());
1214 }
1215 }
1216
1217 // link shapeshift displays to race/gender/form
1218 for (std::pair<uint32 const, std::pair<uint32, uint8>> const& shapeshiftOptionsForModel : Trinity::Containers::MapEqualRange(shapeshiftFormByModel, model->ID))
1219 {
1220 ShapeshiftFormModelData& data = _chrCustomizationChoicesForShapeshifts[{ uint8(raceModel->ChrRacesID), uint8(raceModel->Sex), shapeshiftOptionsForModel.second.second }];
1221 data.OptionID = shapeshiftOptionsForModel.second.first;
1222 data.Choices = Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesByOption, shapeshiftOptionsForModel.second.first);
1223 if (data.Choices)
1224 {
1225 data.Displays.resize(data.Choices->size());
1226 for (std::size_t i = 0; i < data.Choices->size(); ++i)
1227 data.Displays[i] = Trinity::Containers::MapGetValuePtr(displayInfoByCustomizationChoice, (*data.Choices)[i]->ID);
1228 }
1229 }
1230 }
1231 }
1232
1233 memset(_chrSpecializationsByIndex, 0, sizeof(_chrSpecializationsByIndex));
1234 for (ChrSpecializationEntry const* chrSpec : sChrSpecializationStore)
1235 {
1236 ASSERT(chrSpec->ClassID < MAX_CLASSES);
1237 ASSERT(chrSpec->OrderIndex < MAX_SPECIALIZATIONS);
1238
1239 uint32 storageIndex = chrSpec->ClassID;
1240 if (chrSpec->GetFlags().HasFlag(ChrSpecializationFlag::PetOverrideSpec))
1241 {
1242 ASSERT(!chrSpec->ClassID);
1243 storageIndex = PET_SPEC_OVERRIDE_CLASS_INDEX;
1244 }
1245
1246 _chrSpecializationsByIndex[storageIndex][chrSpec->OrderIndex] = chrSpec;
1247 }
1248
1249 for (ConditionalChrModelEntry const* conditionalChrModel : sConditionalChrModelStore)
1250 _conditionalChrModelsByChrModelId[conditionalChrModel->ChrModelID] = conditionalChrModel;
1251
1252 {
1253 for (ConditionalContentTuningEntry const* conditionalContentTuning : sConditionalContentTuningStore)
1254 _conditionalContentTuning[conditionalContentTuning->ParentContentTuningID].push_back(conditionalContentTuning);
1255
1256 for (auto& [parentContentTuningId, conditionalContentTunings] : _conditionalContentTuning)
1257 std::ranges::sort(conditionalContentTunings, std::greater(), &ConditionalContentTuningEntry::OrderIndex);
1258 }
1259
1260 for (ContentTuningXExpectedEntry const* contentTuningXExpectedStat : sContentTuningXExpectedStore)
1261 if (sExpectedStatModStore.LookupEntry(contentTuningXExpectedStat->ExpectedStatModID))
1262 _expectedStatModsByContentTuning[contentTuningXExpectedStat->ContentTuningID].push_back(contentTuningXExpectedStat);
1263
1264 for (ContentTuningXLabelEntry const* contentTuningXLabel : sContentTuningXLabelStore)
1265 _contentTuningLabels.emplace(contentTuningXLabel->ContentTuningID, contentTuningXLabel->LabelID);
1266
1267 for (CreatureLabelEntry const* creatureLabel : sCreatureLabelStore)
1268 _creatureLabels[creatureLabel->CreatureDifficultyID].push_back(creatureLabel->LabelID);
1269
1270 for (CurrencyContainerEntry const* currencyContainer : sCurrencyContainerStore)
1271 _currencyContainers.emplace(currencyContainer->CurrencyTypesID, currencyContainer);
1272
1273 {
1274 std::unordered_map<uint32 /*curveID*/, std::vector<CurvePointEntry const*>> unsortedPoints;
1275 for (CurvePointEntry const* curvePoint : sCurvePointStore)
1276 if (sCurveStore.LookupEntry(curvePoint->CurveID))
1277 unsortedPoints[curvePoint->CurveID].push_back(curvePoint);
1278
1279 for (auto& [curveId, curvePoints] : unsortedPoints)
1280 {
1281 std::ranges::sort(curvePoints, {}, &CurvePointEntry::OrderIndex);
1282 std::vector<DBCPosition2D>& points = _curvePoints[curveId];
1283 points.resize(curvePoints.size());
1284 std::ranges::transform(curvePoints, points.begin(), &CurvePointEntry::Pos);
1285 }
1286 }
1287
1288 for (EmotesTextSoundEntry const* emoteTextSound : sEmotesTextSoundStore)
1289 _emoteTextSounds[EmotesTextSoundContainer::key_type(emoteTextSound->EmotesTextID, emoteTextSound->RaceID, emoteTextSound->SexID, emoteTextSound->ClassID)] = emoteTextSound;
1290
1291 for (ExpectedStatEntry const* expectedStat : sExpectedStatStore)
1292 _expectedStatsByLevel[std::make_pair(expectedStat->Lvl, expectedStat->ExpansionID)] = expectedStat;
1293
1294 for (FactionEntry const* faction : sFactionStore)
1295 if (faction->ParentFactionID)
1296 _factionTeams[faction->ParentFactionID].push_back(faction->ID);
1297
1298 for (FriendshipRepReactionEntry const* friendshipRepReaction : sFriendshipRepReactionStore)
1299 _friendshipRepReactions[friendshipRepReaction->FriendshipRepID].insert(friendshipRepReaction);
1300
1301 for (GameObjectDisplayInfoEntry const* gameObjectDisplayInfo : sGameObjectDisplayInfoStore)
1302 {
1303 if (gameObjectDisplayInfo->GeoBoxMax.X < gameObjectDisplayInfo->GeoBoxMin.X)
1304 std::swap(const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMax.X, const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMin.X);
1305 if (gameObjectDisplayInfo->GeoBoxMax.Y < gameObjectDisplayInfo->GeoBoxMin.Y)
1306 std::swap(const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMax.Y, const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMin.Y);
1307 if (gameObjectDisplayInfo->GeoBoxMax.Z < gameObjectDisplayInfo->GeoBoxMin.Z)
1308 std::swap(const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMax.Z, const_cast<GameObjectDisplayInfoEntry*>(gameObjectDisplayInfo)->GeoBoxMin.Z);
1309 }
1310
1311 for (GameObjectLabelEntry const* gameobjectLabel : sGameObjectLabelStore)
1312 _creatureLabels[gameobjectLabel->GameObjectID].push_back(gameobjectLabel->LabelID);
1313
1314 for (HeirloomEntry const* heirloom : sHeirloomStore)
1315 _heirlooms[heirloom->ItemID] = heirloom;
1316
1317 for (GlyphBindableSpellEntry const* glyphBindableSpell : sGlyphBindableSpellStore)
1318 _glyphBindableSpells[glyphBindableSpell->GlyphPropertiesID].push_back(glyphBindableSpell->SpellID);
1319
1320 for (GlyphRequiredSpecEntry const* glyphRequiredSpec : sGlyphRequiredSpecStore)
1321 _glyphRequiredSpecs[glyphRequiredSpec->GlyphPropertiesID].push_back(ChrSpecialization(glyphRequiredSpec->ChrSpecializationID));
1322
1323 for (ItemChildEquipmentEntry const* itemChildEquipment : sItemChildEquipmentStore)
1324 {
1325 ASSERT(_itemChildEquipment.find(itemChildEquipment->ParentItemID) == _itemChildEquipment.end(), "Item must have max 1 child item.");
1326 _itemChildEquipment[itemChildEquipment->ParentItemID] = itemChildEquipment;
1327 }
1328
1329 for (ItemClassEntry const* itemClass : sItemClassStore)
1330 {
1331 ASSERT(itemClass->ClassID < int32(_itemClassByOldEnum.size()));
1332 ASSERT(!_itemClassByOldEnum[itemClass->ClassID]);
1333 _itemClassByOldEnum[itemClass->ClassID] = itemClass;
1334 }
1335
1336 for (ItemCurrencyCostEntry const* itemCurrencyCost : sItemCurrencyCostStore)
1337 _itemsWithCurrencyCost.insert(itemCurrencyCost->ItemID);
1338
1340 _itemCategoryConditions[condition->ParentItemLimitCategoryID].push_back(condition);
1341
1343 {
1344 ASSERT(appearanceMod->ItemID <= 0xFFFFFF);
1345 _itemModifiedAppearancesByItem[appearanceMod->ItemID | (appearanceMod->ItemAppearanceModifierID << 24)] = appearanceMod;
1346 }
1347
1348 for (ItemSetSpellEntry const* itemSetSpell : sItemSetSpellStore)
1349 _itemSetSpells[itemSetSpell->ItemSetID].push_back(itemSetSpell);
1350
1351 for (ItemSpecOverrideEntry const* itemSpecOverride : sItemSpecOverrideStore)
1352 _itemSpecOverrides[itemSpecOverride->ItemID].push_back(itemSpecOverride);
1353
1354 for (JournalTierEntry const* journalTier : sJournalTierStore)
1355 _journalTiersByIndex.push_back(journalTier);
1356
1357 for (MapDifficultyEntry const* entry : sMapDifficultyStore)
1358 _mapDifficulties[entry->MapID][entry->DifficultyID] = entry;
1359
1360 std::vector<MapDifficultyXConditionEntry const*> mapDifficultyConditions;
1361 mapDifficultyConditions.reserve(sMapDifficultyXConditionStore.GetNumRows());
1362 for (MapDifficultyXConditionEntry const* mapDifficultyCondition : sMapDifficultyXConditionStore)
1363 mapDifficultyConditions.push_back(mapDifficultyCondition);
1364
1365 std::ranges::sort(mapDifficultyConditions, {}, &MapDifficultyXConditionEntry::OrderIndex);
1366
1367 for (MapDifficultyXConditionEntry const* mapDifficultyCondition : mapDifficultyConditions)
1368 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mapDifficultyCondition->PlayerConditionID))
1369 _mapDifficultyConditions[mapDifficultyCondition->MapDifficultyID].emplace_back(mapDifficultyCondition->ID, playerCondition);
1370
1371 for (MountEntry const* mount : sMountStore)
1372 _mountsBySpellId[mount->SourceSpellID] = mount;
1373
1374 for (MountTypeXCapabilityEntry const* mountTypeCapability : sMountTypeXCapabilityStore)
1375 _mountCapabilitiesByType[mountTypeCapability->MountTypeID].insert(mountTypeCapability);
1376
1377 for (MountXDisplayEntry const* mountDisplay : sMountXDisplayStore)
1378 _mountDisplays[mountDisplay->MountID].push_back(mountDisplay);
1379
1380 for (NameGenEntry const* nameGen : sNameGenStore)
1381 _nameGenData[nameGen->RaceID][nameGen->Sex].push_back(nameGen);
1382
1383 for (NamesProfanityEntry const* namesProfanity : sNamesProfanityStore)
1384 {
1385 ASSERT(namesProfanity->Language < TOTAL_LOCALES || namesProfanity->Language == -1);
1386 std::wstring name;
1387 bool conversionResult = Utf8toWStr(namesProfanity->Name, name);
1388 ASSERT(conversionResult);
1389 if (namesProfanity->Language != -1)
1390 _nameValidators[namesProfanity->Language].emplace_back(name, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
1391 else
1392 {
1393 for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
1394 {
1395 if (i == LOCALE_none)
1396 continue;
1397
1398 _nameValidators[i].emplace_back(name, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
1399 }
1400 }
1401 }
1402
1403 for (NamesReservedEntry const* namesReserved : sNamesReservedStore)
1404 {
1405 std::wstring name;
1406 bool conversionResult = Utf8toWStr(namesReserved->Name, name);
1407 ASSERT(conversionResult);
1408 _nameValidators[TOTAL_LOCALES].emplace_back(name, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
1409 }
1410
1411 for (NamesReservedLocaleEntry const* namesReserved : sNamesReservedLocaleStore)
1412 {
1413 ASSERT(!(namesReserved->LocaleMask & ~((1u << TOTAL_LOCALES) - 1)));
1414 std::wstring name;
1415 bool conversionResult = Utf8toWStr(namesReserved->Name, name);
1416 ASSERT(conversionResult);
1417 for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
1418 {
1419 if (i == LOCALE_none)
1420 continue;
1421
1422 if (namesReserved->LocaleMask & (1 << i))
1423 _nameValidators[i].emplace_back(name, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize);
1424 }
1425 }
1426
1427 for (ParagonReputationEntry const* paragonReputation : sParagonReputationStore)
1428 if (sFactionStore.HasRecord(paragonReputation->FactionID))
1429 _paragonReputations[paragonReputation->FactionID] = paragonReputation;
1430
1431 {
1432 std::unordered_map<uint32 /*pathID*/, std::vector<PathNodeEntry const*>> unsortedNodes;
1433 for (PathNodeEntry const* pathNode : sPathNodeStore)
1434 if (sPathStore.HasRecord(pathNode->PathID) && sLocationStore.HasRecord(pathNode->LocationID))
1435 unsortedNodes[pathNode->PathID].push_back(pathNode);
1436
1437 for (auto&& [pathId, pathNodes] : unsortedNodes)
1438 {
1439 PathDb2& path = _paths[pathId];
1440
1441 path.Locations.resize(pathNodes.size());
1442 std::ranges::sort(pathNodes, std::ranges::less(), &PathNodeEntry::Sequence);
1443 std::ranges::transform(pathNodes, path.Locations.begin(), [](PathNodeEntry const* node)
1444 {
1445 return sLocationStore.AssertEntry(node->LocationID)->Pos;
1446 });
1447 }
1448
1449 for (PathPropertyEntry const* pathProperty : sPathPropertyStore)
1450 if (sPathStore.HasRecord(pathProperty->PathID))
1451 _paths[pathProperty->PathID].Properties.push_back(pathProperty);
1452 }
1453
1455 if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseID))
1456 _phasesByGroup[group->PhaseGroupID].push_back(phase->ID);
1457
1458 for (PowerTypeEntry const* powerType : sPowerTypeStore)
1459 {
1460 ASSERT(powerType->PowerTypeEnum < MAX_POWERS);
1461 ASSERT(!_powerTypes[powerType->PowerTypeEnum]);
1462
1463 _powerTypes[powerType->PowerTypeEnum] = powerType;
1464 }
1465
1466 for (PVPDifficultyEntry const* entry : sPVPDifficultyStore)
1467 {
1468 ASSERT(entry->RangeIndex < MAX_BATTLEGROUND_BRACKETS, "PvpDifficulty bracket (%d) exceeded max allowed value (%d)", entry->RangeIndex, MAX_BATTLEGROUND_BRACKETS);
1469 }
1470
1471 for (PVPItemEntry const* pvpItem : sPVPItemStore)
1472 _pvpItemBonus[pvpItem->ItemID] = pvpItem->ItemLevelDelta;
1473
1474 for (PvpTalentSlotUnlockEntry const* talentUnlock : sPvpTalentSlotUnlockStore)
1475 {
1476 ASSERT(talentUnlock->Slot < (1 << MAX_PVP_TALENT_SLOTS));
1477 for (int8 i = 0; i < MAX_PVP_TALENT_SLOTS; ++i)
1478 {
1479 if (talentUnlock->Slot & (1 << i))
1480 {
1481 ASSERT(!_pvpTalentSlotUnlock[i]);
1482 _pvpTalentSlotUnlock[i] = talentUnlock;
1483 }
1484 }
1485 }
1486
1487 {
1488 for (QuestLineXQuestEntry const* questLineQuest : sQuestLineXQuestStore)
1489 _questsByQuestLine[questLineQuest->QuestLineID].push_back(questLineQuest);
1490
1491 for (auto& [questLineId, questLineQuests] : _questsByQuestLine)
1492 std::ranges::sort(questLineQuests, std::ranges::less(), &QuestLineXQuestEntry::OrderIndex);
1493 }
1494
1495 for (QuestPackageItemEntry const* questPackageItem : sQuestPackageItemStore)
1496 {
1497 if (questPackageItem->DisplayType != QUEST_PACKAGE_FILTER_UNMATCHED)
1498 _questPackages[questPackageItem->PackageID].first.push_back(questPackageItem);
1499 else
1500 _questPackages[questPackageItem->PackageID].second.push_back(questPackageItem);
1501 }
1502
1503 for (RewardPackXCurrencyTypeEntry const* rewardPackXCurrencyType : sRewardPackXCurrencyTypeStore)
1504 _rewardPackCurrencyTypes[rewardPackXCurrencyType->RewardPackID].push_back(rewardPackXCurrencyType);
1505
1506 for (RewardPackXItemEntry const* rewardPackXItem : sRewardPackXItemStore)
1507 _rewardPackItems[rewardPackXItem->RewardPackID].push_back(rewardPackXItem);
1508
1509 for (SkillLineEntry const* skill : sSkillLineStore)
1510 if (skill->ParentSkillLineID)
1511 _skillLinesByParentSkillLine[skill->ParentSkillLineID].push_back(skill);
1512
1513 for (SkillLineAbilityEntry const* skillLineAbility : sSkillLineAbilityStore)
1514 _skillLineAbilitiesBySkillupSkill[skillLineAbility->SkillupSkillLineID ? skillLineAbility->SkillupSkillLineID : skillLineAbility->SkillLine].push_back(skillLineAbility);
1515
1517 if (sSkillLineStore.LookupEntry(entry->SkillID))
1518 _skillRaceClassInfoBySkill.insert(SkillRaceClassInfoContainer::value_type(entry->SkillID, entry));
1519
1520 for (SoulbindConduitRankEntry const* soulbindConduitRank : sSoulbindConduitRankStore)
1521 _soulbindConduitRanks[{ soulbindConduitRank->SoulbindConduitID, soulbindConduitRank->RankIndex }] = soulbindConduitRank;
1522
1524 _specializationSpellsBySpec[specSpells->SpecID].push_back(specSpells);
1525
1526 for (SpecSetMemberEntry const* specSetMember : sSpecSetMemberStore)
1527 _specsBySpecSet.insert(std::make_pair(specSetMember->SpecSetID, uint32(specSetMember->ChrSpecializationID)));
1528
1529 for (SpellClassOptionsEntry const* classOption : sSpellClassOptionsStore)
1530 _spellFamilyNames.insert(classOption->SpellClassSet);
1531
1533 _spellProcsPerMinuteMods[ppmMod->SpellProcsPerMinuteID].push_back(ppmMod);
1534
1535 for (SpellVisualMissileEntry const* spellVisualMissile : sSpellVisualMissileStore)
1536 _spellVisualMissilesBySet[spellVisualMissile->SpellVisualMissileSetID].push_back(spellVisualMissile);
1537
1538 for (TalentEntry const* talentInfo : sTalentStore)
1539 {
1540 ASSERT(talentInfo->ClassID < MAX_CLASSES);
1541 ASSERT(talentInfo->TierID < MAX_TALENT_TIERS, "MAX_TALENT_TIERS must be at least %u", talentInfo->TierID + 1);
1542 ASSERT(talentInfo->ColumnIndex < MAX_TALENT_COLUMNS, "MAX_TALENT_COLUMNS must be at least %u", talentInfo->ColumnIndex + 1);
1543
1544 _talentsByPosition[talentInfo->ClassID][talentInfo->TierID][talentInfo->ColumnIndex].push_back(talentInfo);
1545 }
1546
1547 for (TaxiPathEntry const* entry : sTaxiPathStore)
1548 _taxiPaths[{ entry->FromTaxiNode, entry->ToTaxiNode }] = entry;
1549
1550 uint32 pathCount = sTaxiPathStore.GetNumRows();
1551
1552 // Calculate path nodes count
1553 std::vector<uint32> pathLength;
1554 pathLength.resize(pathCount); // 0 and some other indexes not used
1555 for (TaxiPathNodeEntry const* entry : sTaxiPathNodeStore)
1556 pathLength[entry->PathID] = std::max(pathLength[entry->PathID], entry->NodeIndex + 1u);
1557
1558 // Set path length
1559 sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used
1560 for (uint32 i = 0; i < sTaxiPathNodesByPath.size(); ++i)
1561 sTaxiPathNodesByPath[i].resize(pathLength[i]);
1562
1563 // fill data
1564 for (TaxiPathNodeEntry const* entry : sTaxiPathNodeStore)
1565 sTaxiPathNodesByPath[entry->PathID][entry->NodeIndex] = entry;
1566
1567 for (ToyEntry const* toy : sToyStore)
1568 _toys.insert(toy->ItemID);
1569
1570 for (TransmogIllusionEntry const* transmogIllusion : sTransmogIllusionStore)
1571 _transmogIllusionsByEnchantmentId[transmogIllusion->SpellItemEnchantmentID] = transmogIllusion;
1572
1573 for (TransmogSetItemEntry const* transmogSetItem : sTransmogSetItemStore)
1574 {
1575 TransmogSetEntry const* set = sTransmogSetStore.LookupEntry(transmogSetItem->TransmogSetID);
1576 if (!set)
1577 continue;
1578
1579 _transmogSetsByItemModifiedAppearance[transmogSetItem->ItemModifiedAppearanceID].push_back(set);
1580 _transmogSetItemsByTransmogSet[transmogSetItem->TransmogSetID].push_back(transmogSetItem);
1581 }
1582
1583 std::unordered_multimap<int32, UiMapAssignmentEntry const*> uiMapAssignmentByUiMap;
1584 for (UiMapAssignmentEntry const* uiMapAssignment : sUiMapAssignmentStore)
1585 {
1586 uiMapAssignmentByUiMap.emplace(uiMapAssignment->UiMapID, uiMapAssignment);
1587 if (UiMapEntry const* uiMap = sUiMapStore.LookupEntry(uiMapAssignment->UiMapID))
1588 {
1589 ASSERT(uiMap->System < MAX_UI_MAP_SYSTEM, "MAX_UI_MAP_SYSTEM must be at least %u", uiMap->System + 1);
1590 if (uiMapAssignment->MapID >= 0)
1591 _uiMapAssignmentByMap[uiMap->System].emplace(uiMapAssignment->MapID, uiMapAssignment);
1592 if (uiMapAssignment->AreaID)
1593 _uiMapAssignmentByArea[uiMap->System].emplace(uiMapAssignment->AreaID, uiMapAssignment);
1594 if (uiMapAssignment->WmoDoodadPlacementID)
1595 _uiMapAssignmentByWmoDoodadPlacement[uiMap->System].emplace(uiMapAssignment->WmoDoodadPlacementID, uiMapAssignment);
1596 if (uiMapAssignment->WmoGroupID)
1597 _uiMapAssignmentByWmoGroup[uiMap->System].emplace(uiMapAssignment->WmoGroupID, uiMapAssignment);
1598 }
1599 }
1600
1601 std::unordered_map<std::pair<uint32, uint32>, UiMapLinkEntry const*> uiMapLinks;
1602 for (UiMapLinkEntry const* uiMapLink : sUiMapLinkStore)
1603 uiMapLinks[std::make_pair(uiMapLink->ParentUiMapID, uint32(uiMapLink->ChildUiMapID))] = uiMapLink;
1604
1605 for (UiMapEntry const* uiMap : sUiMapStore)
1606 {
1607 UiMapBounds& bounds = _uiMapBounds[uiMap->ID];
1608 memset(&bounds, 0, sizeof(bounds));
1609 if (UiMapEntry const* parentUiMap = sUiMapStore.LookupEntry(uiMap->ParentUiMapID))
1610 {
1611 if (parentUiMap->GetFlags().HasFlag(UiMapFlag::NoWorldPositions))
1612 continue;
1613
1614 UiMapAssignmentEntry const* uiMapAssignment = nullptr;
1615 UiMapAssignmentEntry const* parentUiMapAssignment = nullptr;
1616 for (std::pair<int32 const, UiMapAssignmentEntry const*> const& uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ID))
1617 {
1618 if (uiMapAssignmentForMap.second->MapID >= 0 &&
1619 uiMapAssignmentForMap.second->Region[1].X - uiMapAssignmentForMap.second->Region[0].X > 0 &&
1620 uiMapAssignmentForMap.second->Region[1].Y - uiMapAssignmentForMap.second->Region[0].Y > 0)
1621 {
1622 uiMapAssignment = uiMapAssignmentForMap.second;
1623 break;
1624 }
1625 }
1626
1627 if (!uiMapAssignment)
1628 continue;
1629
1630 for (std::pair<int32 const, UiMapAssignmentEntry const*> const& uiMapAssignmentForMap : Trinity::Containers::MapEqualRange(uiMapAssignmentByUiMap, uiMap->ParentUiMapID))
1631 {
1632 if (uiMapAssignmentForMap.second->MapID == uiMapAssignment->MapID &&
1633 uiMapAssignmentForMap.second->Region[1].X - uiMapAssignmentForMap.second->Region[0].X > 0 &&
1634 uiMapAssignmentForMap.second->Region[1].Y - uiMapAssignmentForMap.second->Region[0].Y > 0)
1635 {
1636 parentUiMapAssignment = uiMapAssignmentForMap.second;
1637 break;
1638 }
1639 }
1640
1641 if (!parentUiMapAssignment)
1642 continue;
1643
1644 float parentXsize = parentUiMapAssignment->Region[1].X - parentUiMapAssignment->Region[0].X;
1645 float parentYsize = parentUiMapAssignment->Region[1].Y - parentUiMapAssignment->Region[0].Y;
1646 float bound0scale = (uiMapAssignment->Region[1].X - parentUiMapAssignment->Region[0].X) / parentXsize;
1647 float bound0 = ((1.0f - bound0scale) * parentUiMapAssignment->UiMax.Y) + (bound0scale * parentUiMapAssignment->UiMin.Y);
1648 float bound2scale = (uiMapAssignment->Region[0].X - parentUiMapAssignment->Region[0].X) / parentXsize;
1649 float bound2 = ((1.0f - bound2scale) * parentUiMapAssignment->UiMax.Y) + (bound2scale * parentUiMapAssignment->UiMin.Y);
1650 float bound1scale = (uiMapAssignment->Region[1].Y - parentUiMapAssignment->Region[0].Y) / parentYsize;
1651 float bound1 = ((1.0f - bound1scale) * parentUiMapAssignment->UiMax.X) + (bound1scale * parentUiMapAssignment->UiMin.X);
1652 float bound3scale = (uiMapAssignment->Region[0].Y - parentUiMapAssignment->Region[0].Y) / parentYsize;
1653 float bound3 = ((1.0f - bound3scale) * parentUiMapAssignment->UiMax.X) + (bound3scale * parentUiMapAssignment->UiMin.X);
1654 if ((bound3 - bound1) > 0.0f || (bound2 - bound0) > 0.0f)
1655 {
1656 bounds.Bounds[0] = bound0;
1657 bounds.Bounds[1] = bound1;
1658 bounds.Bounds[2] = bound2;
1659 bounds.Bounds[3] = bound3;
1660 bounds.IsUiAssignment = true;
1661 }
1662 }
1663
1664 if (UiMapLinkEntry const* uiMapLink = Trinity::Containers::MapGetValuePtr(uiMapLinks, std::make_pair(uiMap->ParentUiMapID, uiMap->ID)))
1665 {
1666 bounds.IsUiAssignment = false;
1667 bounds.IsUiLink = true;
1668 bounds.Bounds[0] = uiMapLink->UiMin.Y;
1669 bounds.Bounds[1] = uiMapLink->UiMin.X;
1670 bounds.Bounds[2] = uiMapLink->UiMax.Y;
1671 bounds.Bounds[3] = uiMapLink->UiMax.X;
1672 }
1673 }
1674
1675 for (UiMapXMapArtEntry const* uiMapArt : sUiMapXMapArtStore)
1676 if (uiMapArt->PhaseID)
1677 _uiMapPhases.insert(uiMapArt->PhaseID);
1678
1679 for (WMOAreaTableEntry const* entry : sWMOAreaTableStore)
1680 _wmoAreaTableLookup[WMOAreaTableKey(entry->WmoID, entry->NameSetID, entry->WmoGroupID)] = entry;
1681
1682 // Initialize global taxinodes mask
1683 // reinitialize internal storage for globals after loading TaxiNodes.db2
1684 sTaxiNodesMask = {};
1688 // include existed nodes that have at least single not spell base (scripted) path
1689 for (TaxiNodesEntry const* node : sTaxiNodesStore)
1690 {
1691 if (!node->IsPartOfTaxiNetwork())
1692 continue;
1693
1694 // valid taxi network node
1695 uint32 field = uint32((node->ID - 1) / (sizeof(TaxiMask::value_type) * 8));
1696 TaxiMask::value_type submask = TaxiMask::value_type(1 << ((node->ID - 1) % (sizeof(TaxiMask::value_type) * 8)));
1697
1698 sTaxiNodesMask[field] |= submask;
1699 if (node->GetFlags().HasFlag(TaxiNodeFlags::ShowOnHordeMap))
1700 sHordeTaxiNodesMask[field] |= submask;
1701 if (node->GetFlags().HasFlag(TaxiNodeFlags::ShowOnAllianceMap))
1702 sAllianceTaxiNodesMask[field] |= submask;
1703
1704 uint32 uiMapId = uint32(-1);
1705 if (!GetUiMapPosition(node->Pos.X, node->Pos.Y, node->Pos.Z, node->ContinentID, 0, 0, 0, UI_MAP_SYSTEM_ADVENTURE, false, &uiMapId))
1706 GetUiMapPosition(node->Pos.X, node->Pos.Y, node->Pos.Z, node->ContinentID, 0, 0, 0, UI_MAP_SYSTEM_TAXI, false, &uiMapId);
1707
1708 if (uiMapId == 985 || uiMapId == 986)
1709 sOldContinentsNodesMask[field] |= submask;
1710 }
1711
1712 for (PVPStatEntry const* pvpStat : sPVPStatStore)
1713 _pvpStatIdsByMap[pvpStat->MapID].insert(pvpStat->ID);
1714
1715 TC_LOG_INFO("server.loading", ">> Indexed DB2 data stores in {} ms", GetMSTimeDiffToNow(oldMSTime));
1716}
1717
1719{
1720 auto itr = _stores.find(type);
1721 if (itr != _stores.end())
1722 return itr->second;
1723
1724 return nullptr;
1725}
1726
1728{
1729 uint32 oldMSTime = getMSTime();
1730
1731 QueryResult result = HotfixDatabase.Query("SELECT Id, UniqueId, TableHash, RecordId, Status FROM hotfix_data ORDER BY Id");
1732
1733 if (!result)
1734 {
1735 TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix info entries.");
1736 return;
1737 }
1738
1739 uint32 count = 0;
1740
1741 std::map<std::pair<uint32, int32>, bool> deletedRecords;
1742
1743 do
1744 {
1745 Field* fields = result->Fetch();
1746
1747 int32 id = fields[0].GetInt32();
1748 uint32 uniqueId = fields[1].GetUInt32();
1749 uint32 tableHash = fields[2].GetUInt32();
1750 int32 recordId = fields[3].GetInt32();
1751 HotfixRecord::Status status = static_cast<HotfixRecord::Status>(fields[4].GetUInt8());
1752 std::bitset<TOTAL_LOCALES> availableDb2Locales = localeMask;
1753 if (status == HotfixRecord::Status::Valid && !_stores.contains(tableHash))
1754 {
1755 HotfixBlobKey key = std::make_pair(tableHash, recordId);
1756 for (std::size_t locale = 0; locale < TOTAL_LOCALES; ++locale)
1757 {
1758 if (!availableDb2Locales[locale])
1759 continue;
1760
1761 if (!_hotfixBlob[locale].contains(key))
1762 availableDb2Locales[locale] = false;
1763 }
1764
1765 if (availableDb2Locales.none())
1766 {
1767 TC_LOG_ERROR("sql.sql", "Table `hotfix_data` references unknown DB2 store by hash 0x{:X} and has no reference to `hotfix_blob` in hotfix id {} with RecordID: {}", tableHash, id, recordId);
1768 continue;
1769 }
1770 }
1771
1772 HotfixRecord hotfixRecord;
1773 hotfixRecord.TableHash = tableHash;
1774 hotfixRecord.RecordID = recordId;
1775 hotfixRecord.ID.PushID = id;
1776 hotfixRecord.ID.UniqueID = uniqueId;
1777 hotfixRecord.HotfixStatus = status;
1778 hotfixRecord.AvailableLocalesMask = availableDb2Locales.to_ulong();
1779
1780 HotfixPush& push = _hotfixData[id];
1781 push.Records.push_back(hotfixRecord);
1782 push.AvailableLocalesMask |= hotfixRecord.AvailableLocalesMask;
1783
1784 _maxHotfixId = std::max(_maxHotfixId, id);
1785 deletedRecords[std::make_pair(tableHash, recordId)] = status == HotfixRecord::Status::RecordRemoved;
1786 ++count;
1787 } while (result->NextRow());
1788
1789 for (auto itr = deletedRecords.begin(); itr != deletedRecords.end(); ++itr)
1790 if (itr->second)
1791 if (DB2StorageBase* store = Trinity::Containers::MapGetValuePtr(_stores, itr->first.first))
1792 store->EraseRecord(itr->first.second);
1793
1794 TC_LOG_INFO("server.loading", ">> Loaded {} hotfix records in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1795}
1796
1798{
1799 uint32 oldMSTime = getMSTime();
1800
1801 QueryResult result = HotfixDatabase.Query("SELECT TableHash, RecordId, locale, `Blob` FROM hotfix_blob ORDER BY TableHash");
1802
1803 if (!result)
1804 {
1805 TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix blob entries.");
1806 return;
1807 }
1808
1809 std::bitset<TOTAL_LOCALES> availableDb2Locales = localeMask;
1810 uint32 hotfixBlobCount = 0;
1811 do
1812 {
1813 Field* fields = result->Fetch();
1814
1815 uint32 tableHash = fields[0].GetUInt32();
1816 auto storeItr = _stores.find(tableHash);
1817 if (storeItr != _stores.end())
1818 {
1819 TC_LOG_ERROR("sql.sql", "Table hash 0x{:X} points to a loaded DB2 store {}, fill related table instead of hotfix_blob",
1820 tableHash, storeItr->second->GetFileName());
1821 continue;
1822 }
1823
1824 int32 recordId = fields[1].GetInt32();
1825 std::string localeName = fields[2].GetString();
1826 LocaleConstant locale = GetLocaleByName(localeName);
1827
1828 if (!IsValidLocale(locale))
1829 {
1830 TC_LOG_ERROR("sql.sql", "`hotfix_blob` contains invalid locale: {} at TableHash: 0x{:X} and RecordID: {}", localeName, tableHash, recordId);
1831 continue;
1832 }
1833
1834 if (!availableDb2Locales[locale])
1835 continue;
1836
1837 _hotfixBlob[locale][std::make_pair(tableHash, recordId)] = fields[3].GetBinary();
1838 hotfixBlobCount++;
1839 } while (result->NextRow());
1840
1841 TC_LOG_INFO("server.loading", ">> Loaded {} hotfix blob records in {} ms", hotfixBlobCount, GetMSTimeDiffToNow(oldMSTime));
1842}
1843
1844bool ValidateBroadcastTextTactKeyOptionalData(std::vector<uint8> const& data)
1845{
1846 return data.size() == 8 + 16;
1847}
1848
1850{
1851 // Register allowed optional data keys
1852 _allowedHotfixOptionalData.emplace(sBroadcastTextStore.GetTableHash(), std::make_pair(sTactKeyStore.GetTableHash(), &ValidateBroadcastTextTactKeyOptionalData));
1853
1854 uint32 oldMSTime = getMSTime();
1855
1856 QueryResult result = HotfixDatabase.Query("SELECT TableHash, RecordId, locale, `Key`, `Data` FROM hotfix_optional_data ORDER BY TableHash");
1857
1858 if (!result)
1859 {
1860 TC_LOG_INFO("server.loading", ">> Loaded 0 hotfix optional data records.");
1861 return;
1862 }
1863
1864 std::bitset<TOTAL_LOCALES> availableDb2Locales = localeMask;
1865 uint32 hotfixOptionalDataCount = 0;
1866 do
1867 {
1868 Field* fields = result->Fetch();
1869
1870 uint32 tableHash = fields[0].GetUInt32();
1871 auto allowedHotfixes = Trinity::Containers::MapEqualRange(_allowedHotfixOptionalData, tableHash);
1872 if (allowedHotfixes.begin() == allowedHotfixes.end())
1873 {
1874 TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references DB2 store by hash 0x{:X} that is not allowed to have optional data", tableHash);
1875 continue;
1876 }
1877
1878 uint32 recordId = fields[1].GetInt32();
1879 auto storeItr = _stores.find(tableHash);
1880 if (storeItr == _stores.end())
1881 {
1882 TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references unknown DB2 store by hash 0x{:X} with RecordID: {}", tableHash, recordId);
1883 continue;
1884 }
1885
1886 std::string localeName = fields[2].GetString();
1887 LocaleConstant locale = GetLocaleByName(localeName);
1888
1889 if (!IsValidLocale(locale))
1890 {
1891 TC_LOG_ERROR("sql.sql", "`hotfix_optional_data` contains invalid locale: {} at TableHash: 0x{:X} and RecordID: {}", localeName, tableHash, recordId);
1892 continue;
1893 }
1894
1895 if (!availableDb2Locales[locale])
1896 continue;
1897
1898 DB2Manager::HotfixOptionalData optionalData;
1899 optionalData.Key = fields[3].GetUInt32();
1900 auto allowedHotfixItr = std::find_if(allowedHotfixes.begin(), allowedHotfixes.end(), [&](std::pair<uint32 const, AllowedHotfixOptionalData> const& v)
1901 {
1902 return v.second.first == optionalData.Key;
1903 });
1904 if (allowedHotfixItr == allowedHotfixes.end())
1905 {
1906 TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` references non-allowed optional data key 0x{:X} for DB2 store by hash 0x{:X} and RecordID: {}",
1907 optionalData.Key, tableHash, recordId);
1908 continue;
1909 }
1910
1911 optionalData.Data = fields[4].GetBinary();
1912 if (!allowedHotfixItr->second.second(optionalData.Data))
1913 {
1914 TC_LOG_ERROR("sql.sql", "Table `hotfix_optional_data` contains invalid data for DB2 store 0x{:X}, RecordID: {} and Key: 0x{:X}",
1915 tableHash, recordId, optionalData.Key);
1916 continue;
1917 }
1918
1919 _hotfixOptionalData[locale][std::make_pair(tableHash, recordId)].push_back(std::move(optionalData));
1920 hotfixOptionalDataCount++;
1921 } while (result->NextRow());
1922
1923 TC_LOG_INFO("server.loading", ">> Loaded {} hotfix optional data records in {} ms", hotfixOptionalDataCount, GetMSTimeDiffToNow(oldMSTime));
1924}
1925
1927{
1928 return _hotfixData.size();
1929}
1930
1932{
1933 return _hotfixData;
1934}
1935
1936std::vector<uint8> const* DB2Manager::GetHotfixBlobData(uint32 tableHash, int32 recordId, LocaleConstant locale) const
1937{
1938 ASSERT(IsValidLocale(locale), "Locale %u is invalid locale", uint32(locale));
1939
1940 return Trinity::Containers::MapGetValuePtr(_hotfixBlob[locale], std::make_pair(tableHash, recordId));
1941}
1942
1943std::vector<DB2Manager::HotfixOptionalData> const* DB2Manager::GetHotfixOptionalData(uint32 tableHash, int32 recordId, LocaleConstant locale) const
1944{
1945 ASSERT(IsValidLocale(locale), "Locale %u is invalid locale", uint32(locale));
1946
1947 return Trinity::Containers::MapGetValuePtr(_hotfixOptionalData[locale], std::make_pair(tableHash, recordId));
1948}
1949
1951{
1952 return sAnimationDataStore.GetNumRows();
1953}
1954
1956{
1957 HotfixRecord hotfixRecord;
1958 hotfixRecord.TableHash = tableHash;
1959 hotfixRecord.RecordID = recordId;
1960 hotfixRecord.ID.PushID = ++_maxHotfixId;
1961 hotfixRecord.ID.UniqueID = rand32();
1962 hotfixRecord.AvailableLocalesMask = 0xDFF;
1963
1964 HotfixPush& push = _hotfixData[hotfixRecord.ID.PushID];
1965 push.Records.push_back(hotfixRecord);
1966 push.AvailableLocalesMask |= hotfixRecord.AvailableLocalesMask;
1967}
1968
1969std::vector<uint32> DB2Manager::GetAreasForGroup(uint32 areaGroupId) const
1970{
1971 auto itr = _areaGroupMembers.find(areaGroupId);
1972 if (itr != _areaGroupMembers.end())
1973 return itr->second;
1974
1975 return std::vector<uint32>();
1976}
1977
1978bool DB2Manager::IsInArea(uint32 objectAreaId, uint32 areaId)
1979{
1980 do
1981 {
1982 if (objectAreaId == areaId)
1983 return true;
1984
1985 AreaTableEntry const* objectArea = sAreaTableStore.LookupEntry(objectAreaId);
1986 if (!objectArea)
1987 break;
1988
1989 objectAreaId = objectArea->ParentAreaID;
1990 } while (objectAreaId);
1991
1992 return false;
1993}
1994
1996{
1997 if (!areaEntry)
1998 return nullptr;
1999
2000 // Get ContentTuning for the area
2001 if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(areaEntry->ContentTuningID))
2002 return contentTuning;
2003
2004 // If there is no data for the current area and it has a parent area, get data from the last (recursive)
2005 if (AreaTableEntry const* parentAreaEntry = sAreaTableStore.LookupEntry(areaEntry->ParentAreaID))
2006 return GetContentTuningForArea(parentAreaEntry);
2007
2008 return nullptr;
2009}
2010
2011std::vector<ArtifactPowerEntry const*> DB2Manager::GetArtifactPowers(uint8 artifactId) const
2012{
2013 auto itr = _artifactPowers.find(artifactId);
2014 if (itr != _artifactPowers.end())
2015 return itr->second;
2016
2017 return std::vector<ArtifactPowerEntry const*>{};
2018}
2019
2020std::vector<uint32> const* DB2Manager::GetArtifactPowerLinks(uint32 artifactPowerId) const
2021{
2022 return Trinity::Containers::MapGetValuePtr(_artifactPowerLinks, artifactPowerId);
2023}
2024
2026{
2027 return Trinity::Containers::MapGetValuePtr(_artifactPowerRanks, { artifactPowerId, rank });
2028}
2029
2031{
2032 return Trinity::Containers::MapGetValuePtr(_azeriteEmpoweredItems, itemId);
2033}
2034
2036{
2037 return std::find_if(sAzeriteItemStore.begin(), sAzeriteItemStore.end(),
2038 [&](AzeriteItemEntry const* azeriteItem) { return azeriteItem->ItemID == int32(itemId); }) != sAzeriteItemStore.end();
2039}
2040
2042{
2043 return Trinity::Containers::MapGetValuePtr(_azeriteEssencePowersByIdAndRank, std::make_pair(azeriteEssenceId, rank));
2044}
2045
2046std::vector<AzeriteItemMilestonePowerEntry const*> const& DB2Manager::GetAzeriteItemMilestonePowers() const
2047{
2048 return _azeriteItemMilestonePowers;
2049}
2050
2052{
2053 ASSERT(slot < MAX_AZERITE_ESSENCE_SLOT, "Slot %u must be lower than MAX_AZERITE_ESSENCE_SLOT (%u)", uint32(slot), MAX_AZERITE_ESSENCE_SLOT);
2054 return _azeriteItemMilestonePowerByEssenceSlot[slot];
2055}
2056
2057std::vector<AzeritePowerSetMemberEntry const*> const* DB2Manager::GetAzeritePowers(uint32 itemId) const
2058{
2059 if (AzeriteEmpoweredItemEntry const* azeriteEmpoweredItem = GetAzeriteEmpoweredItem(itemId))
2060 return Trinity::Containers::MapGetValuePtr(_azeritePowers, azeriteEmpoweredItem->AzeritePowerSetID);
2061
2062 return nullptr;
2063}
2064
2066{
2068 if (std::array<uint8, MAX_AZERITE_EMPOWERED_TIER> const* levels = Trinity::Containers::MapGetValuePtr(_azeriteTierUnlockLevels, std::make_pair(azeriteUnlockSetId, context)))
2069 return (*levels)[tier];
2070
2071 AzeriteTierUnlockSetEntry const* azeriteTierUnlockSet = sAzeriteTierUnlockSetStore.LookupEntry(azeriteUnlockSetId);
2072 if (azeriteTierUnlockSet && azeriteTierUnlockSet->Flags & AZERITE_TIER_UNLOCK_SET_FLAG_DEFAULT)
2073 if (std::array<uint8, MAX_AZERITE_EMPOWERED_TIER> const* levels = Trinity::Containers::MapGetValuePtr(_azeriteTierUnlockLevels, std::make_pair(azeriteUnlockSetId, ItemContext::NONE)))
2074 return (*levels)[tier];
2075
2076 return sAzeriteLevelInfoStore.GetNumRows();
2077}
2078
2079char const* DB2Manager::GetBroadcastTextValue(BroadcastTextEntry const* broadcastText, LocaleConstant locale /*= DEFAULT_LOCALE*/, uint8 gender /*= GENDER_MALE*/, bool forceGender /*= false*/)
2080{
2081 if ((gender == GENDER_FEMALE || gender == GENDER_NONE) && (forceGender || broadcastText->Text1[DEFAULT_LOCALE][0] != '\0'))
2082 {
2083 if (broadcastText->Text1[locale][0] != '\0')
2084 return broadcastText->Text1[locale];
2085
2086 return broadcastText->Text1[DEFAULT_LOCALE];
2087 }
2088
2089 if (broadcastText->Text[locale][0] != '\0')
2090 return broadcastText->Text[locale];
2091
2092 return broadcastText->Text[DEFAULT_LOCALE];
2093}
2094
2095int32 const* DB2Manager::GetBroadcastTextDuration(uint32 broadcastTextId, LocaleConstant locale /*= DEFAULT_LOCALE*/) const
2096{
2097 return Trinity::Containers::MapGetValuePtr(_broadcastTextDurations, { broadcastTextId, WowLocaleToCascLocaleBit[locale] });
2098}
2099
2101{
2102 return Trinity::Containers::MapGetValuePtr(_charBaseInfoByRaceAndClass, { race, class_ });
2103}
2104
2106{
2107 ASSERT(unitClass < MAX_CLASSES);
2108 return _uiDisplayByClass[unitClass];
2109}
2110
2111char const* DB2Manager::GetChrClassName(uint8 class_, LocaleConstant locale /*= DEFAULT_LOCALE*/)
2112{
2113 ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_);
2114 if (!classEntry)
2115 return "";
2116
2117 if (classEntry->Name[locale][0] != '\0')
2118 return classEntry->Name[locale];
2119
2120 return classEntry->Name[DEFAULT_LOCALE];
2121}
2122
2124{
2125 return _powersByClass[classId][power];
2126}
2127
2128std::vector<ChrCustomizationChoiceEntry const*> const* DB2Manager::GetCustomiztionChoices(uint32 chrCustomizationOptionId) const
2129{
2130 return Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesByOption, chrCustomizationOptionId);
2131}
2132
2133std::vector<ChrCustomizationOptionEntry const*> const* DB2Manager::GetCustomiztionOptions(uint8 race, uint8 gender) const
2134{
2135 return Trinity::Containers::MapGetValuePtr(_chrCustomizationOptionsByRaceAndGender, { race,gender });
2136}
2137
2138std::vector<std::pair<uint32, std::vector<uint32>>> const* DB2Manager::GetRequiredCustomizationChoices(uint32 chrCustomizationReqId) const
2139{
2140 return Trinity::Containers::MapGetValuePtr(_chrCustomizationRequiredChoices, chrCustomizationReqId);
2141}
2142
2144{
2145 return Trinity::Containers::MapGetValuePtr(_chrModelsByRaceAndGender, { race, gender });
2146}
2147
2149{
2150 return Trinity::Containers::MapGetValuePtr(_conditionalChrModelsByChrModelId, chrModelId);
2151}
2152
2153char const* DB2Manager::GetChrRaceName(uint8 race, LocaleConstant locale /*= DEFAULT_LOCALE*/)
2154{
2155 ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race);
2156 if (!raceEntry)
2157 return "";
2158
2159 if (raceEntry->Name[locale][0] != '\0')
2160 return raceEntry->Name[locale];
2161
2162 return raceEntry->Name[DEFAULT_LOCALE];
2163}
2164
2166{
2167 return _chrSpecializationsByIndex[class_][index];
2168}
2169
2171{
2173}
2174
2176{
2177 if (std::vector<ConditionalContentTuningEntry const*> const* conditionalContentTunings = Trinity::Containers::MapGetValuePtr(_conditionalContentTuning, contentTuningId))
2178 for (ConditionalContentTuningEntry const* conditionalContentTuning : *conditionalContentTunings)
2179 if (conditionalContentTuning->RedirectFlag & redirectFlag)
2180 return conditionalContentTuning->RedirectContentTuningID;
2181
2182 return contentTuningId;
2183}
2184
2185Optional<ContentTuningLevels> DB2Manager::GetContentTuningData(uint32 contentTuningId, uint32 redirectFlag, bool forItem /*= false*/) const
2186{
2187 ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(GetRedirectedContentTuningId(contentTuningId, redirectFlag));
2188 if (!contentTuning)
2189 return {};
2190
2191 if (forItem && contentTuning->GetFlags().HasFlag(ContentTuningFlag::DisabledForItem))
2192 return {};
2193
2194 auto getLevelAdjustment = [](ContentTuningCalcType type) -> int32
2195 {
2196 switch (type)
2197 {
2199 return 1;
2201 return GetMaxLevelForExpansion(sWorld->getIntConfig(CONFIG_EXPANSION));
2203 return GetMaxLevelForExpansion(std::max<int32>(sWorld->getIntConfig(CONFIG_EXPANSION) - 1, 0));
2204 default:
2205 break;
2206 }
2207
2208 return 0;
2209 };
2210
2211 ContentTuningLevels levels;
2212 levels.MinLevel = contentTuning->MinLevel + getLevelAdjustment(static_cast<ContentTuningCalcType>(contentTuning->MinLevelType));
2213 levels.MaxLevel = contentTuning->MaxLevel + getLevelAdjustment(static_cast<ContentTuningCalcType>(contentTuning->MaxLevelType));
2214 levels.MinLevelWithDelta = std::clamp<int32>(levels.MinLevel + contentTuning->TargetLevelDelta, 1, MAX_LEVEL);
2215 levels.MaxLevelWithDelta = std::clamp<int32>(levels.MaxLevel + contentTuning->TargetLevelMaxDelta, 1, MAX_LEVEL);
2216
2217 // clamp after calculating levels with delta (delta can bring "overflown" level back into correct range)
2218 levels.MinLevel = std::clamp<int32>(levels.MinLevel, 1, MAX_LEVEL);
2219 levels.MaxLevel = std::clamp<int32>(levels.MaxLevel, 1, MAX_LEVEL);
2220
2221 if (contentTuning->TargetLevelMin)
2222 levels.TargetLevelMin = contentTuning->TargetLevelMin;
2223 else
2224 levels.TargetLevelMin = levels.MinLevelWithDelta;
2225
2226 if (contentTuning->TargetLevelMax)
2227 levels.TargetLevelMax = contentTuning->TargetLevelMax;
2228 else
2229 levels.TargetLevelMax = levels.MaxLevelWithDelta;
2230
2231 return levels;
2232}
2233
2234bool DB2Manager::HasContentTuningLabel(uint32 contentTuningId, int32 label) const
2235{
2236 return _contentTuningLabels.contains({ contentTuningId, label });
2237}
2238
2240{
2241 if (!petfamily)
2242 return nullptr;
2243
2244 CreatureFamilyEntry const* petFamily = sCreatureFamilyStore.LookupEntry(petfamily);
2245 if (!petFamily)
2246 return nullptr;
2247
2248 return petFamily->Name[locale][0] != '\0' ? petFamily->Name[locale] : nullptr;
2249}
2250
2251std::span<int32 const> DB2Manager::GetCreatureLabels(uint32 creatureDifficultyId) const
2252{
2253 std::vector<int32> const* labels = Trinity::Containers::MapGetValuePtr(_creatureLabels, creatureDifficultyId);
2254 return labels ? std::span<int32 const>(*labels) : std::span<int32 const>();
2255}
2256
2258{
2259 for (std::pair<uint32 const, CurrencyContainerEntry const*> const& p : Trinity::Containers::MapEqualRange(_currencyContainers, currencyId))
2260 if (quantity >= p.second->MinAmount && (!p.second->MaxAmount || quantity <= p.second->MaxAmount))
2261 return p.second;
2262
2263 return nullptr;
2264}
2265
2266std::pair<float, float> DB2Manager::GetCurveXAxisRange(uint32 curveId) const
2267{
2268 if (std::vector<DBCPosition2D> const* points = Trinity::Containers::MapGetValuePtr(_curvePoints, curveId))
2269 return { points->front().X, points->back().X };
2270
2271 return { 0.0f, 0.0f };
2272}
2273
2274static CurveInterpolationMode DetermineCurveType(CurveEntry const* curve, std::vector<DBCPosition2D> const& points)
2275{
2276 switch (curve->Type)
2277 {
2278 case 1:
2280 case 2:
2281 {
2282 switch (points.size())
2283 {
2284 case 1:
2286 case 2:
2288 case 3:
2290 case 4:
2292 default:
2293 break;
2294 }
2296 }
2297 case 3:
2299 default:
2300 break;
2301 }
2302
2304}
2305
2306float DB2Manager::GetCurveValueAt(uint32 curveId, float x) const
2307{
2308 auto itr = _curvePoints.find(curveId);
2309 if (itr == _curvePoints.end())
2310 return 0.0f;
2311
2312 CurveEntry const* curve = sCurveStore.AssertEntry(curveId);
2313 std::vector<DBCPosition2D> const& points = itr->second;
2314 if (points.empty())
2315 return 0.0f;
2316
2317 return GetCurveValueAt(DetermineCurveType(curve, points), points, x);
2318}
2319
2320float DB2Manager::GetCurveValueAt(CurveInterpolationMode mode, std::span<DBCPosition2D const> points, float x) const
2321{
2322 switch (mode)
2323 {
2325 {
2326 std::size_t pointIndex = 0;
2327 while (pointIndex < points.size() && points[pointIndex].X <= x)
2328 ++pointIndex;
2329 if (!pointIndex)
2330 return points[0].Y;
2331 if (pointIndex >= points.size())
2332 return points.back().Y;
2333 float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
2334 if (xDiff == 0.0)
2335 return points[pointIndex].Y;
2336 return (((x - points[pointIndex - 1].X) / xDiff) * (points[pointIndex].Y - points[pointIndex - 1].Y)) + points[pointIndex - 1].Y;
2337 }
2339 {
2340 std::size_t pointIndex = 0;
2341 while (pointIndex < points.size() && points[pointIndex].X <= x)
2342 ++pointIndex;
2343 if (!pointIndex)
2344 return points[0].Y;
2345 if (pointIndex >= points.size())
2346 return points.back().Y;
2347 float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
2348 if (xDiff == 0.0)
2349 return points[pointIndex].Y;
2350 return ((points[pointIndex].Y - points[pointIndex - 1].Y) * (1.0f - std::cos((x - points[pointIndex - 1].X) / xDiff * float(M_PI))) * 0.5f) + points[pointIndex - 1].Y;
2351 }
2353 {
2354 std::size_t pointIndex = 1;
2355 while (pointIndex < points.size() && points[pointIndex].X <= x)
2356 ++pointIndex;
2357 if (pointIndex == 1)
2358 return points[1].Y;
2359 if (pointIndex >= points.size() - 1)
2360 return points[points.size() - 2].Y;
2361 float xDiff = points[pointIndex].X - points[pointIndex - 1].X;
2362 if (xDiff == 0.0)
2363 return points[pointIndex].Y;
2364
2365 float mu = (x - points[pointIndex - 1].X) / xDiff;
2366 float a0 = -0.5f * points[pointIndex - 2].Y + 1.5f * points[pointIndex - 1].Y - 1.5f * points[pointIndex].Y + 0.5f * points[pointIndex + 1].Y;
2367 float a1 = points[pointIndex - 2].Y - 2.5f * points[pointIndex - 1].Y + 2.0f * points[pointIndex].Y - 0.5f * points[pointIndex + 1].Y;
2368 float a2 = -0.5f * points[pointIndex - 2].Y + 0.5f * points[pointIndex].Y;
2369 float a3 = points[pointIndex - 1].Y;
2370
2371 return a0 * mu * mu * mu + a1 * mu * mu + a2 * mu + a3;
2372 }
2374 {
2375 float xDiff = points[2].X - points[0].X;
2376 if (xDiff == 0.0)
2377 return points[1].Y;
2378 float mu = (x - points[0].X) / xDiff;
2379 return ((1.0f - mu) * (1.0f - mu) * points[0].Y) + (1.0f - mu) * 2.0f * mu * points[1].Y + mu * mu * points[2].Y;
2380 }
2382 {
2383 float xDiff = points[3].X - points[0].X;
2384 if (xDiff == 0.0)
2385 return points[1].Y;
2386 float mu = (x - points[0].X) / xDiff;
2387 return (1.0f - mu) * (1.0f - mu) * (1.0f - mu) * points[0].Y
2388 + 3.0f * mu * (1.0f - mu) * (1.0f - mu) * points[1].Y
2389 + 3.0f * mu * mu * (1.0f - mu) * points[2].Y
2390 + mu * mu * mu * points[3].Y;
2391 }
2393 {
2394 float xDiff = points.back().X - points[0].X;
2395 if (xDiff == 0.0f)
2396 return points.back().Y;
2397
2398 std::vector<float> tmp(points.size());
2399 for (std::size_t i = 0; i < points.size(); ++i)
2400 tmp[i] = points[i].Y;
2401
2402 float mu = (x - points[0].X) / xDiff;
2403 int32 i = int32(points.size()) - 1;
2404 while (i > 0)
2405 {
2406 for (int32 k = 0; k < i; ++k)
2407 {
2408 float val = tmp[k] + mu * (tmp[k + 1] - tmp[k]);
2409 tmp[k] = val;
2410 }
2411 --i;
2412 }
2413 return tmp[0];
2414 }
2416 return points[0].Y;
2417 default:
2418 break;
2419 }
2420
2421 return 0.0f;
2422}
2423
2425{
2426 if (EmotesTextSoundEntry const* emotesTextSound = Trinity::Containers::MapGetValuePtr(_emoteTextSounds, { emote, race, gender, class_ }))
2427 return emotesTextSound;
2428
2429 if (EmotesTextSoundEntry const* emotesTextSound = Trinity::Containers::MapGetValuePtr(_emoteTextSounds, { emote, race, gender, uint8(0) }))
2430 return emotesTextSound;
2431
2432 return nullptr;
2433}
2434
2435template<float(ExpectedStatModEntry::*field)>
2437{
2438 explicit ExpectedStatModReducer(int32 mythicPlusMilestoneSeason) : ActiveMilestoneSeason(mythicPlusMilestoneSeason) { }
2439
2440 float operator()(float mod, ContentTuningXExpectedEntry const* contentTuningXExpected) const
2441 {
2442 if (!contentTuningXExpected)
2443 return mod;
2444
2445 if (contentTuningXExpected->MinMythicPlusSeasonID)
2446 if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MinMythicPlusSeasonID))
2447 if (ActiveMilestoneSeason < mythicPlusSeason->MilestoneSeason)
2448 return mod;
2449
2450 if (contentTuningXExpected->MaxMythicPlusSeasonID)
2451 if (MythicPlusSeasonEntry const* mythicPlusSeason = sMythicPlusSeasonStore.LookupEntry(contentTuningXExpected->MaxMythicPlusSeasonID))
2452 if (ActiveMilestoneSeason >= mythicPlusSeason->MilestoneSeason)
2453 return mod;
2454
2455 return mod * sExpectedStatModStore.AssertEntry(contentTuningXExpected->ExpectedStatModID)->*field;
2456 }
2457
2459};
2460
2461float DB2Manager::EvaluateExpectedStat(ExpectedStatType stat, uint32 level, int32 expansion, uint32 contentTuningId, Classes unitClass, int32 mythicPlusMilestoneSeason) const
2462{
2463 auto expectedStatItr = _expectedStatsByLevel.find(std::make_pair(level, expansion));
2464 if (expectedStatItr == _expectedStatsByLevel.end())
2465 expectedStatItr = _expectedStatsByLevel.find(std::make_pair(level, -2));
2466
2467 if (expectedStatItr == _expectedStatsByLevel.end())
2468 return 1.0f;
2469
2470 ExpectedStatModEntry const* classMod = nullptr;
2471 switch (unitClass)
2472 {
2473 case CLASS_WARRIOR:
2474 classMod = sExpectedStatModStore.LookupEntry(4);
2475 break;
2476 case CLASS_PALADIN:
2477 classMod = sExpectedStatModStore.LookupEntry(2);
2478 break;
2479 case CLASS_ROGUE:
2480 classMod = sExpectedStatModStore.LookupEntry(3);
2481 break;
2482 case CLASS_MAGE:
2483 classMod = sExpectedStatModStore.LookupEntry(1);
2484 break;
2485 default:
2486 break;
2487 }
2488
2489 std::vector<ContentTuningXExpectedEntry const*> const* contentTuningMods = Trinity::Containers::MapGetValuePtr(_expectedStatModsByContentTuning, contentTuningId);
2490 float value = 0.0f;
2491 switch (stat)
2492 {
2494 value = expectedStatItr->second->CreatureHealth;
2495 if (contentTuningMods)
2496 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2498 if (classMod)
2499 value *= classMod->CreatureHealthMod;
2500 break;
2502 value = expectedStatItr->second->PlayerHealth;
2503 if (contentTuningMods)
2504 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2506 if (classMod)
2507 value *= classMod->PlayerHealthMod;
2508 break;
2510 value = expectedStatItr->second->CreatureAutoAttackDps;
2511 if (contentTuningMods)
2512 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2514 if (classMod)
2515 value *= classMod->CreatureAutoAttackDPSMod;
2516 break;
2518 value = expectedStatItr->second->CreatureArmor;
2519 if (contentTuningMods)
2520 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2522 if (classMod)
2523 value *= classMod->CreatureArmorMod;
2524 break;
2526 value = expectedStatItr->second->PlayerMana;
2527 if (contentTuningMods)
2528 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2530 if (classMod)
2531 value *= classMod->PlayerManaMod;
2532 break;
2534 value = expectedStatItr->second->PlayerPrimaryStat;
2535 if (contentTuningMods)
2536 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2538 if (classMod)
2539 value *= classMod->PlayerPrimaryStatMod;
2540 break;
2542 value = expectedStatItr->second->PlayerSecondaryStat;
2543 if (contentTuningMods)
2544 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2546 if (classMod)
2547 value *= classMod->PlayerSecondaryStatMod;
2548 break;
2550 value = expectedStatItr->second->ArmorConstant;
2551 if (contentTuningMods)
2552 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2554 if (classMod)
2555 value *= classMod->ArmorConstantMod;
2556 break;
2558 break;
2560 value = expectedStatItr->second->CreatureSpellDamage;
2561 if (contentTuningMods)
2562 value *= std::accumulate(contentTuningMods->begin(), contentTuningMods->end(), 1.0f,
2564 if (classMod)
2565 value *= classMod->CreatureSpellDamageMod;
2566 break;
2567 default:
2568 break;
2569 }
2570
2571 return value;
2572}
2573
2574std::vector<uint32> const* DB2Manager::GetFactionTeamList(uint32 faction) const
2575{
2576 return Trinity::Containers::MapGetValuePtr(_factionTeams, faction);
2577}
2578
2580{
2581 return Trinity::Containers::MapGetValuePtr(_friendshipRepReactions, friendshipRepID);
2582}
2583
2584std::span<int32 const> DB2Manager::GetGameObjectLabels(uint32 gameobjectId) const
2585{
2586 std::vector<int32> const* labels = Trinity::Containers::MapGetValuePtr(_gameobjectLabels, gameobjectId);
2587 return labels ? std::span<int32 const>(*labels) : std::span<int32 const>();
2588}
2589
2591{
2592 for (GlobalCurveEntry const* globalCurveEntry : sGlobalCurveStore)
2593 if (GlobalCurve(globalCurveEntry->Type) == globalCurveType)
2594 return globalCurveEntry->CurveID;
2595
2596 return 0;
2597}
2598
2599std::vector<uint32> const* DB2Manager::GetGlyphBindableSpells(uint32 glyphPropertiesId) const
2600{
2601 return Trinity::Containers::MapGetValuePtr(_glyphBindableSpells, glyphPropertiesId);
2602}
2603
2604std::vector<ChrSpecialization> const* DB2Manager::GetGlyphRequiredSpecs(uint32 glyphPropertiesId) const
2605{
2606 return Trinity::Containers::MapGetValuePtr(_glyphRequiredSpecs, glyphPropertiesId);
2607}
2608
2610{
2611 return Trinity::Containers::MapGetValuePtr(_heirlooms, itemId);
2612}
2613
2615{
2616 return Trinity::Containers::MapGetValuePtr(_itemChildEquipment, itemId);
2617}
2618
2620{
2621 return _itemClassByOldEnum[itemClass];
2622}
2623
2625{
2626 return _itemsWithCurrencyCost.count(itemId) > 0;
2627}
2628
2629std::vector<ItemLimitCategoryConditionEntry const*> const* DB2Manager::GetItemLimitCategoryConditions(uint32 categoryId) const
2630{
2631 return Trinity::Containers::MapGetValuePtr(_itemCategoryConditions, categoryId);
2632}
2633
2634uint32 DB2Manager::GetItemDisplayId(uint32 itemId, uint32 appearanceModId) const
2635{
2636 if (ItemModifiedAppearanceEntry const* modifiedAppearance = GetItemModifiedAppearance(itemId, appearanceModId))
2637 if (ItemAppearanceEntry const* itemAppearance = sItemAppearanceStore.LookupEntry(modifiedAppearance->ItemAppearanceID))
2638 return itemAppearance->ItemDisplayInfoID;
2639
2640 return 0;
2641}
2642
2644{
2645 auto itr = _itemModifiedAppearancesByItem.find(itemId | (appearanceModId << 24));
2646 if (itr != _itemModifiedAppearancesByItem.end())
2647 return itr->second;
2648
2649 // Fall back to unmodified appearance
2650 if (appearanceModId)
2651 {
2652 itr = _itemModifiedAppearancesByItem.find(itemId);
2653 if (itr != _itemModifiedAppearancesByItem.end())
2654 return itr->second;
2655 }
2656
2657 return nullptr;
2658}
2659
2661{
2662 return Trinity::Containers::MapGetValuePtr(_itemModifiedAppearancesByItem, itemId);
2663}
2664
2665std::vector<ItemSetSpellEntry const*> const* DB2Manager::GetItemSetSpells(uint32 itemSetId) const
2666{
2667 return Trinity::Containers::MapGetValuePtr(_itemSetSpells, itemSetId);
2668}
2669
2670std::vector<ItemSpecOverrideEntry const*> const* DB2Manager::GetItemSpecOverrides(uint32 itemId) const
2671{
2672 return Trinity::Containers::MapGetValuePtr(_itemSpecOverrides, itemId);
2673}
2674
2676{
2677 if (index < _journalTiersByIndex.size())
2678 return _journalTiersByIndex[index];
2679 return nullptr;
2680}
2681
2683{
2684 for (LFGDungeonsEntry const* dungeon : sLFGDungeonsStore)
2685 if (dungeon->MapID == int32(mapId) && Difficulty(dungeon->DifficultyID) == difficulty)
2686 return dungeon;
2687
2688 return nullptr;
2689}
2690
2692{
2693 for (int32 i = sLightStore.GetNumRows(); i >= 0; --i)
2694 {
2695 LightEntry const* light = sLightStore.LookupEntry(uint32(i));
2696 if (!light)
2697 continue;
2698
2699 if (light->ContinentID == int32(mapId) && light->GameCoords.X == 0.0f && light->GameCoords.Y == 0.0f && light->GameCoords.Z == 0.0f)
2700 return uint32(i);
2701 }
2702
2703 return 0;
2704}
2705
2707{
2708 if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquidType))
2709 return 1 << liq->SoundBank;
2710
2711 return 0;
2712}
2713
2714MapDifficultyEntry const* DB2Manager::GetDefaultMapDifficulty(uint32 mapId, Difficulty* difficulty /*= nullptr*/) const
2715{
2716 std::unordered_map<uint32, MapDifficultyEntry const*>* difficultiesForMap = Trinity::Containers::MapGetValuePtr(_mapDifficulties, mapId);
2717 if (!difficultiesForMap)
2718 return nullptr;
2719
2720 auto difficultyEnd = difficultiesForMap->end();
2721
2722 // first find any valid difficulty
2723 auto foundDifficulty = std::ranges::find_if(difficultiesForMap->begin(), difficultyEnd,
2724 [](std::pair<uint32 const, MapDifficultyEntry const*> const& p) { return sDifficultyStore.HasRecord(p.first); });
2725
2726 if (foundDifficulty == difficultyEnd)
2727 return nullptr; // nothing valid was found
2728
2729 if (!(sDifficultyStore.AssertEntry(foundDifficulty->first)->Flags & DIFFICULTY_FLAG_DEFAULT))
2730 {
2731 // first valid difficulty wasn't default, try finding one
2732 auto defaultDifficulty = std::ranges::find_if(foundDifficulty, difficultyEnd,
2733 [](DifficultyEntry const* difficultyEntry) { return difficultyEntry && (difficultyEntry->Flags & DIFFICULTY_FLAG_DEFAULT) != 0; },
2734 [](std::pair<uint32 const, MapDifficultyEntry const*> const& p) { return sDifficultyStore.LookupEntry(p.first); });
2735
2736 if (defaultDifficulty != difficultyEnd)
2737 foundDifficulty = defaultDifficulty; // got a default
2738 }
2739
2740 if (difficulty)
2741 *difficulty = Difficulty(foundDifficulty->first);
2742
2743 return foundDifficulty->second;
2744}
2745
2747{
2748 auto itr = _mapDifficulties.find(mapId);
2749 if (itr == _mapDifficulties.end())
2750 return nullptr;
2751
2752 auto diffItr = itr->second.find(difficulty);
2753 if (diffItr == itr->second.end())
2754 return nullptr;
2755
2756 return diffItr->second;
2757}
2758
2760{
2761 DifficultyEntry const* diffEntry = sDifficultyStore.LookupEntry(difficulty);
2762 if (!diffEntry)
2763 return GetDefaultMapDifficulty(mapId, &difficulty);
2764
2765 uint32 tmpDiff = difficulty;
2766 MapDifficultyEntry const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff));
2767 while (!mapDiff)
2768 {
2769 tmpDiff = diffEntry->FallbackDifficultyID;
2770 diffEntry = sDifficultyStore.LookupEntry(tmpDiff);
2771 if (!diffEntry)
2772 return GetDefaultMapDifficulty(mapId, &difficulty);
2773
2774 // pull new data
2775 mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // we are 10 normal or 25 normal
2776 }
2777
2778 difficulty = Difficulty(tmpDiff);
2779 return mapDiff;
2780}
2781
2783{
2784 return Trinity::Containers::MapGetValuePtr(_mapDifficultyConditions, mapDifficultyId);
2785}
2786
2788{
2789 return Trinity::Containers::MapGetValuePtr(_mountsBySpellId, spellId);
2790}
2791
2793{
2794 return sMountStore.LookupEntry(id);
2795}
2796
2798{
2799 return Trinity::Containers::MapGetValuePtr(_mountCapabilitiesByType, mountType);
2800}
2801
2803{
2804 return Trinity::Containers::MapGetValuePtr(_mountDisplays, mountId);
2805}
2806
2807std::string DB2Manager::GetNameGenEntry(uint8 race, uint8 gender) const
2808{
2809 ASSERT(gender < GENDER_NONE);
2810 auto ritr = _nameGenData.find(race);
2811 if (ritr == _nameGenData.end())
2812 return "";
2813
2814 if (ritr->second[gender].empty())
2815 return "";
2816
2817 return Trinity::Containers::SelectRandomContainerElement(ritr->second[gender])->Name;
2818}
2819
2820ResponseCodes DB2Manager::ValidateName(std::wstring const& name, LocaleConstant locale) const
2821{
2822 for (Trinity::wregex const& regex : _nameValidators[locale])
2823 if (Trinity::regex_search(name, regex))
2824 return CHAR_NAME_PROFANE;
2825
2826 // regexes at TOTAL_LOCALES are loaded from NamesReserved which is not locale specific
2827 for (Trinity::wregex const& regex : _nameValidators[TOTAL_LOCALES])
2828 if (Trinity::regex_search(name, regex))
2829 return CHAR_NAME_RESERVED;
2830
2831 return CHAR_NAME_SUCCESS;
2832}
2833
2835{
2836 NumTalentsAtLevelEntry const* numTalentsAtLevel = sNumTalentsAtLevelStore.LookupEntry(level);
2837 if (!numTalentsAtLevel)
2838 numTalentsAtLevel = sNumTalentsAtLevelStore.LookupEntry(sNumTalentsAtLevelStore.GetNumRows() - 1);
2839
2840 if (numTalentsAtLevel)
2841 {
2842 switch (playerClass)
2843 {
2844 case CLASS_DEATH_KNIGHT:
2845 return numTalentsAtLevel->NumTalentsDeathKnight;
2846 case CLASS_DEMON_HUNTER:
2847 return numTalentsAtLevel->NumTalentsDemonHunter;
2848 default:
2849 return numTalentsAtLevel->NumTalents;
2850 }
2851 }
2852
2853 return 0;
2854}
2855
2857{
2858 return Trinity::Containers::MapGetValuePtr(_paragonReputations, factionId);
2859}
2860
2862{
2863 return Trinity::Containers::MapGetValuePtr(_paths, pathId);
2864}
2865
2867{
2868 PVPDifficultyEntry const* maxEntry = nullptr; // used for level > max listed level case
2869 for (PVPDifficultyEntry const* entry : sPVPDifficultyStore)
2870 {
2871 // skip unrelated and too-high brackets
2872 if (entry->MapID != mapid || entry->MinLevel > level)
2873 continue;
2874
2875 // exactly fit
2876 if (entry->MaxLevel >= level)
2877 return entry;
2878
2879 // remember for possible out-of-range case (search higher from existed)
2880 if (!maxEntry || maxEntry->MaxLevel < entry->MaxLevel)
2881 maxEntry = entry;
2882 }
2883
2884 return maxEntry;
2885}
2886
2888{
2889 for (PVPDifficultyEntry const* entry : sPVPDifficultyStore)
2890 if (entry->MapID == mapid && entry->GetBracketId() == id)
2891 return entry;
2892
2893 return nullptr;
2894}
2895
2897{
2899 if (_pvpTalentSlotUnlock[slot])
2900 {
2901 switch (class_)
2902 {
2903 case CLASS_DEATH_KNIGHT:
2904 return _pvpTalentSlotUnlock[slot]->DeathKnightLevelRequired;
2905 case CLASS_DEMON_HUNTER:
2906 return _pvpTalentSlotUnlock[slot]->DemonHunterLevelRequired;
2907 default:
2908 break;
2909 }
2910 return _pvpTalentSlotUnlock[slot]->LevelRequired;
2911 }
2912
2913 return 0;
2914}
2915
2917{
2918 int32 slots = 0;
2919 for (uint8 slot = 0; slot < MAX_PVP_TALENT_SLOTS; ++slot)
2920 if (level >= GetRequiredLevelForPvpTalentSlot(slot, class_))
2921 ++slots;
2922
2923 return slots;
2924}
2925
2926std::vector<QuestLineXQuestEntry const*> const* DB2Manager::GetQuestsForQuestLine(uint32 questLineId) const
2927{
2928 return Trinity::Containers::MapGetValuePtr(_questsByQuestLine, questLineId);
2929}
2930
2931std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItems(uint32 questPackageID) const
2932{
2933 auto itr = _questPackages.find(questPackageID);
2934 if (itr != _questPackages.end())
2935 return &itr->second.first;
2936
2937 return nullptr;
2938}
2939
2940std::vector<QuestPackageItemEntry const*> const* DB2Manager::GetQuestPackageItemsFallback(uint32 questPackageID) const
2941{
2942 auto itr = _questPackages.find(questPackageID);
2943 if (itr != _questPackages.end())
2944 return &itr->second.second;
2945
2946 return nullptr;
2947}
2948
2950{
2951 QuestV2Entry const* v2 = sQuestV2Store.LookupEntry(questId);
2952 if (!v2)
2953 return 0;
2954
2955 return v2->UniqueBitFlag;
2956}
2957
2958std::vector<uint32> const* DB2Manager::GetPhasesForGroup(uint32 group) const
2959{
2960 return Trinity::Containers::MapGetValuePtr(_phasesByGroup, group);
2961}
2962
2964{
2965 ASSERT(power < MAX_POWERS);
2966 return _powerTypes[power];
2967}
2968
2969PowerTypeEntry const* DB2Manager::GetPowerTypeByName(std::string const& name) const
2970{
2971 for (PowerTypeEntry const* powerType : sPowerTypeStore)
2972 {
2973 std::string powerName = powerType->NameGlobalStringTag;
2974 strToLower(powerName);
2975 if (powerName == name)
2976 return powerType;
2977
2978 powerName.erase(std::remove(powerName.begin(), powerName.end(), '_'), powerName.end());
2979 if (powerName == name)
2980 return powerType;
2981 }
2982
2983 return nullptr;
2984}
2985
2987{
2988 auto itr = _pvpItemBonus.find(itemId);
2989 if (itr != _pvpItemBonus.end())
2990 return itr->second;
2991
2992 return 0;
2993}
2994
2995std::vector<RewardPackXCurrencyTypeEntry const*> const* DB2Manager::GetRewardPackCurrencyTypesByRewardID(uint32 rewardPackID) const
2996{
2997 return Trinity::Containers::MapGetValuePtr(_rewardPackCurrencyTypes, rewardPackID);
2998}
2999
3000std::vector<RewardPackXItemEntry const*> const* DB2Manager::GetRewardPackItemsByRewardID(uint32 rewardPackID) const
3001{
3002 return Trinity::Containers::MapGetValuePtr(_rewardPackItems, rewardPackID);
3003}
3004
3006{
3007 return Trinity::Containers::MapGetValuePtr(_chrCustomizationChoicesForShapeshifts, { race, gender, form });
3008}
3009
3010std::vector<SkillLineEntry const*> const* DB2Manager::GetSkillLinesForParentSkill(uint32 parentSkillId) const
3011{
3012 return Trinity::Containers::MapGetValuePtr(_skillLinesByParentSkillLine, parentSkillId);
3013}
3014
3015std::vector<SkillLineAbilityEntry const*> const* DB2Manager::GetSkillLineAbilitiesBySkill(uint32 skillId) const
3016{
3017 return Trinity::Containers::MapGetValuePtr(_skillLineAbilitiesBySkillupSkill, skillId);
3018}
3019
3021{
3022 for (auto&& [_, skllRaceClassInfo] : Trinity::Containers::MapEqualRange(_skillRaceClassInfoBySkill, skill))
3023 {
3024 if (!skllRaceClassInfo->RaceMask.IsEmpty() && !(skllRaceClassInfo->RaceMask.HasRace(race)))
3025 continue;
3026 if (skllRaceClassInfo->ClassMask && !(skllRaceClassInfo->ClassMask & (1 << (class_ - 1))))
3027 continue;
3028
3029 return skllRaceClassInfo;
3030 }
3031
3032 return nullptr;
3033}
3034
3035std::vector<SkillRaceClassInfoEntry const*> DB2Manager::GetSkillRaceClassInfo(uint32 skill) const
3036{
3037 std::vector<SkillRaceClassInfoEntry const*> result;
3038 for (auto const& [_, skillRaceClassInfo] : Trinity::Containers::MapEqualRange(_skillRaceClassInfoBySkill, skill))
3039 result.push_back(skillRaceClassInfo);
3040
3041 return result;
3042}
3043
3045{
3046 return Trinity::Containers::MapGetValuePtr(_soulbindConduitRanks, { soulbindConduitId, rank });
3047}
3048
3049std::vector<SpecializationSpellsEntry const*> const* DB2Manager::GetSpecializationSpells(uint32 specId) const
3050{
3051 return Trinity::Containers::MapGetValuePtr(_specializationSpellsBySpec, specId);
3052}
3053
3054bool DB2Manager::IsSpecSetMember(int32 specSetId, uint32 specId) const
3055{
3056 return _specsBySpecSet.count(std::make_pair(specSetId, specId)) > 0;
3057}
3058
3060{
3061 return _spellFamilyNames.count(family) > 0;
3062}
3063
3064std::vector<SpellProcsPerMinuteModEntry const*> DB2Manager::GetSpellProcsPerMinuteMods(uint32 spellprocsPerMinuteId) const
3065{
3066 auto itr = _spellProcsPerMinuteMods.find(spellprocsPerMinuteId);
3067 if (itr != _spellProcsPerMinuteMods.end())
3068 return itr->second;
3069
3070 return std::vector<SpellProcsPerMinuteModEntry const*>();
3071}
3072
3073std::vector<SpellVisualMissileEntry const*> const* DB2Manager::GetSpellVisualMissiles(int32 spellVisualMissileSetId) const
3074{
3075 return Trinity::Containers::MapGetValuePtr(_spellVisualMissilesBySet, spellVisualMissileSetId);
3076}
3077
3078std::vector<TalentEntry const*> const& DB2Manager::GetTalentsByPosition(uint32 class_, uint32 tier, uint32 column) const
3079{
3080 return _talentsByPosition[class_][tier][column];
3081}
3082
3084{
3085 return Trinity::Containers::MapGetValuePtr(_taxiPaths, { from, to });
3086}
3087
3088bool DB2Manager::IsTotemCategoryCompatibleWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId, bool requireAllTotems /*= true*/)
3089{
3090 if (requiredTotemCategoryId == 0)
3091 return true;
3092 if (itemTotemCategoryId == 0)
3093 return false;
3094
3095 TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId);
3096 if (!itemEntry)
3097 return false;
3098 TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId);
3099 if (!reqEntry)
3100 return false;
3101
3102 if (itemEntry->TotemCategoryType != reqEntry->TotemCategoryType)
3103 return false;
3104
3105 int32 sharedMask = itemEntry->TotemCategoryMask & reqEntry->TotemCategoryMask;
3106 return requireAllTotems ? sharedMask == reqEntry->TotemCategoryMask : sharedMask != 0;
3107}
3108
3110{
3111 return _toys.count(toy) > 0;
3112}
3113
3115{
3116 return Trinity::Containers::MapGetValuePtr(_transmogIllusionsByEnchantmentId, spellItemEnchantmentId);
3117}
3118
3119std::vector<TransmogSetEntry const*> const* DB2Manager::GetTransmogSetsForItemModifiedAppearance(uint32 itemModifiedAppearanceId) const
3120{
3121 return Trinity::Containers::MapGetValuePtr(_transmogSetsByItemModifiedAppearance, itemModifiedAppearanceId);
3122}
3123
3124std::vector<TransmogSetItemEntry const*> const* DB2Manager::GetTransmogSetItems(uint32 transmogSetId) const
3125{
3126 return Trinity::Containers::MapGetValuePtr(_transmogSetItemsByTransmogSet, transmogSetId);
3127}
3128
3130{
3132 // distances if inside
3133 struct
3134 {
3135 float DistanceToRegionCenterSquared = std::numeric_limits<float>::max();
3136 float DistanceToRegionBottom = std::numeric_limits<float>::max();
3138
3139 // distances if outside
3140 struct
3141 {
3142 float DistanceToRegionEdgeSquared = std::numeric_limits<float>::max();
3143 float DistanceToRegionTop = std::numeric_limits<float>::max();
3144 float DistanceToRegionBottom = std::numeric_limits<float>::max();
3146
3150
3151 bool IsInside() const
3152 {
3153 return Outside.DistanceToRegionEdgeSquared < std::numeric_limits<float>::epsilon() &&
3154 std::abs(Outside.DistanceToRegionTop) < std::numeric_limits<float>::epsilon() &&
3155 std::abs(Outside.DistanceToRegionBottom) < std::numeric_limits<float>::epsilon();
3156 }
3157};
3158
3159static bool operator<(UiMapAssignmentStatus const& left, UiMapAssignmentStatus const& right)
3160{
3161 bool leftInside = left.IsInside();
3162 bool rightInside = right.IsInside();
3163 if (leftInside != rightInside)
3164 return leftInside;
3165
3166 if (left.UiMapAssignment && right.UiMapAssignment &&
3170
3171 if (left.WmoPriority != right.WmoPriority)
3172 return left.WmoPriority < right.WmoPriority;
3173
3174 if (left.AreaPriority != right.AreaPriority)
3175 return left.AreaPriority < right.AreaPriority;
3176
3177 if (left.MapPriority != right.MapPriority)
3178 return left.MapPriority < right.MapPriority;
3179
3180 if (leftInside)
3181 {
3184
3185 float leftUiSizeX = left.UiMapAssignment ? (left.UiMapAssignment->UiMax.X - left.UiMapAssignment->UiMin.X) : 0.0f;
3186 float rightUiSizeX = right.UiMapAssignment ? (right.UiMapAssignment->UiMax.X - right.UiMapAssignment->UiMin.X) : 0.0f;
3187
3188 if (leftUiSizeX > std::numeric_limits<float>::epsilon() && rightUiSizeX > std::numeric_limits<float>::epsilon())
3189 {
3190 float leftScale = (left.UiMapAssignment->Region[1].X - left.UiMapAssignment->Region[0].X) / leftUiSizeX;
3191 float rightScale = (right.UiMapAssignment->Region[1].X - right.UiMapAssignment->Region[0].X) / rightUiSizeX;
3192 if (leftScale != rightScale)
3193 return leftScale < rightScale;
3194 }
3195
3198 }
3199 else
3200 {
3203
3206
3209 }
3210
3211 return true;
3212}
3213
3214static bool CheckUiMapAssignmentStatus(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId,
3215 UiMapAssignmentEntry const* uiMapAssignment, UiMapAssignmentStatus* status)
3216{
3217 status->UiMapAssignment = uiMapAssignment;
3218 // x,y not in region
3219 if (x < uiMapAssignment->Region[0].X || x > uiMapAssignment->Region[1].X || y < uiMapAssignment->Region[0].Y || y > uiMapAssignment->Region[1].Y)
3220 {
3221 float xDiff, yDiff;
3222 if (x >= uiMapAssignment->Region[0].X)
3223 {
3224 xDiff = 0.0f;
3225 if (x > uiMapAssignment->Region[1].X)
3226 xDiff = x - uiMapAssignment->Region[0].X;
3227 }
3228 else
3229 xDiff = uiMapAssignment->Region[0].X - x;
3230
3231 if (y >= uiMapAssignment->Region[0].Y)
3232 {
3233 yDiff = 0.0f;
3234 if (y > uiMapAssignment->Region[1].Y)
3235 yDiff = y - uiMapAssignment->Region[0].Y;
3236 }
3237 else
3238 yDiff = uiMapAssignment->Region[0].Y - y;
3239
3240 status->Outside.DistanceToRegionEdgeSquared = xDiff * xDiff + yDiff * yDiff;
3241 }
3242 else
3243 {
3245 (x - (uiMapAssignment->Region[0].X + uiMapAssignment->Region[1].X) * 0.5f) * (x - (uiMapAssignment->Region[0].X + uiMapAssignment->Region[1].X) * 0.5f)
3246 + (y - (uiMapAssignment->Region[0].Y + uiMapAssignment->Region[1].Y) * 0.5f) * (y - (uiMapAssignment->Region[0].Y + uiMapAssignment->Region[1].Y) * 0.5f);
3247 status->Outside.DistanceToRegionEdgeSquared = 0.0f;
3248 }
3249
3250 // z not in region
3251 if (z < uiMapAssignment->Region[0].Z || z > uiMapAssignment->Region[1].Z)
3252 {
3253 if (z < uiMapAssignment->Region[1].Z)
3254 {
3255 if (z < uiMapAssignment->Region[0].Z)
3256 status->Outside.DistanceToRegionBottom = std::min(uiMapAssignment->Region[0].Z - z, 10000.0f);
3257 }
3258 else
3259 status->Outside.DistanceToRegionTop = std::min(z - uiMapAssignment->Region[1].Z, 10000.0f);
3260 }
3261 else
3262 {
3263 status->Outside.DistanceToRegionTop = 0.0f;
3264 status->Outside.DistanceToRegionBottom = 0.0f;
3265 status->Inside.DistanceToRegionBottom = std::min(uiMapAssignment->Region[0].Z - z, 10000.0f);
3266 }
3267
3268 if (areaId && uiMapAssignment->AreaID)
3269 {
3270 int8 areaPriority = 0;
3271 while (areaId != uiMapAssignment->AreaID)
3272 {
3273 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId))
3274 {
3275 areaId = areaEntry->ParentAreaID;
3276 ++areaPriority;
3277 }
3278 else
3279 return false;
3280 }
3281
3282 status->AreaPriority = areaPriority;
3283 }
3284
3285 if (mapId >= 0 && uiMapAssignment->MapID >= 0)
3286 {
3287 if (mapId != uiMapAssignment->MapID)
3288 {
3289 if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId))
3290 {
3291 if (mapEntry->ParentMapID == uiMapAssignment->MapID)
3292 status->MapPriority = 1;
3293 else if (mapEntry->CosmeticParentMapID == uiMapAssignment->MapID)
3294 status->MapPriority = 2;
3295 else
3296 return false;
3297 }
3298 else
3299 return false;
3300 }
3301 else
3302 status->MapPriority = 0;
3303 }
3304
3305 if (wmoGroupId || wmoDoodadPlacementId)
3306 {
3307 if (uiMapAssignment->WmoGroupID || uiMapAssignment->WmoDoodadPlacementID)
3308 {
3309 bool hasDoodadPlacement = false;
3310 if (wmoDoodadPlacementId && uiMapAssignment->WmoDoodadPlacementID)
3311 {
3312 if (wmoDoodadPlacementId != uiMapAssignment->WmoDoodadPlacementID)
3313 return false;
3314
3315 hasDoodadPlacement = true;
3316 }
3317
3318 if (wmoGroupId && uiMapAssignment->WmoGroupID)
3319 {
3320 if (wmoGroupId != uiMapAssignment->WmoGroupID)
3321 return false;
3322
3323 if (hasDoodadPlacement)
3324 status->WmoPriority = 0;
3325 else
3326 status->WmoPriority = 2;
3327 }
3328 else if (hasDoodadPlacement)
3329 status->WmoPriority = 1;
3330 }
3331 }
3332
3333 return true;
3334}
3335
3336static UiMapAssignmentEntry const* FindNearestMapAssignment(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system)
3337{
3338 UiMapAssignmentStatus nearestMapAssignment;
3339 auto iterateUiMapAssignments = [&](std::unordered_multimap<int32, UiMapAssignmentEntry const*> const& assignments, int32 id)
3340 {
3341 for (auto assignment : Trinity::Containers::MapEqualRange(assignments, id))
3342 {
3343 UiMapAssignmentStatus status;
3344 if (CheckUiMapAssignmentStatus(x, y, z, mapId, areaId, wmoDoodadPlacementId, wmoGroupId, assignment.second, &status))
3345 if (status < nearestMapAssignment)
3346 nearestMapAssignment = status;
3347 }
3348 };
3349
3350 iterateUiMapAssignments(_uiMapAssignmentByWmoGroup[system], wmoGroupId);
3351 iterateUiMapAssignments(_uiMapAssignmentByWmoDoodadPlacement[system], wmoDoodadPlacementId);
3352
3353 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId);
3354 while (areaEntry)
3355 {
3356 iterateUiMapAssignments(_uiMapAssignmentByArea[system], areaEntry->ID);
3357 areaEntry = sAreaTableStore.LookupEntry(areaEntry->ParentAreaID);
3358 }
3359
3360 if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId))
3361 {
3362 iterateUiMapAssignments(_uiMapAssignmentByMap[system], mapEntry->ID);
3363 if (mapEntry->ParentMapID >= 0)
3364 iterateUiMapAssignments(_uiMapAssignmentByMap[system], mapEntry->ParentMapID);
3365 if (mapEntry->CosmeticParentMapID >= 0)
3366 iterateUiMapAssignments(_uiMapAssignmentByMap[system], mapEntry->CosmeticParentMapID);
3367 }
3368
3369 return nearestMapAssignment.UiMapAssignment;
3370}
3371
3373{
3374 UiMapEntry const* uiMap = sUiMapStore.LookupEntry(uiMapID);
3375 while (uiMap)
3376 {
3377 if (uiMap->Type <= UI_MAP_TYPE_CONTINENT)
3378 break;
3379
3380 UiMapBounds const* bounds = Trinity::Containers::MapGetValuePtr(_uiMapBounds, uiMap->ID);
3381 if (!bounds || !bounds->IsUiAssignment)
3382 break;
3383
3384 uiPosition.X = ((1.0 - uiPosition.X) * bounds->Bounds[1]) + (bounds->Bounds[3] * uiPosition.X);
3385 uiPosition.Y = ((1.0 - uiPosition.Y) * bounds->Bounds[0]) + (bounds->Bounds[2] * uiPosition.Y);
3386
3387 uiMap = sUiMapStore.LookupEntry(uiMap->ParentUiMapID);
3388 }
3389
3390 return uiPosition;
3391}
3392
3393bool DB2Manager::GetUiMapPosition(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system, bool local,
3394 uint32* uiMapId /*= nullptr*/, DBCPosition2D* newPos /*= nullptr*/)
3395{
3396 if (uiMapId)
3397 *uiMapId = -1;
3398
3399 if (newPos)
3400 {
3401 newPos->X = 0.0f;
3402 newPos->Y = 0.0f;
3403 }
3404
3405 UiMapAssignmentEntry const* uiMapAssignment = FindNearestMapAssignment(x, y, z, mapId, areaId, wmoDoodadPlacementId, wmoGroupId, system);
3406 if (!uiMapAssignment)
3407 return false;
3408
3409 if (uiMapId)
3410 *uiMapId = uiMapAssignment->UiMapID;
3411
3412 DBCPosition2D relativePosition{ 0.5f, 0.5f };
3413 DBCPosition2D regionSize{ uiMapAssignment->Region[1].X - uiMapAssignment->Region[0].X, uiMapAssignment->Region[1].Y - uiMapAssignment->Region[0].Y };
3414 if (regionSize.X > 0.0f)
3415 relativePosition.X = (x - uiMapAssignment->Region[0].X) / regionSize.X;
3416 if (regionSize.Y > 0.0f)
3417 relativePosition.Y = (y - uiMapAssignment->Region[0].Y) / regionSize.Y;
3418
3419 DBCPosition2D uiPosition
3420 {
3421 // x and y are swapped
3422 ((1.0f - (1.0f - relativePosition.Y)) * uiMapAssignment->UiMin.X) + ((1.0f - relativePosition.Y) * uiMapAssignment->UiMax.X),
3423 ((1.0f - (1.0f - relativePosition.X)) * uiMapAssignment->UiMin.Y) + ((1.0f - relativePosition.X) * uiMapAssignment->UiMax.Y)
3424 };
3425
3426 if (!local)
3427 uiPosition = CalculateGlobalUiMapPosition(uiMapAssignment->UiMapID, uiPosition);
3428
3429 if (newPos)
3430 *newPos = uiPosition;
3431
3432 return true;
3433}
3434
3435bool DB2Manager::Zone2MapCoordinates(uint32 areaId, float& x, float& y) const
3436{
3437 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId);
3438 if (!areaEntry)
3439 return false;
3440
3441 for (auto assignment : Trinity::Containers::MapEqualRange(_uiMapAssignmentByArea[UI_MAP_SYSTEM_WORLD], areaId))
3442 {
3443 if (assignment.second->MapID >= 0 && assignment.second->MapID != areaEntry->ContinentID)
3444 continue;
3445
3446 float tmpY = (y - assignment.second->UiMax.Y) / (assignment.second->UiMin.Y - assignment.second->UiMax.Y);
3447 float tmpX = (x - assignment.second->UiMax.X) / (assignment.second->UiMin.X - assignment.second->UiMax.X);
3448 x = assignment.second->Region[0].X + tmpY * (assignment.second->Region[1].X - assignment.second->Region[0].X);
3449 y = assignment.second->Region[0].Y + tmpX * (assignment.second->Region[1].Y - assignment.second->Region[0].Y);
3450
3451 return true;
3452 }
3453
3454 return false;
3455}
3456
3457void DB2Manager::Map2ZoneCoordinates(uint32 areaId, float& x, float& y) const
3458{
3459 DBCPosition2D zoneCoords;
3460 if (!GetUiMapPosition(x, y, 0.0f, -1, areaId, 0, 0, UI_MAP_SYSTEM_WORLD, true, nullptr, &zoneCoords))
3461 return;
3462
3463 x = zoneCoords.Y * 100.0f;
3464 y = zoneCoords.X * 100.0f;
3465}
3466
3468{
3469 return _uiMapPhases.find(phaseId) != _uiMapPhases.end();
3470}
3471
3473{
3474 return Trinity::Containers::MapGetValuePtr(_wmoAreaTableLookup, WMOAreaTableKey(int16(rootId), int8(adtId), groupId));
3475}
3476
3477std::unordered_set<uint32> const* DB2Manager::GetPVPStatIDsForMap(uint32 mapId) const
3478{
3479 return Trinity::Containers::MapGetValuePtr(_pvpStatIdsByMap, mapId);
3480}
3481
3482bool ChrClassesXPowerTypesEntryComparator::Compare(ChrClassesXPowerTypesEntry const* left, ChrClassesXPowerTypesEntry const* right)
3483{
3484 if (left->ClassID != right->ClassID)
3485 return left->ClassID < right->ClassID;
3486 return left->PowerType < right->PowerType;
3487}
3488
3490{
3491 if (sTaxiNodesStore.GetNumRows())
3492 {
3493 _data.resize((sTaxiNodesStore.GetNumRows() + (8 * sizeof(uint64) - 1)) / (8 * sizeof(uint64)) * (sizeof(uint64) / sizeof(value_type)), 0);
3494 ASSERT((_data.size() % 8) == 0, "TaxiMask size must be aligned to a multiple of uint64");
3495 }
3496}
3497
3498bool DB2Manager::FriendshipRepReactionEntryComparator::Compare(FriendshipRepReactionEntry const* left, FriendshipRepReactionEntry const* right)
3499{
3500 return left->ReactionThreshold < right->ReactionThreshold;
3501}
3502
3503bool DB2Manager::MountTypeXCapabilityEntryComparator::Compare(MountTypeXCapabilityEntry const* left, MountTypeXCapabilityEntry const* right)
3504{
3505 if (left->MountTypeID == right->MountTypeID)
3506 return left->OrderIndex < right->OrderIndex;
3507 return left->MountTypeID < right->MountTypeID;
3508}
char const * localeNames[TOTAL_LOCALES]
Definition: Common.cpp:20
LocaleConstant GetLocaleByName(std::string_view name)
Definition: Common.cpp:36
CascLocaleBit WowLocaleToCascLocaleBit[TOTAL_LOCALES]
Definition: Common.cpp:45
LocaleConstant
Definition: Common.h:48
@ LOCALE_none
Definition: Common.h:58
@ TOTAL_LOCALES
Definition: Common.h:62
@ LOCALE_enUS
Definition: Common.h:49
@ LOCALE_koKR
Definition: Common.h:50
constexpr bool IsValidLocale(LocaleConstant locale)
Definition: Common.h:95
CascLocaleBit
Definition: Common.h:69
#define DEFAULT_LOCALE
Definition: Common.h:66
#define M_PI
Definition: Common.h:115
DB2Storage< UISplashScreenEntry > sUISplashScreenStore("UISplashScreen.db2", &UiSplashScreenLoadInfo::Instance)
DB2Storage< LightEntry > sLightStore("Light.db2", &LightLoadInfo::Instance)
DB2Storage< AzeritePowerSetMemberEntry > sAzeritePowerSetMemberStore("AzeritePowerSetMember.db2", &AzeritePowerSetMemberLoadInfo::Instance)
DB2Storage< QuestFactionRewardEntry > sQuestFactionRewardStore("QuestFactionReward.db2", &QuestFactionRewardLoadInfo::Instance)
DB2Storage< PhaseEntry > sPhaseStore("Phase.db2", &PhaseLoadInfo::Instance)
DB2Storage< ArtifactAppearanceEntry > sArtifactAppearanceStore("ArtifactAppearance.db2", &ArtifactAppearanceLoadInfo::Instance)
DB2Storage< BankBagSlotPricesEntry > sBankBagSlotPricesStore("BankBagSlotPrices.db2", &BankBagSlotPricesLoadInfo::Instance)
DB2Storage< SkillRaceClassInfoEntry > sSkillRaceClassInfoStore("SkillRaceClassInfo.db2", &SkillRaceClassInfoLoadInfo::Instance)
DB2Storage< ItemNameDescriptionEntry > sItemNameDescriptionStore("ItemNameDescription.db2", &ItemNameDescriptionLoadInfo::Instance)
DB2Storage< ChrRaceXChrModelEntry > sChrRaceXChrModelStore("ChrRaceXChrModel.db2", &ChrRaceXChrModelLoadInfo::Instance)
DB2Storage< ItemLimitCategoryEntry > sItemLimitCategoryStore("ItemLimitCategory.db2", &ItemLimitCategoryLoadInfo::Instance)
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< WorldMapOverlayEntry > sWorldMapOverlayStore("WorldMapOverlay.db2", &WorldMapOverlayLoadInfo::Instance)
ChrSpecializationEntry const * ChrSpecializationByIndexContainer[MAX_CLASSES+1][MAX_SPECIALIZATIONS]
Definition: DB2Stores.cpp:404
DB2Storage< ItemModifiedAppearanceExtraEntry > sItemModifiedAppearanceExtraStore("ItemModifiedAppearanceExtra.db2", &ItemModifiedAppearanceExtraLoadInfo::Instance)
DB2Storage< ItemDamageTwoHandCasterEntry > sItemDamageTwoHandCasterStore("ItemDamageTwoHandCaster.db2", &ItemDamageTwoHandCasterLoadInfo::Instance)
DB2Storage< ItemLevelSelectorEntry > sItemLevelSelectorStore("ItemLevelSelector.db2", &ItemLevelSelectorLoadInfo::Instance)
DB2Storage< NamesReservedEntry > sNamesReservedStore("NamesReserved.db2", &NamesReservedLoadInfo::Instance)
DB2Storage< GameObjectDisplayInfoEntry > sGameObjectDisplayInfoStore("GameObjectDisplayInfo.db2", &GameobjectDisplayInfoLoadInfo::Instance)
DB2Storage< SceneScriptEntry > sSceneScriptStore("SceneScript.db2", &SceneScriptLoadInfo::Instance)
DB2Storage< CharacterLoadoutEntry > sCharacterLoadoutStore("CharacterLoadout.db2", &CharacterLoadoutLoadInfo::Instance)
DB2Storage< SpellVisualEntry > sSpellVisualStore("SpellVisual.db2", &SpellVisualLoadInfo::Instance)
DB2Storage< PVPItemEntry > sPVPItemStore("PVPItem.db2", &PvpItemLoadInfo::Instance)
DB2Storage< ItemEntry > sItemStore("Item.db2", &ItemLoadInfo::Instance)
DB2Storage< Achievement_CategoryEntry > sAchievementCategoryStore("Achievement_Category.db2", &AchievementCategoryLoadInfo::Instance)
DB2Storage< ItemSearchNameEntry > sItemSearchNameStore("ItemSearchName.db2", &ItemSearchNameLoadInfo::Instance)
DB2Storage< PhaseXPhaseGroupEntry > sPhaseXPhaseGroupStore("PhaseXPhaseGroup.db2", &PhaseXPhaseGroupLoadInfo::Instance)
std::unordered_map< uint32, std::unordered_map< uint32, MapDifficultyEntry const * > > MapDifficultyContainer
Definition: DB2Stores.cpp:417
DB2Storage< BattlemasterListEntry > sBattlemasterListStore("BattlemasterList.db2", &BattlemasterListLoadInfo::Instance)
DB2Storage< PathEntry > sPathStore("Path.db2", &PathLoadInfo::Instance)
TaxiMask sAllianceTaxiNodesMask
Definition: DB2Stores.cpp:394
std::unordered_map< uint32, std::vector< DBCPosition2D > > CurvePointsContainer
Definition: DB2Stores.cpp:405
DB2Storage< AzeriteEssencePowerEntry > sAzeriteEssencePowerStore("AzeriteEssencePower.db2", &AzeriteEssencePowerLoadInfo::Instance)
DB2Storage< SpellInterruptsEntry > sSpellInterruptsStore("SpellInterrupts.db2", &SpellInterruptsLoadInfo::Instance)
DB2Storage< TraitCurrencySourceEntry > sTraitCurrencySourceStore("TraitCurrencySource.db2", &TraitCurrencySourceLoadInfo::Instance)
DB2Storage< SkillLineEntry > sSkillLineStore("SkillLine.db2", &SkillLineLoadInfo::Instance)
DB2Storage< TraitTreeXTraitCostEntry > sTraitTreeXTraitCostStore("TraitTreeXTraitCost.db2", &TraitTreeXTraitCostLoadInfo::Instance)
DB2Storage< OverrideSpellDataEntry > sOverrideSpellDataStore("OverrideSpellData.db2", &OverrideSpellDataLoadInfo::Instance)
DB2Storage< AnimationDataEntry > sAnimationDataStore("AnimationData.db2", &AnimationDataLoadInfo::Instance)
DB2Storage< FriendshipReputationEntry > sFriendshipReputationStore("FriendshipReputation.db2", &FriendshipReputationLoadInfo::Instance)
DB2Storage< BattlePetBreedQualityEntry > sBattlePetBreedQualityStore("BattlePetBreedQuality.db2", &BattlePetBreedQualityLoadInfo::Instance)
DB2Storage< EmotesTextEntry > sEmotesTextStore("EmotesText.db2", &EmotesTextLoadInfo::Instance)
DB2Storage< ArtifactEntry > sArtifactStore("Artifact.db2", &ArtifactLoadInfo::Instance)
DB2Storage< ArtifactPowerPickerEntry > sArtifactPowerPickerStore("ArtifactPowerPicker.db2", &ArtifactPowerPickerLoadInfo::Instance)
DB2Storage< TraitNodeGroupXTraitCondEntry > sTraitNodeGroupXTraitCondStore("TraitNodeGroupXTraitCond.db2", &TraitNodeGroupXTraitCondLoadInfo::Instance)
std::unordered_map< uint32, HeirloomEntry const * > HeirloomItemsContainer
Definition: DB2Stores.cpp:408
DB2Storage< ArtifactQuestXPEntry > sArtifactQuestXPStore("ArtifactQuestXP.db2", &ArtifactQuestXpLoadInfo::Instance)
DB2Storage< JournalEncounterSectionEntry > sJournalEncounterSectionStore("JournalEncounterSection.db2", &JournalEncounterSectionLoadInfo::Instance)
DB2Storage< BattlePetBreedStateEntry > sBattlePetBreedStateStore("BattlePetBreedState.db2", &BattlePetBreedStateLoadInfo::Instance)
static DBCPosition2D CalculateGlobalUiMapPosition(uint32 uiMapID, DBCPosition2D uiPosition)
Definition: DB2Stores.cpp:3372
DB2Storage< PVPStatEntry > sPVPStatStore("PVPStat.db2", &PvpStatLoadInfo::Instance)
std::unordered_map< uint32, ItemChildEquipmentEntry const * > ItemChildEquipmentContainer
Definition: DB2Stores.cpp:411
DB2Storage< PvpTalentCategoryEntry > sPvpTalentCategoryStore("PvpTalentCategory.db2", &PvpTalentCategoryLoadInfo::Instance)
DB2Storage< ItemBonusTreeEntry > sItemBonusTreeStore("ItemBonusTree.db2", &ItemBonusTreeLoadInfo::Instance)
DB2Storage< RandPropPointsEntry > sRandPropPointsStore("RandPropPoints.db2", &RandPropPointsLoadInfo::Instance)
DB2Storage< ItemBagFamilyEntry > sItemBagFamilyStore("ItemBagFamily.db2", &ItemBagFamilyLoadInfo::Instance)
DB2Storage< GameObjectsEntry > sGameObjectsStore("GameObjects.db2", &GameobjectsLoadInfo::Instance)
DB2Storage< SpellAuraOptionsEntry > sSpellAuraOptionsStore("SpellAuraOptions.db2", &SpellAuraOptionsLoadInfo::Instance)
std::unordered_map< uint32, std::unordered_map< uint32, std::vector< SpellPowerEntry const * > > > SpellPowerDifficultyContainer
Definition: DB2Stores.cpp:428
DB2Storage< TraitNodeGroupXTraitNodeEntry > sTraitNodeGroupXTraitNodeStore("TraitNodeGroupXTraitNode.db2", &TraitNodeGroupXTraitNodeLoadInfo::Instance)
DB2Storage< SpellCategoryEntry > sSpellCategoryStore("SpellCategory.db2", &SpellCategoryLoadInfo::Instance)
DB2Storage< AchievementEntry > sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance)
DB2Storage< ImportPriceWeaponEntry > sImportPriceWeaponStore("ImportPriceWeapon.db2", &ImportPriceWeaponLoadInfo::Instance)
DB2Storage< FriendshipRepReactionEntry > sFriendshipRepReactionStore("FriendshipRepReaction.db2", &FriendshipRepReactionLoadInfo::Instance)
DB2Storage< GarrMissionEntry > sGarrMissionStore("GarrMission.db2", &GarrMissionLoadInfo::Instance)
std::array< ItemClassEntry const *, 20 > ItemClassByOldEnumContainer
Definition: DB2Stores.cpp:412
DB2Storage< SpellNameEntry > sSpellNameStore("SpellName.db2", &SpellNameLoadInfo::Instance)
DB2Storage< CurveEntry > sCurveStore("Curve.db2", &CurveLoadInfo::Instance)
DB2Storage< PvpSeasonEntry > sPvpSeasonStore("PvpSeason.db2", &PvpSeasonLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< TraitNodeEntry > sTraitNodeStore("TraitNode.db2", &TraitNodeLoadInfo::Instance)
DB2Storage< TaxiNodesEntry > sTaxiNodesStore("TaxiNodes.db2", &TaxiNodesLoadInfo::Instance)
std::unordered_map< uint32, ItemModifiedAppearanceEntry const * > ItemModifiedAppearanceByItemContainer
Definition: DB2Stores.cpp:414
DB2Storage< CreatureModelDataEntry > sCreatureModelDataStore("CreatureModelData.db2", &CreatureModelDataLoadInfo::Instance)
DB2Storage< LiquidTypeEntry > sLiquidTypeStore("LiquidType.db2", &LiquidTypeLoadInfo::Instance)
DB2Storage< ConditionalChrModelEntry > sConditionalChrModelStore("ConditionalChrModel.db2", &ConditionalChrModelLoadInfo::Instance)
DB2Storage< CreatureFamilyEntry > sCreatureFamilyStore("CreatureFamily.db2", &CreatureFamilyLoadInfo::Instance)
std::map< uint32, DB2StorageBase * > StorageMap
Definition: DB2Stores.cpp:399
DB2Storage< CurvePointEntry > sCurvePointStore("CurvePoint.db2", &CurvePointLoadInfo::Instance)
DB2Storage< SpellXSpellVisualEntry > sSpellXSpellVisualStore("SpellXSpellVisual.db2", &SpellXSpellVisualLoadInfo::Instance)
DB2Storage< CharacterLoadoutItemEntry > sCharacterLoadoutItemStore("CharacterLoadoutItem.db2", &CharacterLoadoutItemLoadInfo::Instance)
DB2Storage< AnimKitEntry > sAnimKitStore("AnimKit.db2", &AnimKitLoadInfo::Instance)
DB2Storage< MapDifficultyEntry > sMapDifficultyStore("MapDifficulty.db2", &MapDifficultyLoadInfo::Instance)
DB2Storage< SpellEquippedItemsEntry > sSpellEquippedItemsStore("SpellEquippedItems.db2", &SpellEquippedItemsLoadInfo::Instance)
DB2Storage< ItemBonusEntry > sItemBonusStore("ItemBonus.db2", &ItemBonusLoadInfo::Instance)
DB2Storage< UiMapLinkEntry > sUiMapLinkStore("UiMapLink.db2", &UiMapLinkLoadInfo::Instance)
static UiMapAssignmentEntry const * FindNearestMapAssignment(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapSystem system)
Definition: DB2Stores.cpp:3336
static bool CheckUiMapAssignmentStatus(float x, float y, float z, int32 mapId, int32 areaId, int32 wmoDoodadPlacementId, int32 wmoGroupId, UiMapAssignmentEntry const *uiMapAssignment, UiMapAssignmentStatus *status)
Definition: DB2Stores.cpp:3214
DB2Storage< UnitPowerBarEntry > sUnitPowerBarStore("UnitPowerBar.db2", &UnitPowerBarLoadInfo::Instance)
TaxiMask sTaxiNodesMask
Definition: DB2Stores.cpp:391
DB2Storage< SpellReagentsEntry > sSpellReagentsStore("SpellReagents.db2", &SpellReagentsLoadInfo::Instance)
DB2Storage< LanguageWordsEntry > sLanguageWordsStore("LanguageWords.db2", &LanguageWordsLoadInfo::Instance)
DB2Storage< SkillLineXTraitTreeEntry > sSkillLineXTraitTreeStore("SkillLineXTraitTree.db2", &SkillLineXTraitTreeLoadInfo::Instance)
std::unordered_map< uint32, std::vector< uint32 > > ArtifactPowerLinksContainer
Definition: DB2Stores.cpp:402
DB2Storage< TraitCostEntry > sTraitCostStore("TraitCost.db2", &TraitCostLoadInfo::Instance)
DB2Storage< ArtifactCategoryEntry > sArtifactCategoryStore("ArtifactCategory.db2", &ArtifactCategoryLoadInfo::Instance)
DB2Storage< ServerMessagesEntry > sServerMessagesStore("ServerMessages.db2", &ServerMessagesLoadInfo::Instance)
DB2Storage< ItemChildEquipmentEntry > sItemChildEquipmentStore("ItemChildEquipment.db2", &ItemChildEquipmentLoadInfo::Instance)
DB2Storage< SpecSetMemberEntry > sSpecSetMemberStore("SpecSetMember.db2", &SpecSetMemberLoadInfo::Instance)
DB2Storage< GarrBuildingPlotInstEntry > sGarrBuildingPlotInstStore("GarrBuildingPlotInst.db2", &GarrBuildingPlotInstLoadInfo::Instance)
DB2Storage< ItemBonusTreeNodeEntry > sItemBonusTreeNodeStore("ItemBonusTreeNode.db2", &ItemBonusTreeNodeLoadInfo::Instance)
DB2Storage< CreatureLabelEntry > sCreatureLabelStore("CreatureLabel.db2", &CreatureLabelLoadInfo::Instance)
DB2Storage< ChrCustomizationOptionEntry > sChrCustomizationOptionStore("ChrCustomizationOption.db2", &ChrCustomizationOptionLoadInfo::Instance)
DB2Storage< ItemSpecOverrideEntry > sItemSpecOverrideStore("ItemSpecOverride.db2", &ItemSpecOverrideLoadInfo::Instance)
DB2Storage< CreatureTypeEntry > sCreatureTypeStore("CreatureType.db2", &CreatureTypeLoadInfo::Instance)
DB2Storage< DurabilityQualityEntry > sDurabilityQualityStore("DurabilityQuality.db2", &DurabilityQualityLoadInfo::Instance)
DB2Storage< AreaTriggerActionSetEntry > sAreaTriggerActionSetStore("AreaTriggerActionSet.db2", &AreaTriggerActionSetLoadInfo::Instance)
DB2Storage< ChrCustomizationElementEntry > sChrCustomizationElementStore("ChrCustomizationElement.db2", &ChrCustomizationElementLoadInfo::Instance)
DB2Storage< SpellPowerDifficultyEntry > sSpellPowerDifficultyStore("SpellPowerDifficulty.db2", &SpellPowerDifficultyLoadInfo::Instance)
DB2Storage< ArtifactPowerEntry > sArtifactPowerStore("ArtifactPower.db2", &ArtifactPowerLoadInfo::Instance)
DB2Storage< TraitTreeLoadoutEntry > sTraitTreeLoadoutStore("TraitTreeLoadout.db2", &TraitTreeLoadoutLoadInfo::Instance)
DB2Storage< CriteriaEntry > sCriteriaStore("Criteria.db2", &CriteriaLoadInfo::Instance)
TaxiPathNodesByPath sTaxiPathNodesByPath
Definition: DB2Stores.cpp:395
DB2Storage< ChallengeModeItemBonusOverrideEntry > sChallengeModeItemBonusOverrideStore("ChallengeModeItemBonusOverride.db2", &ChallengeModeItemBonusOverrideLoadInfo::Instance)
DB2Storage< AzeriteItemMilestonePowerEntry > sAzeriteItemMilestonePowerStore("AzeriteItemMilestonePower.db2", &AzeriteItemMilestonePowerLoadInfo::Instance)
std::pair< uint32, int32 > HotfixBlobKey
Definition: DB2Stores.cpp:434
DB2Storage< QuestMoneyRewardEntry > sQuestMoneyRewardStore("QuestMoneyReward.db2", &QuestMoneyRewardLoadInfo::Instance)
DB2Storage< ItemXItemEffectEntry > sItemXItemEffectStore("ItemXItemEffect.db2", &ItemXItemEffectLoadInfo::Instance)
DB2Storage< ScenarioEntry > sScenarioStore("Scenario.db2", &ScenarioLoadInfo::Instance)
DB2Storage< TraitNodeXTraitNodeEntryEntry > sTraitNodeXTraitNodeEntryStore("TraitNodeXTraitNodeEntry.db2", &TraitNodeXTraitNodeEntryLoadInfo::Instance)
std::unordered_map< uint32, std::vector< ChrSpecialization > > GlyphRequiredSpecsContainer
Definition: DB2Stores.cpp:410
DB2Storage< JournalInstanceEntry > sJournalInstanceStore("JournalInstance.db2", &JournalInstanceLoadInfo::Instance)
DB2Storage< ItemDamageOneHandEntry > sItemDamageOneHandStore("ItemDamageOneHand.db2", &ItemDamageOneHandLoadInfo::Instance)
DB2Storage< TransmogIllusionEntry > sTransmogIllusionStore("TransmogIllusion.db2", &TransmogIllusionLoadInfo::Instance)
std::unordered_map< uint32, std::vector< ItemSpecOverrideEntry const * > > ItemSpecOverridesContainer
Definition: DB2Stores.cpp:416
static CurveInterpolationMode DetermineCurveType(CurveEntry const *curve, std::vector< DBCPosition2D > const &points)
Definition: DB2Stores.cpp:2274
DB2Storage< TransmogSetEntry > sTransmogSetStore("TransmogSet.db2", &TransmogSetLoadInfo::Instance)
DB2Storage< GuildColorEmblemEntry > sGuildColorEmblemStore("GuildColorEmblem.db2", &GuildColorEmblemLoadInfo::Instance)
DB2Storage< GarrBuildingEntry > sGarrBuildingStore("GarrBuilding.db2", &GarrBuildingLoadInfo::Instance)
DB2Storage< TraitNodeGroupXTraitCostEntry > sTraitNodeGroupXTraitCostStore("TraitNodeGroupXTraitCost.db2", &TraitNodeGroupXTraitCostLoadInfo::Instance)
DB2Storage< AzeriteKnowledgeMultiplierEntry > sAzeriteKnowledgeMultiplierStore("AzeriteKnowledgeMultiplier.db2", &AzeriteKnowledgeMultiplierLoadInfo::Instance)
DB2Storage< SpecializationSpellsEntry > sSpecializationSpellsStore("SpecializationSpells.db2", &SpecializationSpellsLoadInfo::Instance)
std::map< WMOAreaTableKey, WMOAreaTableEntry const * > WMOAreaTableLookupContainer
Definition: DB2Stores.cpp:433
std::unordered_map< uint32, DB2Manager::MountTypeXCapabilitySet > MountCapabilitiesByTypeContainer
Definition: DB2Stores.cpp:418
DB2Storage< GarrFollowerXAbilityEntry > sGarrFollowerXAbilityStore("GarrFollowerXAbility.db2", &GarrFollowerXAbilityLoadInfo::Instance)
DB2Storage< QuestInfoEntry > sQuestInfoStore("QuestInfo.db2", &QuestInfoLoadInfo::Instance)
DB2Storage< ItemArmorTotalEntry > sItemArmorTotalStore("ItemArmorTotal.db2", &ItemArmorTotalLoadInfo::Instance)
DB2Storage< ChrModelEntry > sChrModelStore("ChrModel.db2", &ChrModelLoadInfo::Instance)
std::unordered_map< uint32, std::vector< SpecializationSpellsEntry const * > > SpecializationSpellsContainer
Definition: DB2Stores.cpp:426
DB2Storage< TraitTreeEntry > sTraitTreeStore("TraitTree.db2", &TraitTreeLoadInfo::Instance)
DB2Storage< GarrTalentTreeEntry > sGarrTalentTreeStore("GarrTalentTree.db2", &GarrTalentTreeLoadInfo::Instance)
DB2Storage< TransportRotationEntry > sTransportRotationStore("TransportRotation.db2", &TransportRotationLoadInfo::Instance)
DB2Storage< SpellRangeEntry > sSpellRangeStore("SpellRange.db2", &SpellRangeLoadInfo::Instance)
DB2Storage< ItemLevelSelectorQualityEntry > sItemLevelSelectorQualityStore("ItemLevelSelectorQuality.db2", &ItemLevelSelectorQualityLoadInfo::Instance)
DB2Storage< RewardPackXItemEntry > sRewardPackXItemStore("RewardPackXItem.db2", &RewardPackXItemLoadInfo::Instance)
DB2Storage< EmotesTextSoundEntry > sEmotesTextSoundStore("EmotesTextSound.db2", &EmotesTextSoundLoadInfo::Instance)
std::array< PowerTypeEntry const *, MAX_POWERS > PowerTypesContainer
Definition: DB2Stores.cpp:423
bool ValidateBroadcastTextTactKeyOptionalData(std::vector< uint8 > const &data)
Definition: DB2Stores.cpp:1844
DB2Storage< ChrClassesEntry > sChrClassesStore("ChrClasses.db2", &ChrClassesLoadInfo::Instance)
DB2Storage< SpellShapeshiftFormEntry > sSpellShapeshiftFormStore("SpellShapeshiftForm.db2", &SpellShapeshiftFormLoadInfo::Instance)
DB2Storage< ItemPriceBaseEntry > sItemPriceBaseStore("ItemPriceBase.db2", &ItemPriceBaseLoadInfo::Instance)
DB2Storage< GlobalCurveEntry > sGlobalCurveStore("GlobalCurve.db2", &GlobalCurveLoadInfo::Instance)
DB2Storage< ModifierTreeEntry > sModifierTreeStore("ModifierTree.db2", &ModifierTreeLoadInfo::Instance)
std::unordered_map< uint32, std::vector< uint32 > > FactionTeamContainer
Definition: DB2Stores.cpp:407
DB2Storage< SpellAuraRestrictionsEntry > sSpellAuraRestrictionsStore("SpellAuraRestrictions.db2", &SpellAuraRestrictionsLoadInfo::Instance)
DB2Storage< MountEntry > sMountStore("Mount.db2", &MountLoadInfo::Instance)
DB2Storage< VehicleSeatEntry > sVehicleSeatStore("VehicleSeat.db2", &VehicleSeatLoadInfo::Instance)
DB2Storage< ChrCustomizationDisplayInfoEntry > sChrCustomizationDisplayInfoStore("ChrCustomizationDisplayInfo.db2", &ChrCustomizationDisplayInfoLoadInfo::Instance)
std::unordered_map< uint32, std::vector< SpellProcsPerMinuteModEntry const * > > SpellProcsPerMinuteModContainer
Definition: DB2Stores.cpp:429
DB2Storage< ArtifactPowerRankEntry > sArtifactPowerRankStore("ArtifactPowerRank.db2", &ArtifactPowerRankLoadInfo::Instance)
DB2Storage< DestructibleModelDataEntry > sDestructibleModelDataStore("DestructibleModelData.db2", &DestructibleModelDataLoadInfo::Instance)
DB2Storage< SpellShapeshiftEntry > sSpellShapeshiftStore("SpellShapeshift.db2", &SpellShapeshiftLoadInfo::Instance)
DB2Storage< GarrSiteLevelPlotInstEntry > sGarrSiteLevelPlotInstStore("GarrSiteLevelPlotInst.db2", &GarrSiteLevelPlotInstLoadInfo::Instance)
TaxiMask sOldContinentsNodesMask
Definition: DB2Stores.cpp:392
DB2Storage< MountEquipmentEntry > sMountEquipmentStore("MountEquipment.db2", &MountEquipmentLoadInfo::Instance)
DB2Storage< SpellVisualEffectNameEntry > sSpellVisualEffectNameStore("SpellVisualEffectName.db2", &SpellVisualEffectNameLoadInfo::Instance)
DB2Storage< SpellMiscEntry > sSpellMiscStore("SpellMisc.db2", &SpellMiscLoadInfo::Instance)
DB2Storage< WorldStateExpressionEntry > sWorldStateExpressionStore("WorldStateExpression.db2", &WorldStateExpressionLoadInfo::Instance)
DB2Storage< GarrPlotInstanceEntry > sGarrPlotInstanceStore("GarrPlotInstance.db2", &GarrPlotInstanceLoadInfo::Instance)
DB2Storage< LockEntry > sLockStore("Lock.db2", &LockLoadInfo::Instance)
DB2Storage< NamesProfanityEntry > sNamesProfanityStore("NamesProfanity.db2", &NamesProfanityLoadInfo::Instance)
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< GlyphRequiredSpecEntry > sGlyphRequiredSpecStore("GlyphRequiredSpec.db2", &GlyphRequiredSpecLoadInfo::Instance)
DB2Storage< ExpectedStatEntry > sExpectedStatStore("ExpectedStat.db2", &ExpectedStatLoadInfo::Instance)
DB2Storage< BattlePetSpeciesStateEntry > sBattlePetSpeciesStateStore("BattlePetSpeciesState.db2", &BattlePetSpeciesStateLoadInfo::Instance)
DB2Storage< NumTalentsAtLevelEntry > sNumTalentsAtLevelStore("NumTalentsAtLevel.db2", &NumTalentsAtLevelLoadInfo::Instance)
std::map< std::tuple< uint32, uint8, uint8, uint8 >, EmotesTextSoundEntry const * > EmotesTextSoundContainer
Definition: DB2Stores.cpp:406
DB2Storage< ArtifactUnlockEntry > sArtifactUnlockStore("ArtifactUnlock.db2", &ArtifactUnlockLoadInfo::Instance)
DB2Storage< QuestLineXQuestEntry > sQuestLineXQuestStore("QuestLineXQuest.db2", &QuestLineXQuestLoadInfo::Instance)
DB2Storage< TraitCondEntry > sTraitCondStore("TraitCond.db2", &TraitCondLoadInfo::Instance)
DB2Storage< TransportAnimationEntry > sTransportAnimationStore("TransportAnimation.db2", &TransportAnimationLoadInfo::Instance)
std::vector< TalentEntry const * > TalentsByPosition[MAX_CLASSES][MAX_TALENT_TIERS][MAX_TALENT_COLUMNS]
Definition: DB2Stores.cpp:430
DB2Storage< ContentTuningXExpectedEntry > sContentTuningXExpectedStore("ContentTuningXExpected.db2", &ContentTuningXExpectedLoadInfo::Instance)
DB2Storage< ConditionalContentTuningEntry > sConditionalContentTuningStore("ConditionalContentTuning.db2", &ConditionalContentTuningLoadInfo::Instance)
DB2Storage< WMOAreaTableEntry > sWMOAreaTableStore("WMOAreaTable.db2", &WmoAreaTableLoadInfo::Instance)
DB2Storage< TraitTreeXTraitCurrencyEntry > sTraitTreeXTraitCurrencyStore("TraitTreeXTraitCurrency.db2", &TraitTreeXTraitCurrencyLoadInfo::Instance)
DB2Storage< ItemXBonusTreeEntry > sItemXBonusTreeStore("ItemXBonusTree.db2", &ItemXBonusTreeLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< Cfg_CategoriesEntry > sCfgCategoriesStore("Cfg_Categories.db2", &CfgCategoriesLoadInfo::Instance)
DB2Storage< ExpectedStatModEntry > sExpectedStatModStore("ExpectedStatMod.db2", &ExpectedStatModLoadInfo::Instance)
DB2Storage< PrestigeLevelInfoEntry > sPrestigeLevelInfoStore("PrestigeLevelInfo.db2", &PrestigeLevelInfoLoadInfo::Instance)
DB2Storage< ChrClassesXPowerTypesEntry > sChrClassesXPowerTypesStore("ChrClassesXPowerTypes.db2", &ChrClassesXPowerTypesLoadInfo::Instance)
DB2Storage< GarrPlotBuildingEntry > sGarrPlotBuildingStore("GarrPlotBuilding.db2", &GarrPlotBuildingLoadInfo::Instance)
DB2Storage< SceneScriptTextEntry > sSceneScriptTextStore("SceneScriptText.db2", &SceneScriptTextLoadInfo::Instance)
DB2Storage< ChrCustomizationReqChoiceEntry > sChrCustomizationReqChoiceStore("ChrCustomizationReqChoice.db2", &ChrCustomizationReqChoiceLoadInfo::Instance)
DB2Storage< GossipNPCOptionEntry > sGossipNPCOptionStore("GossipNPCOption.db2", &GossipNpcOptionLoadInfo::Instance)
DB2Storage< PowerTypeEntry > sPowerTypeStore("PowerType.db2", &PowerTypeLoadInfo::Instance)
DB2Storage< ItemSetEntry > sItemSetStore("ItemSet.db2", &ItemSetLoadInfo::Instance)
DB2Storage< TraitNodeEntryEntry > sTraitNodeEntryStore("TraitNodeEntry.db2", &TraitNodeEntryLoadInfo::Instance)
DB2Storage< QuestSortEntry > sQuestSortStore("QuestSort.db2", &QuestSortLoadInfo::Instance)
DB2Storage< GarrSiteLevelEntry > sGarrSiteLevelStore("GarrSiteLevel.db2", &GarrSiteLevelLoadInfo::Instance)
DB2Storage< SceneScriptPackageEntry > sSceneScriptPackageStore("SceneScriptPackage.db2", &SceneScriptPackageLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoExtraEntry > sCreatureDisplayInfoExtraStore("CreatureDisplayInfoExtra.db2", &CreatureDisplayInfoExtraLoadInfo::Instance)
DB2Storage< TotemCategoryEntry > sTotemCategoryStore("TotemCategory.db2", &TotemCategoryLoadInfo::Instance)
DB2Storage< SpellLevelsEntry > sSpellLevelsStore("SpellLevels.db2", &SpellLevelsLoadInfo::Instance)
DB2Storage< SpellVisualKitEntry > sSpellVisualKitStore("SpellVisualKit.db2", &SpellVisualKitLoadInfo::Instance)
DB2Storage< AdventureMapPOIEntry > sAdventureMapPOIStore("AdventureMapPOI.db2", &AdventureMapPoiLoadInfo::Instance)
DB2Storage< PvpTalentEntry > sPvpTalentStore("PvpTalent.db2", &PvpTalentLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
DB2Storage< JournalTierEntry > sJournalTierStore("JournalTier.db2", &JournalTierLoadInfo::Instance)
DB2Storage< BattlePetAbilityEntry > sBattlePetAbilityStore("BattlePetAbility.db2", &BattlePetAbilityLoadInfo::Instance)
DB2Storage< SpellVisualMissileEntry > sSpellVisualMissileStore("SpellVisualMissile.db2", &SpellVisualMissileLoadInfo::Instance)
DB2Storage< ItemEffectEntry > sItemEffectStore("ItemEffect.db2", &ItemEffectLoadInfo::Instance)
std::unordered_map< uint32, std::vector< ArtifactPowerEntry const * > > ArtifactPowersContainer
Definition: DB2Stores.cpp:401
DB2Storage< PathPropertyEntry > sPathPropertyStore("PathProperty.db2", &PathPropertyLoadInfo::Instance)
DB2Storage< BarberShopStyleEntry > sBarberShopStyleStore("BarberShopStyle.db2", &BarberShopStyleLoadInfo::Instance)
std::unordered_multimap< uint32, SkillRaceClassInfoEntry const * > SkillRaceClassInfoContainer
Definition: DB2Stores.cpp:425
DB2Storage< ChatChannelsEntry > sChatChannelsStore("ChatChannels.db2", &ChatChannelsLoadInfo::Instance)
std::pair< uint32, bool(*)(std::vector< uint8 > const &data) > AllowedHotfixOptionalData
Definition: DB2Stores.cpp:436
DB2Storage< MawPowerEntry > sMawPowerStore("MawPower.db2", &MawPowerLoadInfo::Instance)
DB2Storage< ToyEntry > sToyStore("Toy.db2", &ToyLoadInfo::Instance)
DB2Storage< CriteriaTreeEntry > sCriteriaTreeStore("CriteriaTree.db2", &CriteriaTreeLoadInfo::Instance)
DB2Storage< ChrClassUIDisplayEntry > sChrClassUIDisplayStore("ChrClassUIDisplay.db2", &ChrClassUiDisplayLoadInfo::Instance)
DB2Storage< TraitDefinitionEffectPointsEntry > sTraitDefinitionEffectPointsStore("TraitDefinitionEffectPoints.db2", &TraitDefinitionEffectPointsLoadInfo::Instance)
DB2Storage< CorruptionEffectsEntry > sCorruptionEffectsStore("CorruptionEffects.db2", &CorruptionEffectsLoadInfo::Instance)
DB2Storage< ImportPriceShieldEntry > sImportPriceShieldStore("ImportPriceShield.db2", &ImportPriceShieldLoadInfo::Instance)
DB2Storage< LocationEntry > sLocationStore("Location.db2", &LocationLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< ItemArmorShieldEntry > sItemArmorShieldStore("ItemArmorShield.db2", &ItemArmorShieldLoadInfo::Instance)
DB2Storage< AreaTriggerEntry > sAreaTriggerStore("AreaTrigger.db2", &AreaTriggerLoadInfo::Instance)
DB2Storage< SpellDurationEntry > sSpellDurationStore("SpellDuration.db2", &SpellDurationLoadInfo::Instance)
DB2Storage< SpellLearnSpellEntry > sSpellLearnSpellStore("SpellLearnSpell.db2", &SpellLearnSpellLoadInfo::Instance)
DB2Storage< ConversationLineEntry > sConversationLineStore("ConversationLine.db2", &ConversationLineLoadInfo::Instance)
DB2Storage< SpellCooldownsEntry > sSpellCooldownsStore("SpellCooldowns.db2", &SpellCooldownsLoadInfo::Instance)
DB2Storage< MountTypeXCapabilityEntry > sMountTypeXCapabilityStore("MountTypeXCapability.db2", &MountTypeXCapabilityLoadInfo::Instance)
DB2Storage< AdventureJournalEntry > sAdventureJournalStore("AdventureJournal.db2", &AdventureJournalLoadInfo::Instance)
void LoadDB2(std::bitset< TOTAL_LOCALES > &availableDb2Locales, std::vector< std::string > &errlist, StorageMap &stores, DB2StorageBase *storage, std::string const &db2Path, LocaleConstant defaultLocale, std::size_t cppRecordSize)
Definition: DB2Stores.cpp:539
DB2Storage< MapDifficultyXConditionEntry > sMapDifficultyXConditionStore("MapDifficultyXCondition.db2", &MapDifficultyXConditionLoadInfo::Instance)
DB2Storage< BannedAddonsEntry > sBannedAddonsStore("BannedAddons.db2", &BannedAddonsLoadInfo::Instance)
std::tuple< uint16, uint8, int32 > WMOAreaTableKey
Definition: DB2Stores.cpp:432
DB2Storage< ItemArmorQualityEntry > sItemArmorQualityStore("ItemArmorQuality.db2", &ItemArmorQualityLoadInfo::Instance)
DB2Storage< UnitConditionEntry > sUnitConditionStore("UnitCondition.db2", &UnitConditionLoadInfo::Instance)
DB2Storage< BattlemasterListXMapEntry > sBattlemasterListXMapStore("BattlemasterListXMap.db2", &BattlemasterListXMapLoadInfo::Instance)
std::unordered_map< uint32, std::vector< uint32 > > AreaGroupMemberContainer
Definition: DB2Stores.cpp:400
DB2Storage< ItemDamageAmmoEntry > sItemDamageAmmoStore("ItemDamageAmmo.db2", &ItemDamageAmmoLoadInfo::Instance)
DB2Storage< ArtifactTierEntry > sArtifactTierStore("ArtifactTier.db2", &ArtifactTierLoadInfo::Instance)
std::unordered_map< uint32, std::vector< uint32 > > GlyphBindableSpellsContainer
Definition: DB2Stores.cpp:409
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< MailTemplateEntry > sMailTemplateStore("MailTemplate.db2", &MailTemplateLoadInfo::Instance)
DB2Storage< EmotesEntry > sEmotesStore("Emotes.db2", &EmotesLoadInfo::Instance)
std::unordered_map< uint32, std::vector< ItemSetSpellEntry const * > > ItemSetSpellContainer
Definition: DB2Stores.cpp:415
DB2Storage< ItemSetSpellEntry > sItemSetSpellStore("ItemSetSpell.db2", &ItemSetSpellLoadInfo::Instance)
DB2Storage< Cfg_RegionsEntry > sCfgRegionsStore("Cfg_Regions.db2", &CfgRegionsLoadInfo::Instance)
DB2Storage< UiMapEntry > sUiMapStore("UiMap.db2", &UiMapLoadInfo::Instance)
DB2Storage< SkillLineAbilityEntry > sSkillLineAbilityStore("SkillLineAbility.db2", &SkillLineAbilityLoadInfo::Instance)
DB2Storage< CurrencyContainerEntry > sCurrencyContainerStore("CurrencyContainer.db2", &CurrencyContainerLoadInfo::Instance)
DB2Storage< ItemDisenchantLootEntry > sItemDisenchantLootStore("ItemDisenchantLoot.db2", &ItemDisenchantLootLoadInfo::Instance)
DB2Storage< KeychainEntry > sKeychainStore("Keychain.db2", &KeychainLoadInfo::Instance)
std::unordered_map< uint32, std::pair< std::vector< QuestPackageItemEntry const * >, std::vector< QuestPackageItemEntry const * > > > QuestPackageItemContainer
Definition: DB2Stores.cpp:424
DB2Storage< TraitEdgeEntry > sTraitEdgeStore("TraitEdge.db2", &TraitEdgeLoadInfo::Instance)
DB2Storage< AzeriteUnlockMappingEntry > sAzeriteUnlockMappingStore("AzeriteUnlockMapping.db2", &AzeriteUnlockMappingLoadInfo::Instance)
DB2Storage< AzeriteTierUnlockEntry > sAzeriteTierUnlockStore("AzeriteTierUnlock.db2", &AzeriteTierUnlockLoadInfo::Instance)
DB2Storage< SummonPropertiesEntry > sSummonPropertiesStore("SummonProperties.db2", &SummonPropertiesLoadInfo::Instance)
DB2Storage< SpellReagentsCurrencyEntry > sSpellReagentsCurrencyStore("SpellReagentsCurrency.db2", &SpellReagentsCurrencyLoadInfo::Instance)
DB2Storage< GuildPerkSpellsEntry > sGuildPerkSpellsStore("GuildPerkSpells.db2", &GuildPerkSpellsLoadInfo::Instance)
DB2Storage< TraitDefinitionEntry > sTraitDefinitionStore("TraitDefinition.db2", &TraitDefinitionLoadInfo::Instance)
DB2Storage< AzeriteLevelInfoEntry > sAzeriteLevelInfoStore("AzeriteLevelInfo.db2", &AzeriteLevelInfoLoadInfo::Instance)
DB2Storage< LFGDungeonsEntry > sLFGDungeonsStore("LFGDungeons.db2", &LfgDungeonsLoadInfo::Instance)
DB2Storage< TaxiPathNodeEntry > sTaxiPathNodeStore("TaxiPathNode.db2", &TaxiPathNodeLoadInfo::Instance)
DB2Storage< SpellFocusObjectEntry > sSpellFocusObjectStore("SpellFocusObject.db2", &SpellFocusObjectLoadInfo::Instance)
DB2Storage< TactKeyEntry > sTactKeyStore("TactKey.db2", &TactKeyLoadInfo::Instance)
DB2Storage< NamesReservedLocaleEntry > sNamesReservedLocaleStore("NamesReservedLocale.db2", &NamesReservedLocaleLoadInfo::Instance)
DB2Storage< ImportPriceQualityEntry > sImportPriceQualityStore("ImportPriceQuality.db2", &ImportPriceQualityLoadInfo::Instance)
DB2Storage< PvpTierEntry > sPvpTierStore("PvpTier.db2", &PvpTierLoadInfo::Instance)
DB2Storage< ItemContextPickerEntryEntry > sItemContextPickerEntryStore("ItemContextPickerEntry.db2", &ItemContextPickerEntryLoadInfo::Instance)
DB2Storage< MountXDisplayEntry > sMountXDisplayStore("MountXDisplay.db2", &MountXDisplayLoadInfo::Instance)
DB2Storage< NameGenEntry > sNameGenStore("NameGen.db2", &NameGenLoadInfo::Instance)
DB2Storage< BroadcastTextEntry > sBroadcastTextStore("BroadcastText.db2", &BroadcastTextLoadInfo::Instance)
DB2Storage< SpellCastingRequirementsEntry > sSpellCastingRequirementsStore("SpellCastingRequirements.db2", &SpellCastingRequirementsLoadInfo::Instance)
std::unordered_map< uint32, std::vector< ItemLimitCategoryConditionEntry const * > > ItemLimitCategoryConditionContainer
Definition: DB2Stores.cpp:413
DB2Storage< SpellEmpowerEntry > sSpellEmpowerStore("SpellEmpower.db2", &SpellEmpowerLoadInfo::Instance)
DB2Storage< MythicPlusSeasonEntry > sMythicPlusSeasonStore("MythicPlusSeason.db2", &MythicPlusSeasonLoadInfo::Instance)
DB2Storage< GameObjectArtKitEntry > sGameObjectArtKitStore("GameObjectArtKit.db2", &GameobjectArtKitLoadInfo::Instance)
DB2Storage< ItemLimitCategoryConditionEntry > sItemLimitCategoryConditionStore("ItemLimitCategoryCondition.db2", &ItemLimitCategoryConditionLoadInfo::Instance)
DB2Storage< ItemExtendedCostEntry > sItemExtendedCostStore("ItemExtendedCost.db2", &ItemExtendedCostLoadInfo::Instance)
DB2Storage< SpellEffectEntry > sSpellEffectStore("SpellEffect.db2", &SpellEffectLoadInfo::Instance)
DB2Storage< ContentTuningXLabelEntry > sContentTuningXLabelStore("ContentTuningXLabel.db2", &ContentTuningXLabelLoadInfo::Instance)
std::array< std::vector< Trinity::wregex >, TOTAL_LOCALES+1 > NameValidationRegexContainer
Definition: DB2Stores.cpp:421
DB2Storage< GuildColorBackgroundEntry > sGuildColorBackgroundStore("GuildColorBackground.db2", &GuildColorBackgroundLoadInfo::Instance)
DB2Storage< PVPDifficultyEntry > sPVPDifficultyStore("PVPDifficulty.db2", &PvpDifficultyLoadInfo::Instance)
std::map< HotfixBlobKey, std::vector< uint8 > > HotfixBlobMap
Definition: DB2Stores.cpp:435
DB2Storage< TraitNodeEntryXTraitCondEntry > sTraitNodeEntryXTraitCondStore("TraitNodeEntryXTraitCond.db2", &TraitNodeEntryXTraitCondLoadInfo::Instance)
DB2Storage< QuestV2Entry > sQuestV2Store("QuestV2.db2", &QuestV2LoadInfo::Instance)
DB2Storage< AzeriteEmpoweredItemEntry > sAzeriteEmpoweredItemStore("AzeriteEmpoweredItem.db2", &AzeriteEmpoweredItemLoadInfo::Instance)
DB2Storage< VignetteEntry > sVignetteStore("Vignette.db2", &VignetteLoadInfo::Instance)
DB2Storage< CurrencyTypesEntry > sCurrencyTypesStore("CurrencyTypes.db2", &CurrencyTypesLoadInfo::Instance)
DB2Storage< LanguagesEntry > sLanguagesStore("Languages.db2", &LanguagesLoadInfo::Instance)
DB2Storage< MapChallengeModeEntry > sMapChallengeModeStore("MapChallengeMode.db2", &MapChallengeModeLoadInfo::Instance)