mirror of
https://github.com/mangosfour/server.git
synced 2025-12-28 13:37:13 +00:00
ASSERT hard use in predictable way because diff. 3rd party libs code redefine it inf different ways and hard make sure that used in end of mangos define version. This is real detected problem make some expected assert checks ignored and so bugs not detected as expected from code. In addition made related changes: * Common.h header expected to be first include in any src/game/header except most simple cases. * Related FILE.h header expected to be first include in FILE.cpp * Fixed some absent includes and type forwards for safe build without PCH enabled. * Avoid using MANGOS_ASSERT in src/framework code
962 lines
43 KiB
C++
962 lines
43 KiB
C++
/*
|
||
* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
|
||
*
|
||
* 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, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
*/
|
||
|
||
#include "DBCStores.h"
|
||
#include "Policies/SingletonImp.h"
|
||
#include "Log.h"
|
||
#include "ProgressBar.h"
|
||
#include "SharedDefines.h"
|
||
#include "ObjectGuid.h"
|
||
|
||
#include "DBCfmt.h"
|
||
|
||
#include <map>
|
||
|
||
typedef std::map<uint16,uint32> AreaFlagByAreaID;
|
||
typedef std::map<uint32,uint32> AreaFlagByMapID;
|
||
|
||
struct WMOAreaTableTripple
|
||
{
|
||
WMOAreaTableTripple(int32 r, int32 a, int32 g) : rootId(r), adtId(a), groupId(g)
|
||
{
|
||
}
|
||
|
||
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<WMOAreaTableTripple, WMOAreaTableEntry const *> WMOAreaInfoByTripple;
|
||
|
||
DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt);
|
||
DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt);
|
||
static AreaFlagByAreaID sAreaFlagByAreaID;
|
||
static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files
|
||
|
||
static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
|
||
|
||
DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt);
|
||
DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt);
|
||
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
|
||
DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt);
|
||
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
|
||
DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
|
||
DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt);
|
||
DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt);
|
||
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
|
||
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
|
||
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
|
||
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
|
||
DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt);
|
||
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
|
||
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
|
||
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
|
||
DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt);
|
||
DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt);
|
||
|
||
DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
|
||
DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
|
||
|
||
DBCStorage <EmotesEntry> sEmotesStore(EmotesEntryfmt);
|
||
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmotesTextEntryfmt);
|
||
|
||
typedef std::map<uint32,SimpleFactionsList> FactionTeamMap;
|
||
static FactionTeamMap sFactionTeamMap;
|
||
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
|
||
DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
|
||
|
||
DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt);
|
||
DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
|
||
DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore(GlyphPropertiesfmt);
|
||
DBCStorage <GlyphSlotEntry> sGlyphSlotStore(GlyphSlotfmt);
|
||
|
||
DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt);
|
||
DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore(GtCombatRatingsfmt);
|
||
DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt);
|
||
DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt);
|
||
DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt);
|
||
DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSpellCritfmt);
|
||
DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
|
||
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
|
||
DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
|
||
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
|
||
|
||
DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt);
|
||
|
||
DBCStorage <ItemEntry> sItemStore(Itemfmt);
|
||
DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt);
|
||
//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
|
||
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
|
||
DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
|
||
DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore(ItemLimitCategoryEntryfmt);
|
||
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
|
||
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
|
||
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
|
||
|
||
DBCStorage <LockEntry> sLockStore(LockEntryfmt);
|
||
|
||
DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
|
||
DBCStorage <MapEntry> sMapStore(MapEntryfmt);
|
||
|
||
// DBC used only for initialization sMapDifficultyMap at startup.
|
||
DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
|
||
MapDifficultyMap sMapDifficultyMap;
|
||
|
||
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
|
||
|
||
DBCStorage <QuestFactionRewardEntry> sQuestFactionRewardStore(QuestFactionRewardfmt);
|
||
DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
|
||
DBCStorage <QuestXPLevel> sQuestXPLevelStore(QuestXPLevelfmt);
|
||
|
||
DBCStorage <PvPDifficultyEntry> sPvPDifficultyStore(PvPDifficultyfmt);
|
||
|
||
DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore(RandomPropertiesPointsfmt);
|
||
DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore(ScalingStatDistributionfmt);
|
||
DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore(ScalingStatValuesfmt);
|
||
|
||
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
|
||
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
|
||
|
||
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
|
||
|
||
DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt);
|
||
DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt);
|
||
DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
|
||
SpellCategoryStore sSpellCategoryStore;
|
||
PetFamilySpellsStore sPetFamilySpellsStore;
|
||
|
||
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
|
||
DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore(SpellDifficultyfmt);
|
||
DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
|
||
DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
|
||
DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
|
||
DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
|
||
DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt);
|
||
DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
|
||
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
|
||
DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt);
|
||
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
|
||
TalentSpellPosMap sTalentSpellPosMap;
|
||
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
|
||
|
||
// store absolute bit position for first rank for talent inspect
|
||
static uint32 sTalentTabPages[MAX_CLASSES][3];
|
||
|
||
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
|
||
TaxiMask sTaxiNodesMask;
|
||
TaxiMask sOldContinentsNodesMask;
|
||
|
||
// DBC used only for initialization sTaxiPathSetBySource at startup.
|
||
TaxiPathSetBySource sTaxiPathSetBySource;
|
||
DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
|
||
|
||
// DBC store data but sTaxiPathNodesByPath used for fast access to entries (it's not owner pointed data).
|
||
TaxiPathNodesByPath sTaxiPathNodesByPath;
|
||
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
|
||
|
||
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
|
||
DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt);
|
||
DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt);
|
||
DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore(WMOAreaTableEntryfmt);
|
||
DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
|
||
DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
|
||
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
|
||
|
||
typedef std::list<std::string> StoreProblemList;
|
||
|
||
bool IsAcceptableClientBuild(uint32 build)
|
||
{
|
||
int accepted_versions[] = EXPECTED_MANGOSD_CLIENT_BUILD;
|
||
for(int i = 0; accepted_versions[i]; ++i)
|
||
if(build == accepted_versions[i])
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
std::string AcceptableClientBuildsListStr()
|
||
{
|
||
std::ostringstream data;
|
||
int accepted_versions[] = EXPECTED_MANGOSD_CLIENT_BUILD;
|
||
for(int i = 0; accepted_versions[i]; ++i)
|
||
data << accepted_versions[i] << " ";
|
||
return data.str();
|
||
}
|
||
|
||
static bool ReadDBCBuildFileText(const std::string& dbc_path, char const* localeName, std::string& text)
|
||
{
|
||
std::string filename = dbc_path + "component.wow-" + localeName + ".txt";
|
||
|
||
if(FILE* file = fopen(filename.c_str(),"rb"))
|
||
{
|
||
char buf[100];
|
||
fread(buf,1,100-1,file);
|
||
fclose(file);
|
||
|
||
text = &buf[0];
|
||
return true;
|
||
}
|
||
else
|
||
return false;
|
||
}
|
||
|
||
static uint32 ReadDBCBuild(const std::string& dbc_path, LocaleNameStr const* localeNameStr = NULL)
|
||
{
|
||
std::string text;
|
||
|
||
if (!localeNameStr)
|
||
{
|
||
for(LocaleNameStr const* itr = &fullLocaleNameList[0]; itr->name; ++itr)
|
||
{
|
||
if (ReadDBCBuildFileText(dbc_path,itr->name,text))
|
||
{
|
||
localeNameStr = itr;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
ReadDBCBuildFileText(dbc_path,localeNameStr->name,text);
|
||
|
||
if (text.empty())
|
||
return 0;
|
||
|
||
size_t pos = text.find("version=\"");
|
||
size_t pos1 = pos + strlen("version=\"");
|
||
size_t pos2 = text.find("\"",pos1);
|
||
if (pos == text.npos || pos2 == text.npos || pos1 >= pos2)
|
||
return 0;
|
||
|
||
std::string build_str = text.substr(pos1,pos2-pos1);
|
||
|
||
int build = atoi(build_str.c_str());
|
||
if (build <= 0)
|
||
return 0;
|
||
|
||
return build;
|
||
}
|
||
|
||
static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, const std::string& filename)
|
||
{
|
||
sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize);
|
||
|
||
// ASSERT must fail after function call
|
||
return false;
|
||
}
|
||
|
||
struct LocalData
|
||
{
|
||
LocalData(uint32 build)
|
||
: main_build(build), availableDbcLocales(0xFFFFFFFF),checkedDbcLocaleBuilds(0) {}
|
||
|
||
uint32 main_build;
|
||
|
||
// bitmasks for index of fullLocaleNameList
|
||
uint32 availableDbcLocales;
|
||
uint32 checkedDbcLocaleBuilds;
|
||
};
|
||
|
||
template<class T>
|
||
inline void LoadDBC(LocalData& localeData,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, const std::string& dbc_path, const std::string& filename)
|
||
{
|
||
// compatibility format and C++ structure sizes
|
||
MANGOS_ASSERT(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFileLoader::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename));
|
||
|
||
std::string dbc_filename = dbc_path + filename;
|
||
if(storage.Load(dbc_filename.c_str()))
|
||
{
|
||
bar.step();
|
||
for(uint8 i = 0; fullLocaleNameList[i].name; ++i)
|
||
{
|
||
if (!(localeData.availableDbcLocales & (1 << i)))
|
||
continue;
|
||
|
||
LocaleNameStr const* localStr = &fullLocaleNameList[i];
|
||
|
||
std::string dbc_dir_loc = dbc_path + localStr->name + "/";
|
||
|
||
if (!(localeData.checkedDbcLocaleBuilds & (1 << i)))
|
||
{
|
||
localeData.checkedDbcLocaleBuilds |= (1<<i);// mark as checked for speedup next checks
|
||
|
||
|
||
uint32 build_loc = ReadDBCBuild(dbc_dir_loc,localStr);
|
||
if(localeData.main_build != build_loc)
|
||
{
|
||
localeData.availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
|
||
|
||
// exist but wrong build
|
||
if (build_loc)
|
||
{
|
||
std::string dbc_filename_loc = dbc_path + localStr->name + "/" + filename;
|
||
char buf[200];
|
||
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)",localStr->name,build_loc,localeData.main_build);
|
||
errlist.push_back(dbc_filename_loc + buf);
|
||
}
|
||
|
||
continue;
|
||
}
|
||
}
|
||
|
||
std::string dbc_filename_loc = dbc_path + localStr->name + "/" + filename;
|
||
if(!storage.LoadStringsFrom(dbc_filename_loc.c_str()))
|
||
localeData.availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// sort problematic dbc to (1) non compatible and (2) nonexistent
|
||
FILE * f=fopen(dbc_filename.c_str(),"rb");
|
||
if(f)
|
||
{
|
||
char buf[100];
|
||
snprintf(buf,100," (exist, but have %d fields instead " SIZEFMTD ") Wrong client version DBC file?",storage.GetFieldCount(),strlen(storage.GetFormat()));
|
||
errlist.push_back(dbc_filename + buf);
|
||
fclose(f);
|
||
}
|
||
else
|
||
errlist.push_back(dbc_filename);
|
||
}
|
||
}
|
||
|
||
void LoadDBCStores(const std::string& dataPath)
|
||
{
|
||
std::string dbcPath = dataPath+"dbc/";
|
||
|
||
uint32 build = ReadDBCBuild(dbcPath);
|
||
|
||
// Check the expected DBC version
|
||
if (!IsAcceptableClientBuild(build))
|
||
{
|
||
if (build)
|
||
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());
|
||
else
|
||
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());
|
||
Log::WaitBeforeContinueIfNeed();
|
||
exit(1);
|
||
}
|
||
|
||
const uint32 DBCFilesCount = 85;
|
||
|
||
barGoLink bar( (int)DBCFilesCount );
|
||
|
||
StoreProblemList bad_dbc_files;
|
||
|
||
LocalData availableDbcLocales(build);
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaStore, dbcPath,"AreaTable.dbc");
|
||
|
||
// must be after sAreaStore loading
|
||
for(uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0
|
||
{
|
||
if(AreaTableEntry const* area = sAreaStore.LookupEntry(i))
|
||
{
|
||
// fill AreaId->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,bar,bad_dbc_files,sAchievementStore, dbcPath,"Achievement.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementCriteriaStore, dbcPath,"Achievement_Criteria.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaGroupStore, dbcPath,"AreaGroup.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAuctionHouseStore, dbcPath,"AuctionHouse.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCinematicSequencesStore, dbcPath,"CinematicSequences.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCurrencyTypesStore, dbcPath,"CurrencyTypes.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesStore, dbcPath,"Emotes.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc");
|
||
for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i)
|
||
{
|
||
FactionEntry const * faction = sFactionStore.LookupEntry(i);
|
||
if (faction && faction->team)
|
||
{
|
||
SimpleFactionsList &flist = sFactionTeamMap[faction->team];
|
||
flist.push_back(i);
|
||
}
|
||
}
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGameObjectDisplayInfoStore,dbcPath,"GameObjectDisplayInfo.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtBarberShopCostBaseStore,dbcPath,"gtBarberShopCostBase.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc");
|
||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemBagFamilyStore, dbcPath,"ItemBagFamily.dbc");
|
||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently
|
||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemLimitCategoryStore, dbcPath,"ItemLimitCategory.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,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);
|
||
sMapDifficultyStore.Clear();
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMovieStore, dbcPath,"Movie.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestFactionRewardStore, dbcPath,"QuestFactionReward.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestXPLevelStore, dbcPath,"QuestXP.dbc");
|
||
LoadDBC(availableDbcLocales,bar,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)
|
||
MANGOS_ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data");
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatDistributionStore, dbcPath,"ScalingStatDistribution.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
|
||
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
||
{
|
||
SpellEntry const * spell = sSpellStore.LookupEntry(i);
|
||
if(spell && spell->Category)
|
||
sSpellCategoryStore[spell->Category].insert(i);
|
||
|
||
// DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields
|
||
// uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view
|
||
#if MANGOS_ENDIAN == MANGOS_BIGENDIAN
|
||
std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1));
|
||
#endif
|
||
}
|
||
|
||
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 & 0x1D0) == 0x1D0)
|
||
{
|
||
for (unsigned int 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;
|
||
|
||
sPetFamilySpellsStore[i].insert(spellInfo->Id);
|
||
}
|
||
}
|
||
}
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDifficultyStore, dbcPath,"SpellDifficulty.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
|
||
|
||
// create talent spells set
|
||
for (unsigned int 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,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc");
|
||
|
||
// 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
|
||
uint32 cls = 1;
|
||
for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < MAX_CLASSES;m <<=1, ++cls) {}
|
||
|
||
sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId;
|
||
}
|
||
}
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc");
|
||
|
||
LoadDBC(availableDbcLocales,bar,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,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc");
|
||
// Calculate path nodes count
|
||
std::vector<uint32> 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 (pointers to sTaxiPathNodeStore elements
|
||
for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
|
||
if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
|
||
sTaxiPathNodesByPath[entry->path].set(entry->index, entry);
|
||
|
||
// Initialize global taxinodes mask
|
||
// include existing nodes that have at least single not spell base (scripted) path
|
||
{
|
||
std::set<uint32> spellPaths;
|
||
for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i)
|
||
if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
|
||
for(int j=0; j < MAX_EFFECT_INDEX; ++j)
|
||
if(sInfo->Effect[j]==123 /*SPELL_EFFECT_SEND_TAXI*/)
|
||
spellPaths.insert(sInfo->EffectMiscValue[j]);
|
||
|
||
memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
|
||
memset(sOldContinentsNodesMask,0,sizeof(sTaxiNodesMask));
|
||
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(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;
|
||
|
||
// 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;
|
||
}
|
||
}
|
||
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc");
|
||
LoadDBC(availableDbcLocales,bar,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,bar,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc");
|
||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc");
|
||
|
||
// error checks
|
||
if (bad_dbc_files.size() >= DBCFilesCount )
|
||
{
|
||
sLog.outError("\nIncorrect DataDir value in mangosd.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str());
|
||
Log::WaitBeforeContinueIfNeed();
|
||
exit(1);
|
||
}
|
||
else if (!bad_dbc_files.empty() )
|
||
{
|
||
std::string str;
|
||
for(std::list<std::string>::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i)
|
||
str += *i + "\n";
|
||
|
||
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());
|
||
Log::WaitBeforeContinueIfNeed();
|
||
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 gem property added 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 added spell in 3.3.5a
|
||
{
|
||
sLog.outError("\nYou have mixed version DBC files. Please re-extract DBC files for one from client build: %s",AcceptableClientBuildsListStr().c_str());
|
||
Log::WaitBeforeContinueIfNeed();
|
||
exit(1);
|
||
}
|
||
|
||
sLog.outString();
|
||
sLog.outString( ">> Initialized %d data stores", DBCFilesCount );
|
||
}
|
||
|
||
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
|
||
{
|
||
FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
|
||
if(itr==sFactionTeamMap.end())
|
||
return NULL;
|
||
return &itr->second;
|
||
}
|
||
|
||
char const* 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(TalentSpellPos const* pos)
|
||
{
|
||
if (pos)
|
||
return pos->rank+1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
uint32 GetTalentSpellCost(uint32 spellId)
|
||
{
|
||
return GetTalentSpellCost(GetTalentSpellPos(spellId));
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
|
||
{
|
||
// not sorted, numbering index from 0
|
||
for(uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
|
||
{
|
||
ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
|
||
if(ch && ch->ChannelID == channel_id)
|
||
return ch;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
|
||
{
|
||
if(requiredTotemCategoryId==0)
|
||
return true;
|
||
if(itemTotemCategoryId==0)
|
||
return false;
|
||
|
||
TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId);
|
||
if(!itemEntry)
|
||
return false;
|
||
TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId);
|
||
if(!reqEntry)
|
||
return false;
|
||
|
||
if(itemEntry->categoryType!=reqEntry->categoryType)
|
||
return false;
|
||
|
||
return (itemEntry->categoryMask & reqEntry->categoryMask)==reqEntry->categoryMask;
|
||
}
|
||
|
||
bool Zone2MapCoordinates(float& x,float& y,uint32 zone)
|
||
{
|
||
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
|
||
|
||
// if not listed then map coordinates (instance)
|
||
if (!maEntry || maEntry->x2 == maEntry->x1 || maEntry->y2 == maEntry->y1)
|
||
return false;
|
||
|
||
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
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Map2ZoneCoordinates(float& x,float& y,uint32 zone)
|
||
{
|
||
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
|
||
|
||
// if not listed then map coordinates (instance)
|
||
if (!maEntry || maEntry->x2 == maEntry->x1 || maEntry->y2 == maEntry->y1)
|
||
return false;
|
||
|
||
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
|
||
|
||
return true;
|
||
}
|
||
|
||
MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty)
|
||
{
|
||
MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId,difficulty));
|
||
return itr != sMapDifficultyMap.end() ? &itr->second : NULL;
|
||
}
|
||
|
||
PvPDifficultyEntry const* GetBattlegroundBracketByLevel( uint32 mapid, uint32 level )
|
||
{
|
||
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)
|
||
{
|
||
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 const* GetTalentTabPages(uint32 cls)
|
||
{
|
||
return sTalentTabPages[cls];
|
||
}
|
||
|
||
bool IsPointInAreaTriggerZone(AreaTriggerEntry const* atEntry, uint32 mapid, float x, float y, float z, float delta)
|
||
{
|
||
if (mapid != atEntry->mapid)
|
||
return false;
|
||
|
||
if (atEntry->radius > 0)
|
||
{
|
||
// if we have radius check it
|
||
float dist2 = (x-atEntry->x)*(x-atEntry->x) + (y-atEntry->y)*(y-atEntry->y) + (z-atEntry->z)*(z-atEntry->z);
|
||
if(dist2 > (atEntry->radius + delta)*(atEntry->radius + delta))
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
// we have only extent
|
||
|
||
// rotate the players position instead of rotating the whole cube, that way we can make a simplified
|
||
// is-in-cube check and we have to calculate only one point instead of 4
|
||
|
||
// 2PI = 360 |