server/src/game/DBCStores.cpp
VladimirMangos acd0716297 [10432] Rename ASSERT -> MANGOS_ASSERT and related fixes
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
2010-09-02 05:13:16 +04:00

962 lines
43 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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, keep in mind that ingame orientation is counter-clockwise
double rotation = 2*M_PI-atEntry->box_orientation;
double sinVal = sin(rotation);
double cosVal = cos(rotation);
float playerBoxDistX = x - atEntry->x;
float playerBoxDistY = y - atEntry->y;
float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY*sinVal);
float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX*sinVal);
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = z - atEntry->z;
float dx = rotPlayerX - atEntry->x;
float dy = rotPlayerY - atEntry->y;
if( (fabs(dx) > atEntry->box_x/2 + delta) ||
(fabs(dy) > atEntry->box_y/2 + delta) ||
(fabs(dz) > atEntry->box_z/2 + delta) )
{
return false;
}
}
return true;
}
// script support functions
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; }
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; }
MANGOS_DLL_SPEC DBCStorage <FactionEntry> const* GetFactionStore() { return &sFactionStore; }
MANGOS_DLL_SPEC DBCStorage <ItemEntry> const* GetItemDisplayStore() { return &sItemStore; }
MANGOS_DLL_SPEC DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; }
MANGOS_DLL_SPEC DBCStorage <EmotesEntry> const* GetEmotesStore() { return &sEmotesStore; }
MANGOS_DLL_SPEC DBCStorage <EmotesTextEntry> const* GetEmotesTextStore() { return &sEmotesTextStore; }