SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_) { SkillRaceClassInfoBounds bounds = SkillRaceClassInfoBySkill.equal_range(skill); for (SkillRaceClassInfoMap::iterator itr = bounds.first; itr != bounds.second; ++itr) { if (itr->second->RaceMask && !(itr->second->RaceMask & (1 << (race - 1)))) continue; if (itr->second->ClassMask && !(itr->second->ClassMask & (1 << (class_ - 1)))) continue; return itr->second; } return nullptr; }
void LoadDBCStores(const std::string& dataPath) { uint32 oldMSTime = getMSTime(); std::string dbcPath = dataPath+"dbc/"; StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; LoadDBC(availableDbcLocales, 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, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex); LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaPOIStore, dbcPath, "AreaPOI.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAuctionHouseStore, dbcPath, "AuctionHouse.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBankBagSlotPricesStore, dbcPath, "BankBagSlotPrices.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBannedAddOnsStore, dbcPath, "BannedAddOns.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBattlemasterListStore, dbcPath, "BattlemasterList.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sBarberShopStyleStore, dbcPath, "BarberShopStyle.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCharStartOutfitStore, dbcPath, "CharStartOutfit.dbc"); for (uint32 i = 0; i < sCharStartOutfitStore.GetNumRows(); ++i) if (CharStartOutfitEntry const* outfit = sCharStartOutfitStore.LookupEntry(i)) sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit; LoadDBC(availableDbcLocales, bad_dbc_files, sCharSectionsStore, dbcPath, "CharSections.dbc"); for (uint32 i = 0; i < sCharSectionsStore.GetNumRows(); ++i) if (CharSectionsEntry const* entry = sCharSectionsStore.LookupEntry(i)) if (entry->Race && ((1 << (entry->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) //ignore Nonplayable races sCharSectionMap.insert({ entry->GenType | (entry->Gender << 8) | (entry->Race << 16), entry }); LoadDBC(availableDbcLocales, bad_dbc_files, sCharTitlesStore, dbcPath, "CharTitles.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoExtraStore, dbcPath, "CreatureDisplayInfoExtra.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureFamilyStore, dbcPath, "CreatureFamily.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureModelDataStore, dbcPath, "CreatureModelData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureSpellDataStore, dbcPath, "CreatureSpellData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureTypeStore, dbcPath, "CreatureType.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc"); for (uint32 i=0; 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, bad_dbc_files, sFactionTemplateStore, dbcPath, "FactionTemplate.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGameObjectDisplayInfoStore, dbcPath, "GameObjectDisplayInfo.dbc"); for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i) { if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i)) { if (info->maxX < info->minX) std::swap(*(float*)(&info->maxX), *(float*)(&info->minX)); if (info->maxY < info->minY) std::swap(*(float*)(&info->maxY), *(float*)(&info->minY)); if (info->maxZ < info->minZ) std::swap(*(float*)(&info->maxZ), *(float*)(&info->minZ)); } } LoadDBC(availableDbcLocales, bad_dbc_files, sGemPropertiesStore, dbcPath, "GemProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphPropertiesStore, dbcPath, "GlyphProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGlyphSlotStore, dbcPath, "GlyphSlot.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtBarberShopCostBaseStore, dbcPath, "gtBarberShopCostBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtCombatRatingsStore, dbcPath, "gtCombatRatings.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritBaseStore, dbcPath, "gtChanceToMeleeCritBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToMeleeCritStore, dbcPath, "gtChanceToMeleeCrit.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritBaseStore, dbcPath, "gtChanceToSpellCritBase.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtChanceToSpellCritStore, dbcPath, "gtChanceToSpellCrit.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtNPCManaCostScalerStore, dbcPath, "gtNPCManaCostScaler.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTClassCombatRatingScalarStore, dbcPath, "gtOCTClassCombatRatingScalar.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtOCTRegenHPStore, dbcPath, "gtOCTRegenHP.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sGtOCTRegenMPStore, dbcPath, "gtOCTRegenMP.dbc"); -- not used currently LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenHPPerSptStore, dbcPath, "gtRegenHPPerSpt.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sGtRegenMPPerSptStore, dbcPath, "gtRegenMPPerSpt.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemStore, dbcPath, "Item.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); -- not used currently //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemExtendedCostStore, dbcPath, "ItemExtendedCost.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc"); // fill data for (uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i) if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0'); sMapDifficultyStore.Clear(); LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc"); for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillRaceClassInfoStore, dbcPath, "SkillRaceClassInfo.dbc"); for (uint32 i = 0; i < sSkillRaceClassInfoStore.GetNumRows(); ++i) if (SkillRaceClassInfoEntry const* entry = sSkillRaceClassInfoStore.LookupEntry(i)) if (sSkillLineStore.LookupEntry(entry->SkillId)) SkillRaceClassInfoBySkill.emplace(entry->SkillId, entry); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc", &CustomSpellEntryfmt, &CustomSpellEntryIndex); for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { SpellEntry const* spell = sSpellStore.LookupEntry(i); if (spell && spell->Category) sSpellsByCategoryStore[spell->Category].insert(i); } for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); if (!skillLine) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) { for (uint32 i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) { CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); if (!cFamily) continue; if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; if (spellInfo->spellLevel) continue; if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; sPetFamilySpellsStore[i].insert(spellInfo->Id); } } } LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoryStore, dbcPath, "SpellCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDifficultyStore, dbcPath, "SpellDifficulty.dbc", &CustomSpellDifficultyfmt, &CustomSpellDifficultyIndex); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRangeStore, dbcPath, "SpellRange.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRuneCostStore, dbcPath, "SpellRuneCost.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshiftForm.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc"); // Create Spelldifficulty searcher for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i) { SpellDifficultyEntry const* spellDiff = sSpellDifficultyStore.LookupEntry(i); if (!spellDiff) continue; SpellDifficultyEntry newEntry; memset(newEntry.SpellID, 0, 4*sizeof(uint32)); for (int x = 0; x < MAX_DIFFICULTY; ++x) { if (spellDiff->SpellID[x] <= 0 || !sSpellStore.LookupEntry(spellDiff->SpellID[x])) { if (spellDiff->SpellID[x] > 0)//don't show error if spell is <= 0, not all modes have spells and there are unknown negative values TC_LOG_ERROR("sql.sql", "spelldifficulty_dbc: spell %i at field id:%u at spellid%i does not exist in SpellStore (spell.dbc), loaded as 0", spellDiff->SpellID[x], spellDiff->ID, x); newEntry.SpellID[x] = 0;//spell was <= 0 or invalid, set to 0 } else newEntry.SpellID[x] = spellDiff->SpellID[x]; } if (newEntry.SpellID[0] <= 0 || newEntry.SpellID[1] <= 0)//id0-1 must be always set! continue; for (int x = 0; x < MAX_DIFFICULTY; ++x) if (newEntry.SpellID[x]) sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); } // create talent spells set for (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, 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 for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) if (talentTabInfo->ClassMask & (1 << (cls - 1))) sTalentTabPages[cls][talentTabInfo->tabpage] = talentTabId; } } LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc"); for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price); uint32 pathCount = sTaxiPathStore.GetNumRows(); //## TaxiPathNode.dbc ## Loaded only for initialization different structures LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathNodeStore, dbcPath, "TaxiPathNode.dbc"); // Calculate path nodes count std::vector<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->PathID] < entry->NodeIndex + 1) pathLength[entry->PathID] = entry->NodeIndex + 1; } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for (uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); // fill data for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) sTaxiPathNodesByPath[entry->PathID].set(entry->NodeIndex, entry); // Initialize global taxinodes mask // include existed 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_SPELL_EFFECTS; ++j) if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue[j]); memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask)); memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask)); memset(sHordeTaxiNodesMask, 0, sizeof(sHordeTaxiNodesMask)); memset(sAllianceTaxiNodesMask, 0, sizeof(sAllianceTaxiNodesMask)); memset(sDeathKnightTaxiNodesMask, 0, sizeof(sDeathKnightTaxiNodesMask)); for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); if (!node) continue; TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i); if (src_i != sTaxiPathSetBySource.end() && !src_i->second.empty()) { bool ok = false; for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i) { // not spell path if (spellPaths.find(dest_i->second.ID) == spellPaths.end()) { ok = true; break; } } if (!ok) continue; } // valid taxi network node uint8 field = (uint8)((i - 1) / 32); uint32 submask = 1<<((i-1)%32); sTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981) sHordeTaxiNodesMask[field] |= submask; if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981) sAllianceTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981) sDeathKnightTaxiNodesMask[field] |= submask; // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info) if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94) sOldContinentsNodesMask[field] |= submask; // fix DK node at Ebon Hold and Shadow Vault flight master if (i == 315 || i == 333) ((TaxiNodesEntry*)node)->MountCreatureID[1] = 32981; } } LoadDBC(availableDbcLocales, bad_dbc_files, sTeamContributionPointsStore, dbcPath, "TeamContributionPoints.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTotemCategoryStore, dbcPath, "TotemCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sTransportAnimationStore, dbcPath, "TransportAnimation.dbc"); for (uint32 i = 0; i < sTransportAnimationStore.GetNumRows(); ++i) { TransportAnimationEntry const* anim = sTransportAnimationStore.LookupEntry(i); if (!anim) continue; sTransportMgr->AddPathNodeToTransport(anim->TransportEntry, anim->TimeSeg, anim); } LoadDBC(availableDbcLocales, bad_dbc_files, sTransportRotationStore, dbcPath, "TransportRotation.dbc"); for (uint32 i = 0; i < sTransportRotationStore.GetNumRows(); ++i) { TransportRotationEntry const* rot = sTransportRotationStore.LookupEntry(i); if (!rot) continue; sTransportMgr->AddPathRotationToTransport(rot->TransportEntry, rot->TimeSeg, rot); } LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleStore, dbcPath, "Vehicle.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sVehicleSeatStore, dbcPath, "VehicleSeat.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWMOAreaTableStore, dbcPath, "WMOAreaTable.dbc"); for (uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i) if (WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i)) sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry)); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc"); // error checks if (bad_dbc_files.size() >= DBCFileCount) { TC_LOG_ERROR("misc", "Incorrect DataDir value in worldserver.conf or ALL required *.dbc files (%d) not found by path: %sdbc", DBCFileCount, dataPath.c_str()); exit(1); } else if (!bad_dbc_files.empty()) { std::string str; for (StoreProblemList::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) str += *i + "\n"; TC_LOG_ERROR("misc", "Some required *.dbc files (%u from %d) not found or not compatible:\n%s", (uint32)bad_dbc_files.size(), DBCFileCount, str.c_str()); exit(1); } // Check loaded DBC files proper version if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) added in 3.3.5a !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a !sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a !sItemStore.LookupEntry(56806) || // last gem property added in 3.3.5a !sItemExtendedCostStore.LookupEntry(2997) || // last item extended cost added in 3.3.5a !sMapStore.LookupEntry(724) || // last map added in 3.3.5a !sSpellStore.LookupEntry(80864) ) // last client known item added in 3.3.5a { TC_LOG_ERROR("misc", "You have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); }
void LoadDBCStores(const std::string& dataPath) { uint32 oldMSTime = getMSTime(); std::string dbcPath = dataPath + "dbc/"; StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; #define LOAD_DBC(store, file) LoadDBC(availableDbcLocales, bad_dbc_files, store, dbcPath, file) LOAD_DBC(sAreaTableStore, "AreaTable.dbc"); LOAD_DBC(sAchievementCriteriaStore, "Achievement_Criteria.dbc"); LOAD_DBC(sAreaTriggerStore, "AreaTrigger.dbc"); LOAD_DBC(sAreaGroupStore, "AreaGroup.dbc"); LOAD_DBC(sAreaPOIStore, "AreaPOI.dbc"); LOAD_DBC(sAuctionHouseStore, "AuctionHouse.dbc"); LOAD_DBC(sBankBagSlotPricesStore, "BankBagSlotPrices.dbc"); LOAD_DBC(sBannedAddOnsStore, "BannedAddOns.dbc"); LOAD_DBC(sBattlemasterListStore, "BattlemasterList.dbc"); LOAD_DBC(sBarberShopStyleStore, "BarberShopStyle.dbc"); LOAD_DBC(sCharacterFacialHairStylesStore, "CharacterFacialHairStyles.dbc"); LOAD_DBC(sCharSectionsStore, "CharSections.dbc"); LOAD_DBC(sCharStartOutfitStore, "CharStartOutfit.dbc"); LOAD_DBC(sCharTitlesStore, "CharTitles.dbc"); LOAD_DBC(sChatChannelsStore, "ChatChannels.dbc"); LOAD_DBC(sChrClassesStore, "ChrClasses.dbc"); LOAD_DBC(sChrRacesStore, "ChrRaces.dbc"); LOAD_DBC(sCinematicCameraStore, "CinematicCamera.dbc"); LOAD_DBC(sCinematicSequencesStore, "CinematicSequences.dbc"); LOAD_DBC(sCreatureDisplayInfoStore, "CreatureDisplayInfo.dbc"); LOAD_DBC(sCreatureDisplayInfoExtraStore, "CreatureDisplayInfoExtra.dbc"); LOAD_DBC(sCreatureFamilyStore, "CreatureFamily.dbc"); LOAD_DBC(sCreatureModelDataStore, "CreatureModelData.dbc"); LOAD_DBC(sCreatureSpellDataStore, "CreatureSpellData.dbc"); LOAD_DBC(sCreatureTypeStore, "CreatureType.dbc"); LOAD_DBC(sCurrencyTypesStore, "CurrencyTypes.dbc"); LOAD_DBC(sDestructibleModelDataStore, "DestructibleModelData.dbc"); LOAD_DBC(sDungeonEncounterStore, "DungeonEncounter.dbc"); LOAD_DBC(sDurabilityCostsStore, "DurabilityCosts.dbc"); LOAD_DBC(sDurabilityQualityStore, "DurabilityQuality.dbc"); LOAD_DBC(sEmotesStore, "Emotes.dbc"); LOAD_DBC(sEmotesTextStore, "EmotesText.dbc"); LOAD_DBC(sEmotesTextSoundStore, "EmotesTextSound.dbc"); LOAD_DBC(sFactionStore, "Faction.dbc"); LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc"); LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc"); LOAD_DBC(sGemPropertiesStore, "GemProperties.dbc"); LOAD_DBC(sGlyphPropertiesStore, "GlyphProperties.dbc"); LOAD_DBC(sGlyphSlotStore, "GlyphSlot.dbc"); LOAD_DBC(sGtBarberShopCostBaseStore, "gtBarberShopCostBase.dbc"); LOAD_DBC(sGtCombatRatingsStore, "gtCombatRatings.dbc"); LOAD_DBC(sGtChanceToMeleeCritBaseStore, "gtChanceToMeleeCritBase.dbc"); LOAD_DBC(sGtChanceToMeleeCritStore, "gtChanceToMeleeCrit.dbc"); LOAD_DBC(sGtChanceToSpellCritBaseStore, "gtChanceToSpellCritBase.dbc"); LOAD_DBC(sGtChanceToSpellCritStore, "gtChanceToSpellCrit.dbc"); LOAD_DBC(sGtNPCManaCostScalerStore, "gtNPCManaCostScaler.dbc"); LOAD_DBC(sGtOCTClassCombatRatingScalarStore, "gtOCTClassCombatRatingScalar.dbc"); LOAD_DBC(sGtOCTRegenHPStore, "gtOCTRegenHP.dbc"); //LOAD_DBC(sGtOCTRegenMPStore, "gtOCTRegenMP.dbc"); -- not used currently LOAD_DBC(sGtRegenHPPerSptStore, "gtRegenHPPerSpt.dbc"); LOAD_DBC(sGtRegenMPPerSptStore, "gtRegenMPPerSpt.dbc"); LOAD_DBC(sHolidaysStore, "Holidays.dbc"); LOAD_DBC(sItemStore, "Item.dbc"); LOAD_DBC(sItemBagFamilyStore, "ItemBagFamily.dbc"); //LOAD_DBC(sItemDisplayInfoStore, "ItemDisplayInfo.dbc"); -- not used currently //LOAD_DBC(sItemCondExtCostsStore, "ItemCondExtCosts.dbc"); LOAD_DBC(sItemExtendedCostStore, "ItemExtendedCost.dbc"); LOAD_DBC(sItemLimitCategoryStore, "ItemLimitCategory.dbc"); LOAD_DBC(sItemRandomPropertiesStore, "ItemRandomProperties.dbc"); LOAD_DBC(sItemRandomSuffixStore, "ItemRandomSuffix.dbc"); LOAD_DBC(sItemSetStore, "ItemSet.dbc"); LOAD_DBC(sLFGDungeonStore, "LFGDungeons.dbc"); LOAD_DBC(sLightStore, "Light.dbc"); LOAD_DBC(sLiquidTypeStore, "LiquidType.dbc"); LOAD_DBC(sLockStore, "Lock.dbc"); LOAD_DBC(sMailTemplateStore, "MailTemplate.dbc"); LOAD_DBC(sMapStore, "Map.dbc"); LOAD_DBC(sMapDifficultyStore, "MapDifficulty.dbc"); LOAD_DBC(sMovieStore, "Movie.dbc"); LOAD_DBC(sNamesProfanityStore, "NamesProfanity.dbc"); LOAD_DBC(sNamesReservedStore, "NamesReserved.dbc"); LOAD_DBC(sOverrideSpellDataStore, "OverrideSpellData.dbc"); LOAD_DBC(sPowerDisplayStore, "PowerDisplay.dbc"); LOAD_DBC(sPvPDifficultyStore, "PvpDifficulty.dbc"); LOAD_DBC(sQuestXPStore, "QuestXP.dbc"); LOAD_DBC(sQuestFactionRewardStore, "QuestFactionReward.dbc"); LOAD_DBC(sQuestSortStore, "QuestSort.dbc"); LOAD_DBC(sRandomPropertiesPointsStore, "RandPropPoints.dbc"); LOAD_DBC(sScalingStatDistributionStore, "ScalingStatDistribution.dbc"); LOAD_DBC(sScalingStatValuesStore, "ScalingStatValues.dbc"); LOAD_DBC(sSkillLineStore, "SkillLine.dbc"); LOAD_DBC(sSkillLineAbilityStore, "SkillLineAbility.dbc"); LOAD_DBC(sSkillRaceClassInfoStore, "SkillRaceClassInfo.dbc"); LOAD_DBC(sSkillTiersStore, "SkillTiers.dbc"); LOAD_DBC(sSoundEntriesStore, "SoundEntries.dbc"); LOAD_DBC(sSpellCastTimesStore, "SpellCastTimes.dbc"); LOAD_DBC(sSpellCategoryStore, "SpellCategory.dbc"); LOAD_DBC(sSpellDurationStore, "SpellDuration.dbc"); LOAD_DBC(sSpellFocusObjectStore, "SpellFocusObject.dbc"); LOAD_DBC(sSpellItemEnchantmentStore, "SpellItemEnchantment.dbc"); LOAD_DBC(sSpellItemEnchantmentConditionStore, "SpellItemEnchantmentCondition.dbc"); LOAD_DBC(sSpellRadiusStore, "SpellRadius.dbc"); LOAD_DBC(sSpellRangeStore, "SpellRange.dbc"); LOAD_DBC(sSpellRuneCostStore, "SpellRuneCost.dbc"); LOAD_DBC(sSpellShapeshiftStore, "SpellShapeshiftForm.dbc"); LOAD_DBC(sStableSlotPricesStore, "StableSlotPrices.dbc"); LOAD_DBC(sSummonPropertiesStore, "SummonProperties.dbc"); LOAD_DBC(sTalentStore, "Talent.dbc"); LOAD_DBC(sTalentTabStore, "TalentTab.dbc"); LOAD_DBC(sTaxiNodesStore, "TaxiNodes.dbc"); LOAD_DBC(sTaxiPathStore, "TaxiPath.dbc"); LOAD_DBC(sTaxiPathNodeStore, "TaxiPathNode.dbc"); LOAD_DBC(sTeamContributionPointsStore, "TeamContributionPoints.dbc"); LOAD_DBC(sTotemCategoryStore, "TotemCategory.dbc"); LOAD_DBC(sTransportAnimationStore, "TransportAnimation.dbc"); LOAD_DBC(sTransportRotationStore, "TransportRotation.dbc"); LOAD_DBC(sVehicleStore, "Vehicle.dbc"); LOAD_DBC(sVehicleSeatStore, "VehicleSeat.dbc"); LOAD_DBC(sWMOAreaTableStore, "WMOAreaTable.dbc"); LOAD_DBC(sWorldMapAreaStore, "WorldMapArea.dbc"); LOAD_DBC(sWorldMapOverlayStore, "WorldMapOverlay.dbc"); LOAD_DBC(sWorldSafeLocsStore, "WorldSafeLocs.dbc"); #undef LOAD_DBC #define LOAD_DBC_EXT(store, file, dbtable, dbformat, dbpk) LoadDBC(availableDbcLocales, bad_dbc_files, store, dbcPath, file, dbtable, dbformat, dbpk) LOAD_DBC_EXT(sAchievementStore, "Achievement.dbc", "achievement_dbc", CustomAchievementfmt, CustomAchievementIndex); LOAD_DBC_EXT(sSpellStore, "Spell.dbc", "spell_dbc", CustomSpellEntryfmt, CustomSpellEntryIndex); LOAD_DBC_EXT(sSpellDifficultyStore, "SpellDifficulty.dbc", "spelldifficulty_dbc", CustomSpellDifficultyfmt, CustomSpellDifficultyIndex); #undef LOAD_DBC_EXT for (CharacterFacialHairStylesEntry const* entry : sCharacterFacialHairStylesStore) if (entry->Race && ((1 << (entry->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) // ignore nonplayable races sCharFacialHairMap.insert({ entry->Race | (entry->Gender << 8) | (entry->Variation << 16), entry }); for (CharSectionsEntry const* entry : sCharSectionsStore) if (entry->Race && ((1 << (entry->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) // ignore nonplayable races sCharSectionMap.insert({ entry->GenType | (entry->Gender << 8) | (entry->Race << 16), entry }); for (CharStartOutfitEntry const* outfit : sCharStartOutfitStore) sCharStartOutfitMap[outfit->Race | (outfit->Class << 8) | (outfit->Gender << 16)] = outfit; for (EmotesTextSoundEntry const* entry : sEmotesTextSoundStore) sEmotesTextSoundMap[EmotesTextSoundKey(entry->EmotesTextId, entry->RaceId, entry->SexId)] = entry; for (FactionEntry const* faction : sFactionStore) { if (faction->team) { SimpleFactionsList& flist = sFactionTeamMap[faction->team]; flist.push_back(faction->ID); } } for (GameObjectDisplayInfoEntry const* info : sGameObjectDisplayInfoStore) { if (info->maxX < info->minX) std::swap(*(float*)(&info->maxX), *(float*)(&info->minX)); if (info->maxY < info->minY) std::swap(*(float*)(&info->maxY), *(float*)(&info->minY)); if (info->maxZ < info->minZ) std::swap(*(float*)(&info->maxZ), *(float*)(&info->minZ)); } // fill data for (MapDifficultyEntry const* entry : sMapDifficultyStore) sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0'); for (NamesProfanityEntry const* namesProfanity : sNamesProfanityStore) { ASSERT(namesProfanity->Language < TOTAL_LOCALES || namesProfanity->Language == -1); std::wstring wname; bool conversionResult = Utf8toWStr(namesProfanity->Name, wname); ASSERT(conversionResult); if (namesProfanity->Language != -1) NamesProfaneValidators[namesProfanity->Language].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize); else for (uint32 i = 0; i < TOTAL_LOCALES; ++i) NamesProfaneValidators[i].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize); } for (NamesReservedEntry const* namesReserved : sNamesReservedStore) { ASSERT(namesReserved->Language < TOTAL_LOCALES || namesReserved->Language == -1); std::wstring wname; bool conversionResult = Utf8toWStr(namesReserved->Name, wname); ASSERT(conversionResult); if (namesReserved->Language != -1) NamesReservedValidators[namesReserved->Language].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize); else for (uint32 i = 0; i < TOTAL_LOCALES; ++i) NamesReservedValidators[i].emplace_back(wname, Trinity::regex::perl | Trinity::regex::icase | Trinity::regex::optimize); } for (PvPDifficultyEntry const* entry : sPvPDifficultyStore) { ASSERT(entry->bracketId < MAX_BATTLEGROUND_BRACKETS, "PvpDifficulty bracket (%d) exceeded max allowed value (%d)", entry->bracketId, MAX_BATTLEGROUND_BRACKETS); } for (SkillRaceClassInfoEntry const* entry : sSkillRaceClassInfoStore) if (sSkillLineStore.LookupEntry(entry->SkillId)) SkillRaceClassInfoBySkill.emplace(entry->SkillId, entry); for (SkillLineAbilityEntry const* skillLine : sSkillLineAbilityStore) { SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) { for (CreatureFamilyEntry const* cFamily : sCreatureFamilyStore) { if (skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; if (spellInfo->spellLevel) continue; if (skillLine->AutolearnType != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) continue; sPetFamilySpellsStore[cFamily->ID].insert(spellInfo->Id); } } } // Create Spelldifficulty searcher for (SpellDifficultyEntry const* spellDiff : sSpellDifficultyStore) { SpellDifficultyEntry newEntry; memset(newEntry.SpellID, 0, 4*sizeof(uint32)); for (uint8 x = 0; x < MAX_DIFFICULTY; ++x) { if (spellDiff->SpellID[x] <= 0 || !sSpellStore.LookupEntry(spellDiff->SpellID[x])) { if (spellDiff->SpellID[x] > 0)//don't show error if spell is <= 0, not all modes have spells and there are unknown negative values TC_LOG_ERROR("sql.sql", "spelldifficulty_dbc: spell %i at field id:%u at spellid%i does not exist in SpellStore (spell.dbc), loaded as 0", spellDiff->SpellID[x], spellDiff->ID, x); newEntry.SpellID[x] = 0;//spell was <= 0 or invalid, set to 0 } else newEntry.SpellID[x] = spellDiff->SpellID[x]; } if (newEntry.SpellID[0] <= 0 || newEntry.SpellID[1] <= 0)//id0-1 must be always set! continue; for (uint8 x = 0; x < MAX_DIFFICULTY; ++x) if (newEntry.SpellID[x]) sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); } // create talent spells set for (TalentEntry const* talentInfo : sTalentStore) { for (uint8 j = 0; j < MAX_TALENT_RANK; ++j) if (talentInfo->RankID[j]) sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(talentInfo->TalentID, j); } // prepare fast data access to bit pos of talent ranks for use at inspecting { // now have all max ranks (and then bit amount used for store talent ranks in inspect) for (TalentTabEntry const* talentTabInfo : sTalentTabStore) { // prevent memory corruption; otherwise cls will become 12 below if ((talentTabInfo->ClassMask & CLASSMASK_ALL_PLAYABLE) == 0) continue; // store class talent tab pages for (uint32 cls = 1; cls < MAX_CLASSES; ++cls) if (talentTabInfo->ClassMask & (1 << (cls - 1))) sTalentTabPages[cls][talentTabInfo->tabpage] = talentTabInfo->TalentTabID; } } for (TaxiPathEntry const* entry : sTaxiPathStore) sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price); uint32 pathCount = sTaxiPathStore.GetNumRows(); // Calculate path nodes count std::vector<uint32> pathLength; pathLength.resize(pathCount); // 0 and some other indexes not used for (TaxiPathNodeEntry const* entry : sTaxiPathNodeStore) { if (pathLength[entry->PathID] < entry->NodeIndex + 1) pathLength[entry->PathID] = entry->NodeIndex + 1; } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for (uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); // fill data for (TaxiPathNodeEntry const* entry : sTaxiPathNodeStore) sTaxiPathNodesByPath[entry->PathID][entry->NodeIndex] = entry; // Initialize global taxinodes mask // include existed nodes that have at least single not spell base (scripted) path { std::set<uint32> spellPaths; for (SpellEntry const* sInfo : sSpellStore) for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue[j]); sTaxiNodesMask.fill(0); sOldContinentsNodesMask.fill(0); sHordeTaxiNodesMask.fill(0); sAllianceTaxiNodesMask.fill(0); sDeathKnightTaxiNodesMask.fill(0); for (TaxiNodesEntry const* node : sTaxiNodesStore) { TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(node->ID); if (src_i != sTaxiPathSetBySource.end() && !src_i->second.empty()) { bool ok = false; for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i) { // not spell path if (dest_i->second.price || spellPaths.find(dest_i->second.ID) == spellPaths.end()) { ok = true; break; } } if (!ok) continue; } // valid taxi network node uint8 field = (uint8)((node->ID - 1) / 32); uint32 submask = 1 << ((node->ID - 1) % 32); sTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981) sHordeTaxiNodesMask[field] |= submask; if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981) sAllianceTaxiNodesMask[field] |= submask; if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981) sDeathKnightTaxiNodesMask[field] |= submask; // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info) if (node->map_id < 2 || node->ID == 82 || node->ID == 83 || node->ID == 93 || node->ID == 94) sOldContinentsNodesMask[field] |= submask; // fix DK node at Ebon Hold and Shadow Vault flight master if (node->ID == 315 || node->ID == 333) const_cast<TaxiNodesEntry*>(node)->MountCreatureID[1] = 32981; } } for (WMOAreaTableEntry const* entry : sWMOAreaTableStore) sWMOAreaInfoByTripple[WMOAreaTableKey(entry->rootId, entry->adtId, entry->groupId)] = entry; // error checks if (bad_dbc_files.size() >= DBCFileCount) { TC_LOG_ERROR("misc", "Incorrect DataDir value in worldserver.conf or ALL required *.dbc files (%d) not found by path: %sdbc", DBCFileCount, dataPath.c_str()); exit(1); } else if (!bad_dbc_files.empty()) { std::string str; for (StoreProblemList::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) str += *i + "\n"; TC_LOG_ERROR("misc", "Some required *.dbc files (%u from %d) not found or not compatible:\n%s", (uint32)bad_dbc_files.size(), DBCFileCount, str.c_str()); exit(1); } // Check loaded DBC files proper version if (!sAreaTableStore.LookupEntry(4987) || // last area added in 3.3.5a !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a !sGemPropertiesStore.LookupEntry(1629) || // last 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 { TC_LOG_ERROR("misc", "You have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); }
void LoadDBCStores(const std::string& dataPath) { uint32 oldMSTime = getMSTime(); std::string dbcPath = dataPath+"dbc/"; StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; #define LOAD_DBC(store, file) LoadDBC(availableDbcLocales, bad_dbc_files, store, dbcPath, file) LOAD_DBC(sAchievementStore, "Achievement.dbc"/*, &CustomAchievementfmt, &CustomAchievementIndex*/);//20201 LOAD_DBC(sAnimKitStore, "AnimKit.dbc");//20201 LOAD_DBC(sAreaStore, "AreaTable.dbc");//20201 LOAD_DBC(sAreaTriggerStore, "AreaTrigger.dbc");//20201 LOAD_DBC(sArmorLocationStore, "ArmorLocation.dbc");//20201 LOAD_DBC(sBankBagSlotPricesStore, "BankBagSlotPrices.dbc");//20201 LOAD_DBC(sBannedAddOnsStore, "BannedAddOns.dbc");//20201 LOAD_DBC(sBattlemasterListStore, "BattlemasterList.dbc");//20201 LOAD_DBC(sCharSectionsStore, "CharSections.dbc");//20201 LOAD_DBC(sCharTitlesStore, "CharTitles.dbc");//20201 LOAD_DBC(sChatChannelsStore, "ChatChannels.dbc");//20201 LOAD_DBC(sChrClassesStore, "ChrClasses.dbc");//20201 LOAD_DBC(sChrRacesStore, "ChrRaces.dbc");//20201 LOAD_DBC(sChrSpecializationStore, "ChrSpecialization.dbc");//20201 LOAD_DBC(sCreatureDisplayInfoExtraStore, "CreatureDisplayInfoExtra.dbc");//20201 LOAD_DBC(sCreatureFamilyStore, "CreatureFamily.dbc");//20201 LOAD_DBC(sCreatureModelDataStore, "CreatureModelData.dbc");//20201 LOAD_DBC(sCriteriaStore, "Criteria.dbc");//20201 LOAD_DBC(sCriteriaTreeStore, "CriteriaTree.dbc");//20201 LOAD_DBC(sDifficultyStore, "Difficulty.dbc");//20201 LOAD_DBC(sDungeonEncounterStore, "DungeonEncounter.dbc");//20201 LOAD_DBC(sDurabilityCostsStore, "DurabilityCosts.dbc");//20201 LOAD_DBC(sEmotesStore, "Emotes.dbc");//20201 LOAD_DBC(sEmotesTextStore, "EmotesText.dbc");//20201 LOAD_DBC(sFactionStore, "Faction.dbc");//20201 LOAD_DBC(sFactionTemplateStore, "FactionTemplate.dbc");//20201 LOAD_DBC(sGameObjectDisplayInfoStore, "GameObjectDisplayInfo.dbc");//20201 LOAD_DBC(sGemPropertiesStore, "GemProperties.dbc");//20201 LOAD_DBC(sGlyphPropertiesStore, "GlyphProperties.dbc");//20201 LOAD_DBC(sGuildColorBackgroundStore, "GuildColorBackground.dbc");//20201 LOAD_DBC(sGuildColorBorderStore, "GuildColorBorder.dbc"); //20201 LOAD_DBC(sGuildColorEmblemStore, "GuildColorEmblem.dbc");//20201 LOAD_DBC(sItemArmorQualityStore, "ItemArmorQuality.dbc");//20201 LOAD_DBC(sItemArmorShieldStore, "ItemArmorShield.dbc");//20201 LOAD_DBC(sItemArmorTotalStore, "ItemArmorTotal.dbc");//20201 LOAD_DBC(sItemBagFamilyStore, "ItemBagFamily.dbc");//20201 LOAD_DBC(sItemDamageAmmoStore, "ItemDamageAmmo.dbc");//20201 LOAD_DBC(sItemDamageOneHandCasterStore, "ItemDamageOneHandCaster.dbc");//20201 LOAD_DBC(sItemDamageOneHandStore, "ItemDamageOneHand.dbc");//20201 LOAD_DBC(sItemDamageRangedStore, "ItemDamageRanged.dbc");//20201 LOAD_DBC(sItemDamageThrownStore, "ItemDamageThrown.dbc");//20201 LOAD_DBC(sItemDamageTwoHandCasterStore, "ItemDamageTwoHandCaster.dbc");//20201 LOAD_DBC(sItemDamageTwoHandStore, "ItemDamageTwoHand.dbc");//20201 LOAD_DBC(sItemDamageWandStore, "ItemDamageWand.dbc");//20201 LOAD_DBC(sItemSetSpellStore, "ItemSetSpell.dbc");//20201 LOAD_DBC(sItemSetStore, "ItemSet.dbc");//20201 LOAD_DBC(sLFGDungeonStore, "LfgDungeons.dbc");//20201 LOAD_DBC(sLightStore, "Light.dbc"); //20201 LOAD_DBC(sLiquidTypeStore, "LiquidType.dbc");//20201 LOAD_DBC(sLockStore, "Lock.dbc");//20201 LOAD_DBC(sMapDifficultyStore, "MapDifficulty.dbc");//20201 LOAD_DBC(sMapStore, "Map.dbc");//20201 LOAD_DBC(sModifierTreeStore, "ModifierTree.dbc");//20201 LOAD_DBC(sMovieStore, "Movie.dbc");//20201 LOAD_DBC(sPhaseStore, "Phase.dbc"); // 20201 LOAD_DBC(sPowerDisplayStore, "PowerDisplay.dbc");//20201 LOAD_DBC(sPvPDifficultyStore, "PvpDifficulty.dbc");//20201 LOAD_DBC(sQuestFactionRewardStore, "QuestFactionReward.dbc");//20201 LOAD_DBC(sRandomPropertiesPointsStore, "RandPropPoints.dbc");//20201 LOAD_DBC(sSkillLineAbilityStore, "SkillLineAbility.dbc");//20201 LOAD_DBC(sSkillLineStore, "SkillLine.dbc");//20201 LOAD_DBC(sSkillRaceClassInfoStore, "SkillRaceClassInfo.dbc");//20201 LOAD_DBC(sSpellAuraOptionsStore, "SpellAuraOptions.dbc");//20201 LOAD_DBC(sSpellCategoriesStore, "SpellCategories.dbc");//20201 LOAD_DBC(sSpellCategoryStore, "SpellCategory.dbc");//20201 LOAD_DBC(sSpellCooldownsStore, "SpellCooldowns.dbc");//20201 LOAD_DBC(sSpellEffectScalingStore, "SpellEffectScaling.dbc");//20201 LOAD_DBC(sSpellEffectStore, "SpellEffect.dbc"/*, &CustomSpellEffectEntryfmt, &CustomSpellEffectEntryIndex*/);//20201 LOAD_DBC(sSpellEquippedItemsStore, "SpellEquippedItems.dbc");//20201 LOAD_DBC(sSpellFocusObjectStore, "SpellFocusObject.dbc");//20201 LOAD_DBC(sSpellInterruptsStore, "SpellInterrupts.dbc");//20201 LOAD_DBC(sSpellItemEnchantmentStore, "SpellItemEnchantment.dbc");//20201 LOAD_DBC(sSpellLevelsStore, "SpellLevels.dbc");//20201 LOAD_DBC(sSpellScalingStore, "SpellScaling.dbc");//20201 LOAD_DBC(sSpellShapeshiftFormStore, "SpellShapeshiftForm.dbc");//20201 LOAD_DBC(sSpellShapeshiftStore, "SpellShapeshift.dbc");//20201 LOAD_DBC(sSpellStore, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/);//20201 LOAD_DBC(sSpellTargetRestrictionsStore, "SpellTargetRestrictions.dbc");//20201 LOAD_DBC(sSummonPropertiesStore, "SummonProperties.dbc");//20201 LOAD_DBC(sTalentStore, "Talent.dbc");//20201 LOAD_DBC(sVehicleSeatStore, "VehicleSeat.dbc");//20201 LOAD_DBC(sVehicleStore, "Vehicle.dbc");//20201 LOAD_DBC(sWMOAreaTableStore, "WMOAreaTable.dbc");//20201 LOAD_DBC(sWorldMapAreaStore, "WorldMapArea.dbc");//20201 LOAD_DBC(sWorldSafeLocsStore, "WorldSafeLocs.dbc"); // 20201 #undef LOAD_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->AreaBit)); // fill MapId->DBC records (skip sub zones and continents) if (area->ParentAreaID == 0) sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->MapID, area->AreaBit)); } } for (uint32 i = 0; i < sCharSectionsStore.GetNumRows(); ++i) if (CharSectionsEntry const* entry = sCharSectionsStore.LookupEntry(i)) if (entry->Race && ((1 << (entry->Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0) //ignore Nonplayable races sCharSectionMap.insert({ entry->GenType | (entry->Gender << 8) | (entry->Race << 16), entry }); memset(sChrSpecializationByIndexStore, 0, sizeof(sChrSpecializationByIndexStore)); for (uint32 i = 0; i < sChrSpecializationStore.GetNumRows(); ++i) if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(i)) sChrSpecializationByIndexStore[chrSpec->ClassID][chrSpec->OrderIndex] = chrSpec; for (uint32 i = 0; i < sFactionStore.GetNumRows(); ++i) { FactionEntry const* faction = sFactionStore.LookupEntry(i); if (faction && faction->ParentFactionID) { SimpleFactionsList &flist = sFactionTeamMap[faction->ParentFactionID]; flist.push_back(i); } } for (uint32 i = 0; i < sGameObjectDisplayInfoStore.GetNumRows(); ++i) { if (GameObjectDisplayInfoEntry const* info = sGameObjectDisplayInfoStore.LookupEntry(i)) { if (info->GeoBoxMax.X < info->GeoBoxMin.X) std::swap(*(float*)(&info->GeoBoxMax.X), *(float*)(&info->GeoBoxMin.X)); if (info->GeoBoxMax.Y < info->GeoBoxMin.Y) std::swap(*(float*)(&info->GeoBoxMax.Y), *(float*)(&info->GeoBoxMin.Y)); if (info->GeoBoxMax.Z < info->GeoBoxMin.Z) std::swap(*(float*)(&info->GeoBoxMax.Z), *(float*)(&info->GeoBoxMin.Z)); } } for (ItemSetSpellEntry const* entry : sItemSetSpellStore) sItemSetSpellsStore[entry->ItemSetID].push_back(entry); // fill data for (uint32 i = 0; i < sMapDifficultyStore.GetNumRows(); ++i) if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) sMapDifficultyMap[entry->MapID][entry->DifficultyID] = entry; sMapDifficultyMap[0][0] = sMapDifficultyMap[1][0]; //map 0 is missing from MapDifficulty.dbc use this till its ported to sql for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->BracketID > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); for (uint32 i = 0; i < sSkillRaceClassInfoStore.GetNumRows(); ++i) if (SkillRaceClassInfoEntry const* entry = sSkillRaceClassInfoStore.LookupEntry(i)) if (sSkillLineStore.LookupEntry(entry->SkillID)) SkillRaceClassInfoBySkill.emplace(entry->SkillID, entry); for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { SpellEntry const* spell = sSpellStore.LookupEntry(i); if (!spell) continue; if (SpellCategoriesEntry const* category = sSpellCategoriesStore.LookupEntry(spell->CategoriesID)) sSpellsByCategoryStore[category->Category].insert(i); } for (uint32 j = 0; j < sSpellEffectScalingStore.GetNumRows(); j++) { SpellEffectScalingEntry const* spellEffectScaling = sSpellEffectScalingStore.LookupEntry(j); if (!spellEffectScaling) continue; sSpellEffectScallingByEffectId.insert(std::make_pair(spellEffectScaling->SpellEffectID, j)); } for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(i)) { if (talentInfo->ClassID < MAX_CLASSES && talentInfo->TierID < MAX_TALENT_TIERS && talentInfo->ColumnIndex < MAX_TALENT_COLUMNS) sTalentByPos[talentInfo->ClassID][talentInfo->TierID][talentInfo->ColumnIndex].push_back(talentInfo); else TC_LOG_ERROR("server.loading", "Value of class (found: %u, max allowed %u) or (found: %u, max allowed %u) tier or column (found: %u, max allowed %u) is invalid.", talentInfo->ClassID, MAX_CLASSES, talentInfo->TierID, MAX_TALENT_TIERS, talentInfo->ColumnIndex, MAX_TALENT_COLUMNS); } } for (uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i) if (WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i)) sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->WMOID, entry->NameSet, entry->WMOGroupID), entry)); // error checks if (bad_dbc_files.size() >= DBCFileCount) { TC_LOG_ERROR("misc", "Incorrect DataDir value in worldserver.conf or ALL required *.dbc files (%d) not found by path: %sdbc", DBCFileCount, dataPath.c_str()); exit(1); } else if (!bad_dbc_files.empty()) { std::string str; for (StoreProblemList::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) str += *i + "\n"; TC_LOG_ERROR("misc", "Some required *.dbc files (%u from %d) not found or not compatible:\n%s", (uint32)bad_dbc_files.size(), DBCFileCount, str.c_str()); exit(1); } // Check loaded DBC files proper version if (!sAreaStore.LookupEntry(6133) || // last area (areaflag) added in 6.0.3 (19342) !sCharTitlesStore.LookupEntry(444) || // last char title added in 6.0.3 (19342) !sGemPropertiesStore.LookupEntry(2534) || // last gem property added in 6.0.3 (19342) !sMapStore.LookupEntry(1447) || // last map added in 6.0.3 (19342) !sSpellStore.LookupEntry(178987) ) // last spell added in 6.0.3 (19342) { TC_LOG_ERROR("misc", "You have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } TC_LOG_INFO("server.loading", ">> Initialized %d DBC data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); }