/* * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "DBCStores.h" #include "BattlegroundMgr.h" #include "DBCFileLoader.h" #include "DBCfmt.h" #include "Errors.h" #include "LFGMgr.h" #include "Log.h" #include "SharedDefines.h" #include "SpellMgr.h" #include "TransportMgr.h" #include "World.h" #include typedef std::map AreaFlagByAreaID; typedef std::map AreaFlagByMapID; typedef std::tuple WMOAreaTableKey; typedef std::map WMOAreaInfoByTripple; DBCStorage sAreaTableStore(AreaTableEntryfmt); DBCStorage sAreaGroupStore(AreaGroupEntryfmt); DBCStorage sAreaPOIStore(AreaPOIEntryfmt); static WMOAreaInfoByTripple sWMOAreaInfoByTripple; DBCStorage sAchievementStore(Achievementfmt); DBCStorage sAchievementCategoryStore(AchievementCategoryfmt); DBCStorage sAchievementCriteriaStore(AchievementCriteriafmt); DBCStorage sAuctionHouseStore(AuctionHouseEntryfmt); DBCStorage sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); DBCStorage sBattlemasterListStore(BattlemasterListEntryfmt); DBCStorage sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage sCharStartOutfitStore(CharStartOutfitEntryfmt); std::map sCharStartOutfitMap; DBCStorage sCharTitlesStore(CharTitlesEntryfmt); DBCStorage sChatChannelsStore(ChatChannelsEntryfmt); DBCStorage sChrClassesStore(ChrClassesEntryfmt); DBCStorage sChrRacesStore(ChrRacesEntryfmt); DBCStorage sCinematicCameraStore(CinematicCameraEntryfmt); DBCStorage sCinematicSequencesStore(CinematicSequencesEntryfmt); DBCStorage sCreatureDisplayInfoStore(CreatureDisplayInfofmt); DBCStorage sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt); DBCStorage sCreatureFamilyStore(CreatureFamilyfmt); DBCStorage sCreatureModelDataStore(CreatureModelDatafmt); DBCStorage sCreatureSpellDataStore(CreatureSpellDatafmt); DBCStorage sCreatureTypeStore(CreatureTypefmt); DBCStorage sCurrencyTypesStore(CurrencyTypesfmt); DBCStorage sDestructibleModelDataStore(DestructibleModelDatafmt); DBCStorage sDungeonEncounterStore(DungeonEncounterfmt); DBCStorage sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage sDurabilityCostsStore(DurabilityCostsfmt); DBCStorage sEmotesStore(EmotesEntryfmt); DBCStorage sEmotesTextStore(EmotesTextEntryfmt); typedef std::map FactionTeamMap; static FactionTeamMap sFactionTeamMap; DBCStorage sFactionStore(FactionEntryfmt); DBCStorage sFactionTemplateStore(FactionTemplateEntryfmt); DBCStorage sGameObjectArtKitStore(GameObjectArtKitfmt); DBCStorage sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt); DBCStorage sGemPropertiesStore(GemPropertiesEntryfmt); DBCStorage sGlyphPropertiesStore(GlyphPropertiesfmt); DBCStorage sGlyphSlotStore(GlyphSlotfmt); DBCStorage sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt); DBCStorage sGtCombatRatingsStore(GtCombatRatingsfmt); DBCStorage sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt); DBCStorage sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); DBCStorage sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt); DBCStorage sGtChanceToSpellCritStore(GtChanceToSpellCritfmt); DBCStorage sGtNPCManaCostScalerStore(GtNPCManaCostScalerfmt); DBCStorage sGtOCTClassCombatRatingScalarStore(GtOCTClassCombatRatingScalarfmt); DBCStorage sGtOCTRegenHPStore(GtOCTRegenHPfmt); //DBCStorage sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently DBCStorage sGtRegenHPPerSptStore(GtRegenHPPerSptfmt); DBCStorage sGtRegenMPPerSptStore(GtRegenMPPerSptfmt); DBCStorage sHolidaysStore(Holidaysfmt); DBCStorage sItemStore(Itemfmt); DBCStorage sItemBagFamilyStore(ItemBagFamilyfmt); //DBCStorage sItemCondExtCostsStore(ItemCondExtCostsEntryfmt); DBCStorage sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); DBCStorage sItemExtendedCostStore(ItemExtendedCostEntryfmt); DBCStorage sItemLimitCategoryStore(ItemLimitCategoryEntryfmt); DBCStorage sItemRandomPropertiesStore(ItemRandomPropertiesfmt); DBCStorage sItemRandomSuffixStore(ItemRandomSuffixfmt); DBCStorage sItemSetStore(ItemSetEntryfmt); DBCStorage sLFGDungeonStore(LFGDungeonEntryfmt); DBCStorage sLightStore(LightEntryfmt); DBCStorage sLiquidTypeStore(LiquidTypefmt); DBCStorage sLockStore(LockEntryfmt); DBCStorage sMailTemplateStore(MailTemplateEntryfmt); DBCStorage sMapStore(MapEntryfmt); // DBC used only for initialization sMapDifficultyMap at startup. DBCStorage sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading MapDifficultyMap sMapDifficultyMap; DBCStorage sMovieStore(MovieEntryfmt); DBCStorage sNamesReservedStore(NamesReservedfmt); DBCStorage sNamesProfanityStore(NamesProfanityfmt); DBCStorage sOverrideSpellDataStore(OverrideSpellDatafmt); DBCStorage sPowerDisplayStore(PowerDisplayfmt); DBCStorage sPvPDifficultyStore(PvPDifficultyfmt); DBCStorage sQuestSortStore(QuestSortEntryfmt); DBCStorage sQuestXPStore(QuestXPfmt); DBCStorage sQuestFactionRewardStore(QuestFactionRewardfmt); DBCStorage sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); DBCStorage sScalingStatDistributionStore(ScalingStatDistributionfmt); DBCStorage sScalingStatValuesStore(ScalingStatValuesfmt); DBCStorage sSkillLineStore(SkillLinefmt); DBCStorage sSkillLineAbilityStore(SkillLineAbilityfmt); SkillLineAbilityIndexBySkillLine sSkillLineAbilityIndexBySkillLine; DBCStorage sSkillRaceClassInfoStore(SkillRaceClassInfofmt); SkillRaceClassInfoMap SkillRaceClassInfoBySkill; DBCStorage sSkillTiersStore(SkillTiersfmt); DBCStorage sSoundEntriesStore(SoundEntriesfmt); DBCStorage sSpellItemEnchantmentStore(SpellItemEnchantmentfmt); DBCStorage sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt); DBCStorage sSpellStore(SpellEntryfmt); SpellCategoryStore sSpellsByCategoryStore; PetFamilySpellsStore sPetFamilySpellsStore; DBCStorage sSpellCastTimesStore(SpellCastTimefmt); DBCStorage sSpellCategoryStore(SpellCategoryfmt); DBCStorage sSpellDifficultyStore(SpellDifficultyfmt); DBCStorage sSpellDurationStore(SpellDurationfmt); DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage sSpellRadiusStore(SpellRadiusfmt); DBCStorage sSpellRangeStore(SpellRangefmt); DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage sSpellShapeshiftFormStore(SpellShapeshiftFormEntryfmt); DBCStorage sSpellVisualStore(SpellVisualfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; std::unordered_set sPetTalentSpells; DBCStorage sTalentTabStore(TalentTabEntryfmt); // store absolute bit position for first rank for talent inspect static uint32 sTalentTabPages[MAX_CLASSES][3]; DBCStorage sTaxiNodesStore(TaxiNodesEntryfmt); TaxiMask sTaxiNodesMask; TaxiMask sOldContinentsNodesMask; TaxiMask sHordeTaxiNodesMask; TaxiMask sAllianceTaxiNodesMask; TaxiMask sDeathKnightTaxiNodesMask; // DBC used only for initialization sTaxiPathSetBySource at startup. TaxiPathSetBySource sTaxiPathSetBySource; DBCStorage sTaxiPathStore(TaxiPathEntryfmt); // DBC used only for initialization sTaxiPathNodeStore at startup. TaxiPathNodesByPath sTaxiPathNodesByPath; static DBCStorage sTaxiPathNodeStore(TaxiPathNodeEntryfmt); DBCStorage sTeamContributionPointsStore(TeamContributionPointsfmt); DBCStorage sTotemCategoryStore(TotemCategoryEntryfmt); DBCStorage sTransportAnimationStore(TransportAnimationfmt); DBCStorage sTransportRotationStore(TransportRotationfmt); DBCStorage sVehicleStore(VehicleEntryfmt); DBCStorage sVehicleSeatStore(VehicleSeatEntryfmt); DBCStorage sWMOAreaTableStore(WMOAreaTableEntryfmt); DBCStorage sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage sWorldMapOverlayStore(WorldMapOverlayEntryfmt); typedef std::list StoreProblemList; uint32 DBCFileCount = 0; static bool LoadDBC_assert_print(uint32 fsize, uint32 rsize, const std::string& filename) { LOG_ERROR("dbc", "Size of '{}' set by format string ({}) not equal size of C++ structure ({}).", filename, fsize, rsize); // ASSERT must fail after function call return false; } template inline void LoadDBC(uint32& availableDbcLocales, StoreProblemList& errors, DBCStorage& storage, std::string const& dbcPath, std::string const& filename, char const* dbTable = nullptr) { // compatibility format and C++ structure sizes ASSERT(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()), sizeof(T), filename)); ++DBCFileCount; std::string dbcFilename = dbcPath + filename; bool existDBData = false; if (storage.Load(dbcFilename.c_str())) { for (uint8 i = 0; i < TOTAL_LOCALES; ++i) { if (!(availableDbcLocales & (1 << i))) continue; std::string localizedName(dbcPath); localizedName.append(localeNames[i]); localizedName.push_back('/'); localizedName.append(filename); if (!storage.LoadStringsFrom(localizedName.c_str())) availableDbcLocales &= ~(1 << i); // mark as not available for speedup next checks } } if (dbTable) storage.LoadFromDB(dbTable, storage.GetFormat()); if (storage.GetNumRows()) existDBData = true; if (!existDBData) { // sort problematic dbc to (1) non compatible and (2) non-existed if (FILE* f = fopen(dbcFilename.c_str(), "rb")) { std::ostringstream stream; stream << dbcFilename << " exists, and has " << storage.GetFieldCount() << " field(s) (expected " << strlen(storage.GetFormat()) << "). Extracted file might be from wrong client version or a database-update has been forgotten."; std::string buf = stream.str(); errors.push_back(buf); fclose(f); } else errors.push_back(dbcFilename); } } void LoadDBCStores(const std::string& dataPath) { uint32 oldMSTime = getMSTime(); std::string dbcPath = dataPath + "dbc/"; StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; #define LOAD_DBC(store, file, dbtable) LoadDBC(availableDbcLocales, bad_dbc_files, store, dbcPath, file, dbtable) LOAD_DBC(sAreaTableStore, "AreaTable.dbc", "areatable_dbc"); LOAD_DBC(sAchievementStore, "Achievement.dbc", "achievement_dbc"); LOAD_DBC(sAchievementCategoryStore, "Achievement_Category.dbc", "achievement_category_dbc"); LOAD_DBC(sAchievementCriteriaStore, "Achievement_Criteria.dbc", "achievement_criteria_dbc"); LOAD_DBC(sAreaGroupStore, "AreaGroup.dbc", "areagroup_dbc"); LOAD_DBC(sAreaPOIStore, "AreaPOI.dbc", "areapoi_dbc"); LOAD_DBC(sAuctionHouseStore, "AuctionHouse.dbc", "auctionhouse_dbc"); LOAD_DBC(sBankBagSlotPricesStore, "BankBagSlotPrices.dbc", "bankbagslotprices_dbc"); LOAD_DBC(sBattlemasterListStore, "BattlemasterList.dbc", "battlemasterlist_dbc"); LOAD_DBC(sBarberShopStyleStore, "BarberShopStyle.dbc", "barbershopstyle_dbc"); LOAD_DBC(sCharStartOutfitStore, "CharStartOutfit.dbc", "charstartoutfit_dbc"); LOAD_DBC(sCharTitlesStore, "CharTitles.dbc", "chartitles_dbc"); LOAD_DBC(sChatChannelsStore, "ChatChannels.dbc", "chatchannels_dbc"); LOAD_DBC(sChrClassesStore, "ChrClasses.dbc", "chrclasses_dbc"); LOAD_DBC(sChrRacesStore, "ChrRaces.dbc", "chrraces_dbc"); LOAD_DBC(sCinematicCameraStore, "CinematicCamera.dbc", "cinematiccamera_dbc"); LOAD_DBC(sCinematicSequencesStore, "CinematicSequences.dbc", "cinematicsequences_dbc"); LOAD_DBC(sCreatureDisplayInfoStore, "CreatureDisplayInfo.dbc", "creaturedisplayinfo_dbc"); LOAD_DBC(sCreatureDisplayInfoExtraStore, "CreatureDisplayInfoExtra.dbc", "creaturedisplayinfoextra_dbc"); LOAD_DBC(sCreatureFamilyStore, "CreatureFamily.dbc", "creaturefamily_dbc"); LOAD_DBC(sCreatureModelDataStore, "CreatureModelData.dbc", "creaturemodeldata_dbc"); LOAD_DBC(sCreatureSpellDataStore, "CreatureSpellData.dbc", "creaturespelldata_dbc"); LOAD_DBC(sCreatureTypeStore, "CreatureType.dbc", "creaturetype_dbc"); LOAD_DBC(sCurrencyTypesStore, "CurrencyTypes.dbc", "currencytypes_dbc"); LOAD_DBC(sDestructibleModelDataStore, "DestructibleModelData.dbc", "destructiblemodeldata_dbc"); LOAD_DBC(sDungeonEncounterStore, "DungeonEncounter.dbc", "dungeonencounter_dbc"); LOAD_DBC(sDurabilityCostsStore, "DurabilityCosts.dbc", "durabilitycosts_dbc"); LOAD_DBC(sDurabilityQualityStore, "DurabilityQuality.dbc", "durabilityquality_dbc"); LOAD_DBC(sEmotesStore, "Emotes.dbc", "emotes_dbc"); LOAD_DBC(sEmotesTextStore, "EmotesText.dbc", "emotestext_dbc"); LOAD_DBC(sFactionStore, "Faction.dbc", "faction_dbc"); LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc", "factiontemplate_dbc"); LOAD_DBC(sGameObjectArtKitStore, "GameObjectArtKit.dbc", "gameobjectartkit_dbc"); LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc", "gameobjectdisplayinfo_dbc"); LOAD_DBC(sGemPropertiesStore, "GemProperties.dbc", "gemproperties_dbc"); LOAD_DBC(sGlyphPropertiesStore, "GlyphProperties.dbc", "glyphproperties_dbc"); LOAD_DBC(sGlyphSlotStore, "GlyphSlot.dbc", "glyphslot_dbc"); LOAD_DBC(sGtBarberShopCostBaseStore, "gtBarberShopCostBase.dbc", "gtbarbershopcostbase_dbc"); LOAD_DBC(sGtCombatRatingsStore, "gtCombatRatings.dbc", "gtcombatratings_dbc"); LOAD_DBC(sGtChanceToMeleeCritBaseStore, "gtChanceToMeleeCritBase.dbc", "gtchancetomeleecritbase_dbc"); LOAD_DBC(sGtChanceToMeleeCritStore, "gtChanceToMeleeCrit.dbc", "gtchancetomeleecrit_dbc"); LOAD_DBC(sGtChanceToSpellCritBaseStore, "gtChanceToSpellCritBase.dbc", "gtchancetospellcritbase_dbc"); LOAD_DBC(sGtChanceToSpellCritStore, "gtChanceToSpellCrit.dbc", "gtchancetospellcrit_dbc"); LOAD_DBC(sGtNPCManaCostScalerStore, "gtNPCManaCostScaler.dbc", "gtnpcmanacostscaler_dbc"); LOAD_DBC(sGtOCTClassCombatRatingScalarStore, "gtOCTClassCombatRatingScalar.dbc", "gtoctclasscombatratingscalar_dbc"); LOAD_DBC(sGtOCTRegenHPStore, "gtOCTRegenHP.dbc", "gtoctregenhp_dbc"); //LOAD_DBC(sGtOCTRegenMPStore, "gtOCTRegenMP.dbc", "gtoctregenmp_dbc"); -- not used currently LOAD_DBC(sGtRegenHPPerSptStore, "gtRegenHPPerSpt.dbc", "gtregenhpperspt_dbc"); LOAD_DBC(sGtRegenMPPerSptStore, "gtRegenMPPerSpt.dbc", "gtregenmpperspt_dbc"); LOAD_DBC(sHolidaysStore, "Holidays.dbc", "holidays_dbc"); LOAD_DBC(sItemStore, "Item.dbc", "item_dbc"); LOAD_DBC(sItemBagFamilyStore, "ItemBagFamily.dbc", "itembagfamily_dbc"); LOAD_DBC(sItemDisplayInfoStore, "ItemDisplayInfo.dbc", "itemdisplayinfo_dbc"); //LOAD_DBC(sItemCondExtCostsStore, "ItemCondExtCosts.dbc", "itemcondextcosts_dbc"); LOAD_DBC(sItemExtendedCostStore, "ItemExtendedCost.dbc", "itemextendedcost_dbc"); LOAD_DBC(sItemLimitCategoryStore, "ItemLimitCategory.dbc", "itemlimitcategory_dbc"); LOAD_DBC(sItemRandomPropertiesStore, "ItemRandomProperties.dbc", "itemrandomproperties_dbc"); LOAD_DBC(sItemRandomSuffixStore, "ItemRandomSuffix.dbc", "itemrandomsuffix_dbc"); LOAD_DBC(sItemSetStore, "ItemSet.dbc", "itemset_dbc"); LOAD_DBC(sLFGDungeonStore, "LFGDungeons.dbc", "lfgdungeons_dbc"); LOAD_DBC(sLightStore, "Light.dbc", "light_dbc"); LOAD_DBC(sLiquidTypeStore, "LiquidType.dbc", "liquidtype_dbc"); LOAD_DBC(sLockStore, "Lock.dbc", "lock_dbc"); LOAD_DBC(sMailTemplateStore, "MailTemplate.dbc", "mailtemplate_dbc"); LOAD_DBC(sMapStore, "Map.dbc", "map_dbc"); LOAD_DBC(sMapDifficultyStore, "MapDifficulty.dbc", "mapdifficulty_dbc"); LOAD_DBC(sMovieStore, "Movie.dbc", "movie_dbc"); LOAD_DBC(sNamesReservedStore, "NamesReserved.dbc", "namesreserved_dbc"); LOAD_DBC(sNamesProfanityStore, "NamesProfanity.dbc", "namesprofanity_dbc"); LOAD_DBC(sOverrideSpellDataStore, "OverrideSpellData.dbc", "overridespelldata_dbc"); LOAD_DBC(sPowerDisplayStore, "PowerDisplay.dbc", "powerdisplay_dbc"); LOAD_DBC(sPvPDifficultyStore, "PvpDifficulty.dbc", "pvpdifficulty_dbc"); LOAD_DBC(sQuestXPStore, "QuestXP.dbc", "questxp_dbc"); LOAD_DBC(sQuestFactionRewardStore, "QuestFactionReward.dbc", "questfactionreward_dbc"); LOAD_DBC(sQuestSortStore, "QuestSort.dbc", "questsort_dbc"); LOAD_DBC(sRandomPropertiesPointsStore, "RandPropPoints.dbc", "randproppoints_dbc"); LOAD_DBC(sScalingStatDistributionStore, "ScalingStatDistribution.dbc", "scalingstatdistribution_dbc"); LOAD_DBC(sScalingStatValuesStore, "ScalingStatValues.dbc", "scalingstatvalues_dbc"); LOAD_DBC(sSkillLineStore, "SkillLine.dbc", "skillline_dbc"); LOAD_DBC(sSkillLineAbilityStore, "SkillLineAbility.dbc", "skilllineability_dbc"); LOAD_DBC(sSkillRaceClassInfoStore, "SkillRaceClassInfo.dbc", "skillraceclassinfo_dbc"); LOAD_DBC(sSkillTiersStore, "SkillTiers.dbc", "skilltiers_dbc"); LOAD_DBC(sSoundEntriesStore, "SoundEntries.dbc", "soundentries_dbc"); LOAD_DBC(sSpellStore, "Spell.dbc", "spell_dbc"); LOAD_DBC(sSpellCastTimesStore, "SpellCastTimes.dbc", "spellcasttimes_dbc"); LOAD_DBC(sSpellCategoryStore, "SpellCategory.dbc", "spellcategory_dbc"); LOAD_DBC(sSpellDifficultyStore, "SpellDifficulty.dbc", "spelldifficulty_dbc"); LOAD_DBC(sSpellDurationStore, "SpellDuration.dbc", "spellduration_dbc"); LOAD_DBC(sSpellFocusObjectStore, "SpellFocusObject.dbc", "spellfocusobject_dbc"); LOAD_DBC(sSpellItemEnchantmentStore, "SpellItemEnchantment.dbc", "spellitemenchantment_dbc"); LOAD_DBC(sSpellItemEnchantmentConditionStore, "SpellItemEnchantmentCondition.dbc", "spellitemenchantmentcondition_dbc"); LOAD_DBC(sSpellRadiusStore, "SpellRadius.dbc", "spellradius_dbc"); LOAD_DBC(sSpellRangeStore, "SpellRange.dbc", "spellrange_dbc"); LOAD_DBC(sSpellRuneCostStore, "SpellRuneCost.dbc", "spellrunecost_dbc"); LOAD_DBC(sSpellShapeshiftFormStore, "SpellShapeshiftForm.dbc", "spellshapeshiftform_dbc"); LOAD_DBC(sSpellVisualStore, "SpellVisual.dbc", "spellvisual_dbc"); LOAD_DBC(sStableSlotPricesStore, "StableSlotPrices.dbc", "stableslotprices_dbc"); LOAD_DBC(sSummonPropertiesStore, "SummonProperties.dbc", "summonproperties_dbc"); LOAD_DBC(sTalentStore, "Talent.dbc", "talent_dbc"); LOAD_DBC(sTalentTabStore, "TalentTab.dbc", "talenttab_dbc"); LOAD_DBC(sTaxiNodesStore, "TaxiNodes.dbc", "taxinodes_dbc"); LOAD_DBC(sTaxiPathStore, "TaxiPath.dbc", "taxipath_dbc"); LOAD_DBC(sTaxiPathNodeStore, "TaxiPathNode.dbc", "taxipathnode_dbc"); LOAD_DBC(sTeamContributionPointsStore, "TeamContributionPoints.dbc", "teamcontributionpoints_dbc"); LOAD_DBC(sTotemCategoryStore, "TotemCategory.dbc", "totemcategory_dbc"); LOAD_DBC(sTransportAnimationStore, "TransportAnimation.dbc", "transportanimation_dbc"); LOAD_DBC(sTransportRotationStore, "TransportRotation.dbc", "transportrotation_dbc"); LOAD_DBC(sVehicleStore, "Vehicle.dbc", "vehicle_dbc"); LOAD_DBC(sVehicleSeatStore, "VehicleSeat.dbc", "vehicleseat_dbc"); LOAD_DBC(sWMOAreaTableStore, "WMOAreaTable.dbc", "wmoareatable_dbc"); LOAD_DBC(sWorldMapAreaStore, "WorldMapArea.dbc", "worldmaparea_dbc"); LOAD_DBC(sWorldMapOverlayStore, "WorldMapOverlay.dbc", "worldmapoverlay_dbc"); #undef LOAD_DBC for (CharStartOutfitEntry const* outfit : sCharStartOutfitStore) sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit; for (FactionEntry const* faction : sFactionStore) { if (faction->team) { SimpleFactionsList& flist = sFactionTeamMap[faction->team]; flist.push_back(faction->ID); } } for (GameObjectDisplayInfoEntry const* info : sGameObjectDisplayInfoStore) { if (info->maxX < info->minX) std::swap(*(float*)(&info->maxX), *(float*)(&info->minX)); if (info->maxY < info->minY) std::swap(*(float*)(&info->maxY), *(float*)(&info->minY)); if (info->maxZ < info->minZ) std::swap(*(float*)(&info->maxZ), *(float*)(&info->minZ)); } // fill data for (MapDifficultyEntry const* entry : sMapDifficultyStore) sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0'); for (PvPDifficultyEntry const* entry : sPvPDifficultyStore) if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); for (auto i : sSpellStore) if (i->Category) sSpellsByCategoryStore[i->Category].emplace(false, i->Id); for (SkillRaceClassInfoEntry const* entry : sSkillRaceClassInfoStore) { if (sSkillLineStore.LookupEntry(entry->SkillID)) { SkillRaceClassInfoBySkill.emplace(entry->SkillID, entry); } } for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore) { SpellEntry const* spellEntry = sSpellStore.LookupEntry(skillLine->Spell); if (spellEntry && spellEntry->Attributes & SPELL_ATTR0_PASSIVE) { for (CreatureFamilyEntry const* cFamily : sCreatureFamilyStore) { if (skillLine->SkillLine != cFamily->skillLine[0] && skillLine->SkillLine != cFamily->skillLine[1]) { continue; } if (spellEntry->SpellLevel) { continue; } if (skillLine->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) { continue; } sPetFamilySpellsStore[cFamily->ID].insert(spellEntry->Id); } } } for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore) sSkillLineAbilityIndexBySkillLine[skillLine->SkillLine].push_back(skillLine); // Create Spelldifficulty searcher for (SpellDifficultyEntry const* spellDiff : sSpellDifficultyStore) { SpellDifficultyEntry newEntry; memset(newEntry.SpellID, 0, 4 * sizeof(uint32)); for (uint8 x = 0; x < MAX_DIFFICULTY; ++x) { if (spellDiff->SpellID[x] <= 0 || !sSpellStore.LookupEntry(spellDiff->SpellID[x])) { if (spellDiff->SpellID[x] > 0) //don't show error if spell is <= 0, not all modes have spells and there are unknown negative values LOG_ERROR("sql.sql", "spelldifficulty_dbc: spell {} at field id: {} at spellid {} does not exist in SpellStore (spell.dbc), loaded as 0", spellDiff->SpellID[x], spellDiff->ID, x); newEntry.SpellID[x] = 0; // spell was <= 0 or invalid, set to 0 } else newEntry.SpellID[x] = spellDiff->SpellID[x]; } if (newEntry.SpellID[0] <= 0 || newEntry.SpellID[1] <= 0) // id0-1 must be always set! continue; for (uint8 x = 0; x < MAX_DIFFICULTY; ++x) if (newEntry.SpellID[x]) sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); } // create talent spells set for (TalentEntry const* talentInfo : sTalentStore) { TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(talentInfo->TalentTab); for (uint8 j = 0; j < MAX_TALENT_RANK; ++j) { if (talentInfo->RankID[j]) { sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(talentInfo->TalentID, j); if (talentTab && talentTab->petTalentMask) { sPetTalentSpells.insert(talentInfo->RankID[j]); } } } } // prepare fast data access to bit pos of talent ranks for use at inspecting { // now have all max ranks (and then bit amount used for store talent ranks in inspect) for (uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId) { TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabId); if (!talentTabInfo) continue; // prevent memory corruption; otherwise cls will become 12 below if ((talentTabInfo->ClassMask & CLASSMASK_ALL_PLAYABLE) == 0) continue; // store class talent tab pages for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) if (talentTabInfo->ClassMask & (1 << (cls - 1))) sTalentTabPages[cls][talentTabInfo->tabpage] = talentTabId; } } for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) sTaxiPathSetBySource[entry->from][entry->to] = entry; // Calculate path nodes count uint32 pathCount = sTaxiPathStore.GetNumRows(); std::vector pathLength; pathLength.resize(pathCount); // 0 and some other indexes not used for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) if (pathLength[entry->path] < entry->index + 1) pathLength[entry->path] = entry->index + 1; // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for (uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); // fill data for (TaxiPathNodeEntry const* entry : sTaxiPathNodeStore) sTaxiPathNodesByPath[entry->path][entry->index] = entry; // Initialize global taxinodes mask // include existed nodes that have at least single not spell base (scripted) path { std::set spellPaths; for (SpellEntry const* sInfo : sSpellStore) for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue[j]); sTaxiNodesMask.fill(0); sOldContinentsNodesMask.fill(0); sHordeTaxiNodesMask.fill(0); sAllianceTaxiNodesMask.fill(0); sDeathKnightTaxiNodesMask.fill(0); for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); if (!node) continue; TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i); if (src_i != sTaxiPathSetBySource.end() && !src_i->second.empty()) { bool ok = false; for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i) { // not spell path if (dest_i->second->price || spellPaths.find(dest_i->second->ID) == spellPaths.end()) { ok = true; break; } } if (!ok) continue; } // valid taxi network node uint8 field = (uint8)((i - 1) / 32); uint32 submask = 1 << ((i - 1) % 32); sTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981) sHordeTaxiNodesMask[field] |= submask; if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981) sAllianceTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981) sDeathKnightTaxiNodesMask[field] |= submask; // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info) if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94) sOldContinentsNodesMask[field] |= submask; // fix DK node at Ebon Hold and Shadow Vault flight master if (i == 315 || i == 333) ((TaxiNodesEntry*)node)->MountCreatureID[1] = 32981; } } for (TransportAnimationEntry const* anim : sTransportAnimationStore) sTransportMgr->AddPathNodeToTransport(anim->TransportEntry, anim->TimeSeg, anim); for (TransportRotationEntry const* rot : sTransportRotationStore) sTransportMgr->AddPathRotationToTransport(rot->TransportEntry, rot->TimeSeg, rot); for (WMOAreaTableEntry const* entry : sWMOAreaTableStore) sWMOAreaInfoByTripple[WMOAreaTableKey(entry->rootId, entry->adtId, entry->groupId)] = entry; // error checks if (bad_dbc_files.size() >= DBCFileCount) { LOG_ERROR("dbc", "Incorrect DataDir value in worldserver.conf or ALL required *.dbc files ({}) not found by path: {}dbc", DBCFileCount, dataPath); exit(1); } else if (!bad_dbc_files.empty()) { std::string str; for (StoreProblemList::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) str += *i + "\n"; LOG_ERROR("dbc", "Some required *.dbc files ({} from {}) not found or not compatible:\n{}", (uint32)bad_dbc_files.size(), DBCFileCount, str); exit(1); } // Check loaded DBC files proper version if (!sAreaTableStore.LookupEntry(4987) || // last area added in 3.3.5a !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a !sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a !sItemStore.LookupEntry(56806) || // last client known item added in 3.3.5a !sItemExtendedCostStore.LookupEntry(2997) || // last item extended cost added in 3.3.5a !sMapStore.LookupEntry(724) || // last map added in 3.3.5a !sSpellStore.LookupEntry(80864) ) // last client known item added in 3.3.5a { LOG_ERROR("dbc", "You have _outdated_ DBC data. Please extract correct versions from current using client."); exit(1); } LOG_INFO("server.loading", ">> Initialized {} Data Stores in {} ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } SimpleFactionsList const* GetFactionTeamList(uint32 faction) { FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction); if (itr != sFactionTeamMap.end()) return &itr->second; return nullptr; } char const* GetPetName(uint32 petfamily, uint32 dbclang) { if (!petfamily) return nullptr; CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(petfamily); if (!pet_family) return nullptr; return pet_family->Name[dbclang]; } TalentSpellPos const* GetTalentSpellPos(uint32 spellId) { TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId); if (itr == sTalentSpellPosMap.end()) return nullptr; return &itr->second; } uint32 GetTalentSpellCost(uint32 spellId) { if (TalentSpellPos const* pos = GetTalentSpellPos(spellId)) return pos->rank + 1; return 0; } WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid) { auto i = sWMOAreaInfoByTripple.find(WMOAreaTableKey(int16(rootid), int8(adtid), groupid)); if (i != sWMOAreaInfoByTripple.end()) return i->second; return nullptr; } uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) { if (mapid != MAP_OUTLAND && mapid != MAP_NORTHREND) // speed for most cases return mapid; if (WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId)) return wma->virtual_map_id >= 0 ? wma->virtual_map_id : wma->map_id; return mapid; } ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId) { mapid = GetVirtualMapForMapAndZone(mapid, zoneId); if (mapid < 2) return CONTENT_1_60; MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry) return CONTENT_1_60; switch (mapEntry->Expansion()) { default: return CONTENT_1_60; case 1: return CONTENT_61_70; case 2: return CONTENT_71_80; } } void Zone2MapCoordinates(float& x, float& y, uint32 zone) { WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone); // if not listed then map coordinates (instance) if (!maEntry) return; std::swap(x, y); // at client map coords swapped x = x * ((maEntry->x2 - maEntry->x1) / 100) + maEntry->x1; y = y * ((maEntry->y2 - maEntry->y1) / 100) + maEntry->y1; // client y coord from top to down } void Map2ZoneCoordinates(float& x, float& y, uint32 zone) { WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone); // if not listed then map coordinates (instance) if (!maEntry) return; x = (x - maEntry->x1) / ((maEntry->x2 - maEntry->x1) / 100); y = (y - maEntry->y1) / ((maEntry->y2 - maEntry->y1) / 100); // client y coord from top to down std::swap(x, y); // client have map coords swapped } MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty) { MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId, difficulty)); return itr != sMapDifficultyMap.end() ? &itr->second : nullptr; } MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty& difficulty) { uint32 tmpDiff = difficulty; MapDifficulty const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); if (!mapDiff) { if (tmpDiff > RAID_DIFFICULTY_25MAN_NORMAL) // heroic, downscale to normal tmpDiff -= 2; else tmpDiff -= 1; // any non-normal mode for raids like tbc (only one mode) // pull new data mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // we are 10 normal or 25 normal if (!mapDiff) { tmpDiff -= 1; mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // 10 normal } } difficulty = Difficulty(tmpDiff); return mapDiff; } PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level) { PvPDifficultyEntry const* maxEntry = nullptr; // used for level > max listed level case for (PvPDifficultyEntry const* entry : sPvPDifficultyStore) { // skip unrelated and too-high brackets if (entry->mapId != mapid || entry->minLevel > level) continue; // exactly fit if (entry->maxLevel >= level) return entry; // remember for possible out-of-range case (search higher from existed) if (!maxEntry || maxEntry->maxLevel < entry->maxLevel) maxEntry = entry; } return maxEntry; } PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id) { for (PvPDifficultyEntry const* entry : sPvPDifficultyStore) if (entry->mapId == mapid && entry->GetBracketId() == id) return entry; return nullptr; } uint32 const* GetTalentTabPages(uint8 cls) { return sTalentTabPages[cls]; } bool IsSharedDifficultyMap(uint32 mapid) { return sWorld->getBoolConfig(CONFIG_INSTANCE_SHARED_ID) && (mapid == 631 || mapid == 724); } uint32 GetLiquidFlags(uint32 liquidType) { if (LiquidTypeEntry const* liq = sLiquidTypeStore.LookupEntry(liquidType)) return 1 << liq->Type; return 0; } CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender) { std::map::const_iterator itr = sCharStartOutfitMap.find(race | (class_ << 8) | (gender << 16)); if (itr == sCharStartOutfitMap.end()) return nullptr; return itr->second; } /// Returns LFGDungeonEntry for a specific map and difficulty. Will return first found entry if multiple dungeons use the same map (such as Scarlet Monastery) LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty) { for (uint32 i = 0; i < sLFGDungeonStore.GetNumRows(); ++i) { LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(i); if (!dungeon) continue; if (dungeon->MapID == uint32(mapId) && Difficulty(dungeon->Difficulty) == difficulty) return dungeon; } return nullptr; } LFGDungeonEntry const* GetZoneLFGDungeonEntry(std::string const& zoneName, LocaleConstant locale) { for (LFGDungeonEntry const* dungeon : sLFGDungeonStore) { if (dungeon->TypeID == lfg::LFG_TYPE_ZONE && zoneName.find(dungeon->Name[locale]) != std::string::npos) { return dungeon; } } return nullptr; } uint32 GetDefaultMapLight(uint32 mapId) { for (int32 i = sLightStore.GetNumRows(); i >= 0; --i) { LightEntry const* light = sLightStore.LookupEntry(uint32(i)); if (!light) continue; if (light->MapId == mapId && light->X == 0.0f && light->Y == 0.0f && light->Z == 0.0f) return light->Id; } return 0; } SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_) { SkillRaceClassInfoBounds bounds = SkillRaceClassInfoBySkill.equal_range(skill); for (SkillRaceClassInfoMap::iterator itr = bounds.first; itr != bounds.second; ++itr) { if (itr->second->RaceMask && !(itr->second->RaceMask & (1 << (race - 1)))) { continue; } if (itr->second->ClassMask && !(itr->second->ClassMask & (1 << (class_ - 1)))) { continue; } return itr->second; } return nullptr; } const std::vector& GetSkillLineAbilitiesBySkillLine(uint32 skillLine) { auto it = sSkillLineAbilityIndexBySkillLine.find(skillLine); if (it == sSkillLineAbilityIndexBySkillLine.end()) { static const std::vector emptyVector; return emptyVector; } return it->second; }