[9581] Fixed apply damage reduction to melee/ranged damage.
[getmangos.git] / src / game / DBCStores.cpp
blob6154967e26fea4429b9904373434aa814d13743c
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "DBCStores.h"
20 #include "Policies/SingletonImp.h"
21 #include "Log.h"
22 #include "ProgressBar.h"
23 #include "SharedDefines.h"
24 #include "ObjectGuid.h"
26 #include "DBCfmt.h"
28 #include <map>
30 typedef std::map<uint16,uint32> AreaFlagByAreaID;
31 typedef std::map<uint32,uint32> AreaFlagByMapID;
33 DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt);
34 DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt);
35 static AreaFlagByAreaID sAreaFlagByAreaID;
36 static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files
38 DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
39 DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt);
40 DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
41 DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
42 DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
43 DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
44 DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt);
45 DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt);
46 DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
47 DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
48 DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
49 DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
50 DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt);
51 DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
52 DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
53 DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
54 DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
55 DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
57 DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
58 DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
60 DBCStorage <EmotesEntry> sEmotesStore(EmotesEntryfmt);
61 DBCStorage <EmotesTextEntry> sEmotesTextStore(EmotesTextEntryfmt);
63 typedef std::map<uint32,SimpleFactionsList> FactionTeamMap;
64 static FactionTeamMap sFactionTeamMap;
65 DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
66 DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
68 DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt);
69 DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
70 DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore(GlyphPropertiesfmt);
71 DBCStorage <GlyphSlotEntry> sGlyphSlotStore(GlyphSlotfmt);
73 DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt);
74 DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore(GtCombatRatingsfmt);
75 DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt);
76 DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt);
77 DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt);
78 DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSpellCritfmt);
79 DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
80 //DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
81 DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
82 DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
84 DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
86 DBCStorage <ItemEntry> sItemStore(Itemfmt);
87 DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
88 //DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
89 //DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
90 DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
91 DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
92 DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
93 DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
94 DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
96 DBCStorage <LockEntry> sLockStore(LockEntryfmt);
98 DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
99 DBCStorage <MapEntry> sMapStore(MapEntryfmt);
101 // DBC used only for initialization sMapDifficultyMap at startup.
102 DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
103 MapDifficultyMap sMapDifficultyMap;
105 DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
107 DBCStorage <QuestFactionRewardEntry> sQuestFactionRewardStore(QuestFactionRewardfmt);
108 DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
109 DBCStorage <QuestXPLevel> sQuestXPLevelStore(QuestXPLevelfmt);
111 DBCStorage <PvPDifficultyEntry> sPvPDifficultyStore(PvPDifficultyfmt);
113 DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore(RandomPropertiesPointsfmt);
114 DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore(ScalingStatDistributionfmt);
115 DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore(ScalingStatValuesfmt);
117 DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
118 DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
120 DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
122 DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt);
123 DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt);
124 DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
125 SpellCategoryStore sSpellCategoryStore;
126 PetFamilySpellsStore sPetFamilySpellsStore;
128 DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
129 DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
130 DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
131 DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
132 DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
133 DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt);
134 DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
135 DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
136 DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
137 DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
138 TalentSpellPosMap sTalentSpellPosMap;
139 DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
141 // store absolute bit position for first rank for talent inspect
142 static uint32 sTalentTabPages[MAX_CLASSES][3];
144 DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
145 TaxiMask sTaxiNodesMask;
146 TaxiMask sOldContinentsNodesMask;
148 // DBC used only for initialization sTaxiPathSetBySource at startup.
149 TaxiPathSetBySource sTaxiPathSetBySource;
150 DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
152 // DBC used only for initialization sTaxiPathNodeStore at startup.
153 TaxiPathNodesByPath sTaxiPathNodesByPath;
154 static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
156 DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
157 DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt);
158 DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt);
159 DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
160 DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
161 DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
163 typedef std::list<std::string> StoreProblemList;
165 bool IsAcceptableClientBuild(uint32 build)
167 int accepted_versions[] = EXPECTED_MANGOSD_CLIENT_BUILD;
168 for(int i = 0; accepted_versions[i]; ++i)
169 if(build == accepted_versions[i])
170 return true;
172 return false;
175 std::string AcceptableClientBuildsListStr()
177 std::ostringstream data;
178 int accepted_versions[] = EXPECTED_MANGOSD_CLIENT_BUILD;
179 for(int i = 0; accepted_versions[i]; ++i)
180 data << accepted_versions[i] << " ";
181 return data.str();
184 static bool ReadDBCBuildFileText(const std::string& dbc_path, char const* localeName, std::string& text)
186 std::string filename = dbc_path + "component.wow-" + localeName + ".txt";
188 if(FILE* file = fopen(filename.c_str(),"rb"))
190 char buf[100];
191 fread(buf,1,100-1,file);
192 fclose(file);
194 text = &buf[0];
195 return true;
197 else
198 return false;
201 static uint32 ReadDBCBuild(const std::string& dbc_path, char const* localeName = NULL)
203 std::string text;
205 if (!localeName)
207 for(LocaleNameStr* itr = &fullLocaleNameList[0]; itr->name; ++itr)
208 if (ReadDBCBuildFileText(dbc_path,itr->name,text))
209 break;
211 else
212 ReadDBCBuildFileText(dbc_path,localeName,text);
214 if (text.empty())
215 return 0;
217 size_t pos = text.find("version=\"");
218 size_t pos1 = pos + strlen("version=\"");
219 size_t pos2 = text.find("\"",pos1);
220 if (pos == text.npos || pos2 == text.npos || pos1 >= pos2)
221 return 0;
223 std::string build_str = text.substr(pos1,pos2-pos1);
225 int build = atoi(build_str.c_str());
226 if (build <= 0)
227 return 0;
229 return build;
232 static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, const std::string& filename)
234 sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize);
236 // assert must fail after function call
237 return false;
240 struct LocalData
242 explicit LocalData(uint32 build) : main_build(build), availableDbcLocales(0xFFFFFFFF),checkedDbcLocaleBuilds(0) {}
243 uint32 main_build;
245 // bitmasks for index of fullLocaleNameList
246 uint32 availableDbcLocales;
247 uint32 checkedDbcLocaleBuilds;
250 template<class T>
251 inline void LoadDBC(LocalData& localeData,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, const std::string& dbc_path, const std::string& filename)
253 // compatibility format and C++ structure sizes
254 assert(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename));
256 std::string dbc_filename = dbc_path + filename;
257 if(storage.Load(dbc_filename.c_str()))
259 bar.step();
260 for(uint8 i = 0; fullLocaleNameList[i].name; ++i)
262 if (!(localeData.availableDbcLocales & (1 << i)))
263 continue;
265 std::string dbc_dir_loc = dbc_path + fullLocaleNameList[i].name + "/";
267 if (!(localeData.checkedDbcLocaleBuilds & (1 << i)))
269 localeData.checkedDbcLocaleBuilds |= (1<<i);// mark as checked for speedup next checks
271 uint32 build_loc = ReadDBCBuild(dbc_dir_loc,fullLocaleNameList[i].name);
272 if(localeData.main_build != build_loc)
274 localeData.availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
276 // exist but wrong build
277 if (build_loc)
279 std::string dbc_filename_loc = dbc_path + fullLocaleNameList[i].name + "/" + filename;
280 char buf[200];
281 snprintf(buf,200," (exist, but DBC locale subdir %s have DBCs for build %u instead expected build %u, it and other DBC from subdir skipped)",fullLocaleNameList[i].name,build_loc,localeData.main_build);
282 errlist.push_back(dbc_filename_loc + buf);
285 continue;
289 std::string dbc_filename_loc = dbc_path + fullLocaleNameList[i].name + "/" + filename;
290 if(!storage.LoadStringsFrom(dbc_filename_loc.c_str()))
291 localeData.availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
294 else
296 // sort problematic dbc to (1) non compatible and (2) non-existed
297 FILE * f=fopen(dbc_filename.c_str(),"rb");
298 if(f)
300 char buf[100];
301 snprintf(buf,100," (exist, but have %d fields instead " SIZEFMTD ") Wrong client version DBC file?",storage.GetFieldCount(),strlen(storage.GetFormat()));
302 errlist.push_back(dbc_filename + buf);
303 fclose(f);
305 else
306 errlist.push_back(dbc_filename);
310 void LoadDBCStores(const std::string& dataPath)
312 std::string dbcPath = dataPath+"dbc/";
314 uint32 build = ReadDBCBuild(dbcPath);
316 // Check the expected DBC version
317 if (!IsAcceptableClientBuild(build))
319 if (build)
320 sLog.outError("Found DBC files for build %u but mangosd expected DBC for one from builds: %s Please extract correct DBC files.", build, AcceptableClientBuildsListStr().c_str());
321 else
322 sLog.outError("Incorrect DataDir value in mangosd.conf or not found build info (outdated DBC files). Required one from builds: %s Please extract correct DBC files.",AcceptableClientBuildsListStr().c_str());
323 exit(1);
326 const uint32 DBCFilesCount = 84;
328 barGoLink bar( (int)DBCFilesCount );
330 StoreProblemList bad_dbc_files;
332 LocalData availableDbcLocales(build);
334 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaStore, dbcPath,"AreaTable.dbc");
336 // must be after sAreaStore loading
337 for(uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0
339 if(AreaTableEntry const* area = sAreaStore.LookupEntry(i))
341 // fill AreaId->DBC records
342 sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag));
344 // fill MapId->DBC records ( skip sub zones and continents )
345 if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571 )
346 sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag));
350 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementStore, dbcPath,"Achievement.dbc");
351 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementCriteriaStore, dbcPath,"Achievement_Criteria.dbc");
352 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc");
353 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaGroupStore, dbcPath,"AreaGroup.dbc");
354 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAuctionHouseStore, dbcPath,"AuctionHouse.dbc");
355 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc");
356 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
357 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc");
358 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc");
359 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
360 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
361 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
362 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc");
363 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCinematicSequencesStore, dbcPath,"CinematicSequences.dbc");
364 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
365 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
366 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
367 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc");
368 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc");
369 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc");
370 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc");
371 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesStore, dbcPath,"Emotes.dbc");
372 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc");
373 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc");
374 for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i)
376 FactionEntry const * faction = sFactionStore.LookupEntry(i);
377 if (faction && faction->team)
379 SimpleFactionsList &flist = sFactionTeamMap[faction->team];
380 flist.push_back(i);
384 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc");
385 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGameObjectDisplayInfoStore,dbcPath,"GameObjectDisplayInfo.dbc");
386 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc");
387 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc");
388 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc");
390 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtBarberShopCostBaseStore,dbcPath,"gtBarberShopCostBase.dbc");
391 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc");
393 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc");
394 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc");
396 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc");
397 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc");
399 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc");
400 //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
401 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
402 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
403 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc");
404 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc");
405 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemBagFamilyStore, dbcPath,"ItemBagFamily.dbc");
406 //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently
407 //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc");
408 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc");
409 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemLimitCategoryStore, dbcPath,"ItemLimitCategory.dbc");
410 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc");
411 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc");
412 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc");
413 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
414 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
415 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
417 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapDifficultyStore, dbcPath,"MapDifficulty.dbc");
418 // fill data
419 for(uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i)
420 if(MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i))
421 sMapDifficultyMap[MAKE_PAIR32(entry->MapId,entry->Difficulty)] = MapDifficulty(entry->resetTime,entry->maxPlayers);
422 sMapDifficultyStore.Clear();
424 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMovieStore, dbcPath,"Movie.dbc");
425 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestFactionRewardStore, dbcPath,"QuestFactionReward.dbc");
426 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc");
427 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestXPLevelStore, dbcPath,"QuestXP.dbc");
428 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sPvPDifficultyStore, dbcPath,"PvpDifficulty.dbc");
429 for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
430 if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
431 if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS)
432 assert(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data");
434 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc");
435 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatDistributionStore, dbcPath,"ScalingStatDistribution.dbc");
436 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc");
437 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
438 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
439 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
440 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
441 for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
443 SpellEntry const * spell = sSpellStore.LookupEntry(i);
444 if(spell && spell->Category)
445 sSpellCategoryStore[spell->Category].insert(i);
447 // DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields
448 // uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view
449 #if MANGOS_ENDIAN == MANGOS_BIGENDIAN
450 std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1));
451 #endif
454 for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
456 SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
458 if(!skillLine)
459 continue;
461 SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
463 if(spellInfo && (spellInfo->Attributes & 0x1D0) == 0x1D0)
465 for (unsigned int i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i)
467 CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i);
468 if(!cFamily)
469 continue;
471 if(skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1])
472 continue;
474 sPetFamilySpellsStore[i].insert(spellInfo->Id);
479 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc");
480 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc");
481 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc");
482 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc");
483 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc");
484 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc");
485 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc");
486 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc");
487 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
488 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
489 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
490 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
492 // create talent spells set
493 for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i)
495 TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
496 if (!talentInfo) continue;
497 for (int j = 0; j < MAX_TALENT_RANK; j++)
498 if(talentInfo->RankID[j])
499 sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i,j);
502 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc");
504 // prepare fast data access to bit pos of talent ranks for use at inspecting
506 // now have all max ranks (and then bit amount used for store talent ranks in inspect)
507 for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
509 TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId );
510 if(!talentTabInfo)
511 continue;
513 // prevent memory corruption; otherwise cls will become 12 below
514 if ((talentTabInfo->ClassMask & CLASSMASK_ALL_PLAYABLE)==0)
515 continue;
517 // store class talent tab pages
518 uint32 cls = 1;
519 for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < MAX_CLASSES;m <<=1, ++cls) {}
521 sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId;
525 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc");
527 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc");
528 for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
529 if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
530 sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID,entry->price);
531 uint32 pathCount = sTaxiPathStore.GetNumRows();
533 //## TaxiPathNode.dbc ## Loaded only for initialization different structures
534 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc");
535 // Calculate path nodes count
536 std::vector<uint32> pathLength;
537 pathLength.resize(pathCount); // 0 and some other indexes not used
538 for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
539 if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
541 if (pathLength[entry->path] < entry->index + 1)
542 pathLength[entry->path] = entry->index + 1;
544 // Set path length
545 sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used
546 for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i)
547 sTaxiPathNodesByPath[i].resize(pathLength[i]);
548 // fill data
549 for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
550 if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
551 sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay);
552 sTaxiPathNodeStore.Clear();
554 // Initialize global taxinodes mask
555 // include existed nodes that have at least single not spell base (scripted) path
557 std::set<uint32> spellPaths;
558 for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i)
559 if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
560 for(int j=0; j < MAX_EFFECT_INDEX; ++j)
561 if(sInfo->Effect[j]==123 /*SPELL_EFFECT_SEND_TAXI*/)
562 spellPaths.insert(sInfo->EffectMiscValue[j]);
564 memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
565 memset(sOldContinentsNodesMask,0,sizeof(sTaxiNodesMask));
566 for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
568 TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
569 if(!node)
570 continue;
572 TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i);
573 if(src_i!=sTaxiPathSetBySource.end() && !src_i->second.empty())
575 bool ok = false;
576 for(TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin();dest_i != src_i->second.end(); ++dest_i)
578 // not spell path
579 if(spellPaths.find(dest_i->second.ID)==spellPaths.end())
581 ok = true;
582 break;
586 if(!ok)
587 continue;
590 // valid taxi network node
591 uint8 field = (uint8)((i - 1) / 32);
592 uint32 submask = 1<<((i-1)%32);
593 sTaxiNodesMask[field] |= submask;
595 // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info)
596 if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94)
597 sOldContinentsNodesMask[field] |= submask;
601 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc");
602 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc");
603 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc");
604 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc");
605 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc");
606 LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc");
608 // error checks
609 if(bad_dbc_files.size() >= DBCFilesCount )
611 sLog.outError("\nIncorrect DataDir value in mangosd.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str());
612 exit(1);
614 else if(!bad_dbc_files.empty() )
616 std::string str;
617 for(std::list<std::string>::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i)
618 str += *i + "\n";
620 sLog.outError("\nSome required *.dbc files (%u from %d) not found or not compatible:\n%s",(uint32)bad_dbc_files.size(),DBCFilesCount,str.c_str());
621 exit(1);
624 // Check loaded DBC files proper version
625 if( !sSpellStore.LookupEntry(74445) || // last added spell in 3.3.2
626 !sMapStore.LookupEntry(718) || // last map added in 3.3.2
627 !sGemPropertiesStore.LookupEntry(1629) || // last gem property added in 3.3.2
628 !sItemExtendedCostStore.LookupEntry(2982) || // last item extended cost added in 3.3.2
629 !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.2
630 !sAreaStore.LookupEntry(3461) || // last area (areaflag) added in 3.3.2
631 !sItemStore.LookupEntry(52686) ) // last client known item added in 3.3.2
633 sLog.outError("\nYou have mixed version DBC files. Please re-extract DBC files for one from client build: %s",AcceptableClientBuildsListStr().c_str());
634 exit(1);
637 sLog.outString();
638 sLog.outString( ">> Initialized %d data stores", DBCFilesCount );
641 SimpleFactionsList const* GetFactionTeamList(uint32 faction)
643 FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
644 if(itr==sFactionTeamMap.end())
645 return NULL;
646 return &itr->second;
649 char* GetPetName(uint32 petfamily, uint32 dbclang)
651 if(!petfamily)
652 return NULL;
653 CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(petfamily);
654 if(!pet_family)
655 return NULL;
656 return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL;
659 TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
661 TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId);
662 if(itr==sTalentSpellPosMap.end())
663 return NULL;
665 return &itr->second;
668 uint32 GetTalentSpellCost(uint32 spellId)
670 if(TalentSpellPos const* pos = GetTalentSpellPos(spellId))
671 return pos->rank+1;
673 return 0;
676 int32 GetAreaFlagByAreaID(uint32 area_id)
678 AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id);
679 if(i == sAreaFlagByAreaID.end())
680 return -1;
682 return i->second;
685 AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id)
687 int32 areaflag = GetAreaFlagByAreaID(area_id);
688 if(areaflag < 0)
689 return NULL;
691 return sAreaStore.LookupEntry(areaflag );
694 AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id)
696 if(area_flag)
697 return sAreaStore.LookupEntry(area_flag);
699 if(MapEntry const* mapEntry = sMapStore.LookupEntry(map_id))
700 return GetAreaEntryByAreaID(mapEntry->linked_zone);
702 return NULL;
705 uint32 GetAreaFlagByMapId(uint32 mapid)
707 AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid);
708 if(i == sAreaFlagByMapID.end())
709 return 0;
710 else
711 return i->second;
714 uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
716 if(mapid != 530 && mapid != 571) // speed for most cases
717 return mapid;
719 if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
720 return wma->virtual_map_id >= 0 ? wma->virtual_map_id : wma->map_id;
722 return mapid;
725 ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
727 mapid = GetVirtualMapForMapAndZone(mapid,zoneId);
728 if(mapid < 2)
729 return CONTENT_1_60;
731 MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
732 if(!mapEntry)
733 return CONTENT_1_60;
735 switch(mapEntry->Expansion())
737 default: return CONTENT_1_60;
738 case 1: return CONTENT_61_70;
739 case 2: return CONTENT_71_80;
743 ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
745 // not sorted, numbering index from 0
746 for(uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
748 ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
749 if(ch && ch->ChannelID == channel_id)
750 return ch;
752 return NULL;
755 bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
757 if(requiredTotemCategoryId==0)
758 return true;
759 if(itemTotemCategoryId==0)
760 return false;
762 TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId);
763 if(!itemEntry)
764 return false;
765 TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId);
766 if(!reqEntry)
767 return false;
769 if(itemEntry->categoryType!=reqEntry->categoryType)
770 return false;
772 return (itemEntry->categoryMask & reqEntry->categoryMask)==reqEntry->categoryMask;
775 bool Zone2MapCoordinates(float& x,float& y,uint32 zone)
777 WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
779 // if not listed then map coordinates (instance)
780 if (!maEntry || maEntry->x2 == maEntry->x1 || maEntry->y2 == maEntry->y1)
781 return false;
783 std::swap(x,y); // at client map coords swapped
784 x = x*((maEntry->x2-maEntry->x1)/100)+maEntry->x1;
785 y = y*((maEntry->y2-maEntry->y1)/100)+maEntry->y1; // client y coord from top to down
787 return true;
790 bool Map2ZoneCoordinates(float& x,float& y,uint32 zone)
792 WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
794 // if not listed then map coordinates (instance)
795 if (!maEntry || maEntry->x2 == maEntry->x1 || maEntry->y2 == maEntry->y1)
796 return false;
798 x = (x-maEntry->x1)/((maEntry->x2-maEntry->x1)/100);
799 y = (y-maEntry->y1)/((maEntry->y2-maEntry->y1)/100); // client y coord from top to down
800 std::swap(x,y); // client have map coords swapped
802 return true;
805 MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
807 MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId,difficulty));
808 return itr != sMapDifficultyMap.end() ? &itr->second : NULL;
811 PvPDifficultyEntry const* GetBattlegroundBracketByLevel( uint32 mapid, uint32 level )
813 // prevent out-of-range levels for dbc data
814 if (level > DEFAULT_MAX_LEVEL)
815 level = DEFAULT_MAX_LEVEL;
817 for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
818 if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
819 if (entry->mapId == mapid && entry->minLevel <= level && entry->maxLevel >= level)
820 return entry;
822 return NULL;
825 PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattleGroundBracketId id)
827 for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i)
828 if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i))
829 if (entry->mapId == mapid && entry->GetBracketId() == id)
830 return entry;
832 return NULL;
835 uint32 const* GetTalentTabPages(uint32 cls)
837 return sTalentTabPages[cls];
840 // script support functions
841 MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; }
842 MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }
843 MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; }
844 MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore() { return &sFactionStore; }
845 MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore() { return &sItemStore; }
846 MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; }
847 MANGOS_DLL_SPEC DBCStorage <EmotesEntry> const* GetEmotesStore() { return &sEmotesStore; }
848 MANGOS_DLL_SPEC DBCStorage <EmotesTextEntry> const* GetEmotesTextStore() { return &sEmotesTextStore; }