/* * Copyright (C) * Copyright (C) * * 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 "Log.h" #include "SharedDefines.h" #include "SpellMgr.h" #include "TransportMgr.h" #include "DBCfmt.h" #include "BattlegroundMgr.h" #include typedef std::map AreaFlagByAreaID; typedef std::map AreaFlagByMapID; struct WMOAreaTableTripple { WMOAreaTableTripple(int32 r, int32 a, int32 g) : groupId(g), rootId(r), adtId(a) { } bool operator <(const WMOAreaTableTripple& b) const { return memcmp(this, &b, sizeof(WMOAreaTableTripple))<0; } // ordered by entropy; that way memcmp will have a minimal medium runtime int32 groupId; int32 rootId; int32 adtId; }; typedef std::map WMOAreaInfoByTripple; DBCStorage sAreaStore(AreaTableEntryfmt); DBCStorage sAreaGroupStore(AreaGroupEntryfmt); DBCStorage sAreaPOIStore(AreaPOIEntryfmt); static AreaFlagByAreaID sAreaFlagByAreaID; static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files static WMOAreaInfoByTripple sWMOAreaInfoByTripple; DBCStorage sAchievementStore(Achievementfmt); DBCStorage sAchievementCriteriaStore(AchievementCriteriafmt); DBCStorage sAreaTriggerStore(AreaTriggerEntryfmt); 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 sCinematicSequencesStore(CinematicSequencesEntryfmt); DBCStorage sCreatureDisplayInfoStore(CreatureDisplayInfofmt); 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 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 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); 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 sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; DBCStorage sTalentTabStore(TalentTabEntryfmt); 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); DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); typedef std::list StoreProblemList; uint32 DBCFileCount = 0; static bool LoadDBC_assert_print(uint32 fsize, uint32 rsize, const std::string& filename) { sLog->outError("Size of '%s' set by format string (%u) not equal size of C++ structure (%u).", filename.c_str(), 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, std::string const* customFormat = NULL, std::string const* customIndexName = NULL) { // 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; SqlDbc * sql = NULL; if (customFormat) sql = new SqlDbc(&filename, customFormat, customIndexName, storage.GetFormat()); if (storage.Load(dbcFilename.c_str(), sql)) { 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<DBC records sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID), area->exploreFlag)); // fill MapId->DBC records (skip sub zones and continents) if (area->zone == 0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571) sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid, area->exploreFlag)); } } LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex); LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc"); for (uint32 i = 0; i < sCharStartOutfitStore.GetNumRows(); ++i) if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i)) sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit; LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc"); for (uint32 i=0; iteam) { SimpleFactionsList &flist = sFactionTeamMap[faction->team]; flist.push_back(i); } } LoadDBC(availableDbcLocales, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc"); for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i) { if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i)) { 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)); } } LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtNPCManaCostScalerStore, dbcPath, "gtNPCManaCostScaler.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sGtOCTRegenMPStore, dbcPath, "gtOCTRegenMP.dbc"); -- not used currently LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenHPPerSptStore, dbcPath, "gtRegenHPPerSpt.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemStore, dbcPath, "Item.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemExtendedCostStore, dbcPath, "ItemExtendedCost.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc"); // fill data for (uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i) if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0'); sMapDifficultyStore.Clear(); LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc"); for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex); for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { SpellEntry const* spell = sSpellStore.LookupEntry(i); if (spell && spell->Category) sSpellsByCategoryStore[spell->Category].insert(i); } for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); if (!skillLine) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); if (spellInfo && (spellInfo->Attributes & SPELL_ATTR0_PASSIVE)) { for (uint32 i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) { CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); if (!cFamily) continue; if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; if (spellInfo->spellLevel) continue; if (skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) continue; sPetFamilySpellsStore[i].insert(spellInfo->Id); } } } LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoryStore, dbcPath, "SpellCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshiftForm.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc"); // Create Spelldifficulty searcher for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i) { SpellDifficultyEntry const* spellDiff = sSpellDifficultyStore.LookupEntry(i); if (!spellDiff) continue; SpellDifficultyEntry newEntry; memset(newEntry.SpellID, 0, 4*sizeof(uint32)); for (int 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 sLog->outErrorDb("spelldifficulty_dbc: spell %i at field id:%u at spellid%i 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 (int x = 0; x < MAX_DIFFICULTY; ++x) if (newEntry.SpellID[x]) sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); } // create talent spells set for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; for (int j = 0; j < MAX_TALENT_RANK; j++) if (talentInfo->RankID[j]) sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i, j); } LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc"); for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price); uint32 pathCount = sTaxiPathStore.GetNumRows(); //## TaxiPathNode.dbc ## Loaded only for initialization different structures LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc"); // Calculate path nodes count 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 (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) 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 (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) if (SpellEntry const* sInfo = sSpellStore.LookupEntry (i)) for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue[j]); memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask)); memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask)); memset(sHordeTaxiNodesMask, 0, sizeof(sHordeTaxiNodesMask)); memset(sAllianceTaxiNodesMask, 0, sizeof(sAllianceTaxiNodesMask)); memset(sDeathKnightTaxiNodesMask, 0, sizeof(sDeathKnightTaxiNodesMask)); 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; } } LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTransportAnimationStore, dbcPath, "TransportAnimation.dbc"); for (uint32 i = 0; i < sTransportAnimationStore.GetNumRows(); ++i) { TransportAnimationEntry const* anim = sTransportAnimationStore.LookupEntry(i); if (!anim) continue; sTransportMgr->AddPathNodeToTransport(anim->TransportEntry, anim->TimeSeg, anim); } LoadDBC(availableDbcLocales, bad_dbc_files, sTransportRotationStore, dbcPath, "TransportRotation.dbc"); for (uint32 i = 0; i < sTransportRotationStore.GetNumRows(); ++i) { TransportRotationEntry const* rot = sTransportRotationStore.LookupEntry(i); if (!rot) continue; sTransportMgr->AddPathRotationToTransport(rot->TransportEntry, rot->TimeSeg, rot); } LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc"); for (uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i) if (WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i)) sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry)); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc"); // error checks if (bad_dbc_files.size() >= DBCFileCount) { sLog->outError("Incorrect DataDir value in worldserver.conf or ALL required *.dbc files (%d) not found by path: %sdbc", DBCFileCount, dataPath.c_str()); 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"; sLog->outError("Some required *.dbc files (%u from %d) not found or not compatible:\n%s", (uint32)bad_dbc_files.size(), DBCFileCount, str.c_str()); exit(1); } // Check loaded DBC files proper version if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) 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 gem property 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 { sLog->outError("You have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } sLog->outString(">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } SimpleFactionsList const* GetFactionTeamList(uint32 faction) { FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction); if (itr != sFactionTeamMap.end()) return &itr->second; return NULL; } char* GetPetName(uint32 petfamily, uint32 dbclang) { if (!petfamily) return NULL; CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(petfamily); if (!pet_family) return NULL; return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL; } TalentSpellPos const* GetTalentSpellPos(uint32 spellId) { TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId); if (itr == sTalentSpellPosMap.end()) return NULL; return &itr->second; } uint32 GetTalentSpellCost(uint32 spellId) { if (TalentSpellPos const* pos = GetTalentSpellPos(spellId)) return pos->rank+1; return 0; } int32 GetAreaFlagByAreaID(uint32 area_id) { AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); if (i == sAreaFlagByAreaID.end()) return -1; return i->second; } WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid) { WMOAreaInfoByTripple::iterator i = sWMOAreaInfoByTripple.find(WMOAreaTableTripple(rootid, adtid, groupid)); if (i == sWMOAreaInfoByTripple.end()) return NULL; return i->second; } AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) { int32 areaflag = GetAreaFlagByAreaID(area_id); if (areaflag < 0) return NULL; return sAreaStore.LookupEntry(areaflag); } AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id) { if (area_flag) return sAreaStore.LookupEntry(area_flag); if (MapEntry const* mapEntry = sMapStore.LookupEntry(map_id)) return GetAreaEntryByAreaID(mapEntry->linked_zone); return NULL; } uint32 GetAreaFlagByMapId(uint32 mapid) { AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid); if (i == sAreaFlagByMapID.end()) return 0; else return i->second; } uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) { if (mapid != 530 && mapid != 571) // 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 : NULL; } 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) { if (mapid == sBattlegroundMgr->randomBgDifficultyEntry.mapId) { if (level < sBattlegroundMgr->randomBgDifficultyEntry.minLevel) return NULL; return &sBattlegroundMgr->randomBgDifficultyEntry; } PvPDifficultyEntry const* maxEntry = NULL; // used for level > max listed level case for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) { if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) { // 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) { if (mapid == sBattlegroundMgr->randomBgDifficultyEntry.mapId) { if (id != sBattlegroundMgr->randomBgDifficultyEntry.bracketId) return NULL; return &sBattlegroundMgr->randomBgDifficultyEntry; } for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->mapId == mapid && entry->GetBracketId() == id) return entry; return NULL; } 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 NULL; 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->map == int32(mapId) && Difficulty(dungeon->difficulty) == difficulty) return dungeon; } return NULL; } 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; }