void MapManager::LoadTransportNPCs() { uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 5 6 7 QueryResult result = WorldDatabase.Query("SELECT guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO, emote FROM creature_transport"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 transport NPCs. DB table `creature_transport` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetInt32(); uint32 entry = fields[1].GetInt32(); uint32 transportEntry = fields[2].GetInt32(); float tX = fields[3].GetFloat(); float tY = fields[4].GetFloat(); float tZ = fields[5].GetFloat(); float tO = fields[6].GetFloat(); uint32 anim = fields[7].GetInt32(); for (MapManager::TransportSet::iterator itr = m_Transports.begin(); itr != m_Transports.end(); ++itr) { if ((*itr)->GetEntry() == transportEntry) { (*itr)->AddNPCPassenger(guid, entry, tX, tY, tZ, tO, anim); break; } } ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u transport npcs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void TicketMgr::LoadTickets() { uint32 oldMSTime = getMSTime(); for (GmTicketList::const_iterator itr = _ticketList.begin(); itr != _ticketList.end(); ++itr) delete itr->second; _ticketList.clear(); _lastTicketId = 0; _openTicketCount = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GM_TICKETS); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 GM tickets. DB table `gm_tickets` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); GmTicket* ticket = new GmTicket(); if (!ticket->LoadFromDB(fields)) { delete ticket; continue; } if (!ticket->IsClosed()) ++_openTicketCount; // Update max ticket id if necessary uint32 id = ticket->GetId(); if (_lastTicketId < id) _lastTicketId = id; _ticketList[id] = ticket; ++count; } while (result->NextRow()); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u GM tickets in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void CreatureTextMgr::LoadCreatureTexts() { uint32 oldMSTime = getMSTime(); mTextMap.clear(); // for reload case mTextRepeatMap.clear(); //reset all currently used temp texts PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_LOAD_CRETEXT); PreparedQueryResult result = WorldDatabase.Query(stmt); if(!result) { sLog->outString(">> Loaded 0 ceature texts. DB table `creature_texts` is empty."); sLog->outString(); return; } uint32 textCount = 0; uint32 creatureCount = 0; do { Field* fields = result->Fetch(); CreatureTextEntry temp; temp.entry = fields[0].GetUInt32(); temp.group = fields[1].GetUInt8(); temp.id = fields[2].GetUInt8(); temp.text = fields[3].GetString(); temp.type = ChatMsg(fields[4].GetUInt8()); temp.lang = Language(fields[5].GetUInt8()); temp.probability = fields[6].GetFloat(); temp.emote = Emote(fields[7].GetUInt32()); temp.duration = fields[8].GetUInt32(); temp.sound = fields[9].GetUInt32(); if(temp.sound) { if(!sSoundEntriesStore.LookupEntry(temp.sound)){ sLog->outErrorDb("CreatureTextMgr: Entry %u, Group %u in table `creature_texts` has Sound %u but sound does not exist.", temp.entry, temp.group, temp.sound); temp.sound = 0; } } if(!GetLanguageDescByID(temp.lang)) { sLog->outErrorDb("CreatureTextMgr: Entry %u, Group %u in table `creature_texts` using Language %u but Language does not exist.", temp.entry, temp.group, uint32(temp.lang)); temp.lang = LANG_UNIVERSAL; } if(temp.type >= MAX_CHAT_MSG_TYPE) { sLog->outErrorDb("CreatureTextMgr: Entry %u, Group %u in table `creature_texts` has Type %u but this Chat Type does not exist.", temp.entry, temp.group, uint32(temp.type)); temp.type = CHAT_MSG_SAY; } if(temp.emote) { if(!sEmotesStore.LookupEntry(temp.emote)) { sLog->outErrorDb("CreatureTextMgr: Entry %u, Group %u in table `creature_texts` has Emote %u but emote does not exist.", temp.entry, temp.group, uint32(temp.emote)); temp.emote = EMOTE_ONESHOT_NONE; } } //entry not yet added, add empty TextHolder (list of groups) if(mTextMap.find(temp.entry) == mTextMap.end()) { ++creatureCount; CreatureTextHolder TextHolder; mTextMap[temp.entry] = TextHolder; } //group not yet added, add empty TextGroup (list of texts) if(mTextMap[temp.entry].find(temp.group) == mTextMap[temp.entry].end()) { CreatureTextGroup TextGroup; mTextMap[temp.entry][temp.group] = TextGroup; } //add the text into our entry's group mTextMap[temp.entry][temp.group].push_back(temp); ++textCount; } while(result->NextRow()); sLog->outString(">> Loaded %u creature texts for %u creatures in %u ms", textCount, creatureCount, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void CreatureTextMgr::LoadCreatureTexts() { uint32 oldMSTime = getMSTime(); mTextMap.clear(); // for reload case mTextRepeatMap.clear(); //reset all currently used temp texts PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEXT); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 ceature texts. DB table `creature_text` is empty."); return; } uint32 textCount = 0; do { Field* fields = result->Fetch(); CreatureTextEntry temp; temp.entry = fields[0].GetUInt32(); temp.group = fields[1].GetUInt8(); temp.id = fields[2].GetUInt8(); temp.type = ChatMsg(fields[3].GetUInt8()); temp.lang = Language(fields[4].GetUInt8()); temp.probability = fields[5].GetFloat(); temp.duration = fields[6].GetUInt32(); temp.BroadcastTextId = fields[7].GetUInt32(); temp.TextRange = CreatureTextRange(fields[8].GetUInt8()); if (!GetLanguageDescByID(temp.lang)) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u in table `creature_text` using Language %u but Language does not exist.", temp.entry, temp.group, uint32(temp.lang)); temp.lang = LANG_UNIVERSAL; } if (temp.type >= MAX_CHAT_MSG_TYPE) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u in table `creature_text` has Type %u but this Chat Type does not exist.", temp.entry, temp.group, uint32(temp.type)); temp.type = CHAT_MSG_SAY; } if (temp.BroadcastTextId) { if (!sObjectMgr->GetBroadcastText(temp.BroadcastTextId)) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u, Id %u in table `creature_text` has non-existing or incompatible BroadcastTextId %u.", temp.entry, temp.group, temp.id, temp.BroadcastTextId); temp.BroadcastTextId = 0; } } if (temp.TextRange > TEXT_RANGE_WORLD) { TC_LOG_ERROR("sql.sql", "CreatureTextMgr: Entry %u, Group %u, Id %u in table `creature_text` has incorrect TextRange %u.", temp.entry, temp.group, temp.id, temp.TextRange); temp.TextRange = TEXT_RANGE_NORMAL; } // add the text into our entry's group mTextMap[temp.entry][temp.group].push_back(temp); ++textCount; } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u creature texts for " SZFMTD " creatures in %u ms", textCount, mTextMap.size(), GetMSTimeDiffToNow(oldMSTime)); }
void AuctionHouseMgr::LoadAuctions() { uint32 oldMSTime = getMSTime(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONS); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 auctions. DB table `auctionhouse` is empty."); return; } uint32 count = 0; SQLTransaction trans = CharacterDatabase.BeginTransaction(); do { Field* fields = result->Fetch(); AuctionEntry* aItem = new AuctionEntry(); if (!aItem->LoadFromDB(fields)) { aItem->DeleteFromDB(trans); delete aItem; continue; } GetAuctionsMap(aItem->factionTemplateId)->AddAuction(aItem); count++; } while (result->NextRow()); CharacterDatabase.CommitTransaction(trans); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u auctions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void PoolMgr::LoadFromDB() { // Pool templates { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT entry, max_limit FROM pool_template"); if (!result) { mPoolTemplate.clear(); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 object pools. DB table `pool_template` is empty."); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 pool_id = fields[0].GetUInt32(); PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id]; pPoolTemplate.MaxLimit = fields[1].GetUInt32(); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u objects pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } // Creatures sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Creatures Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_creature"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 creatures in pools. DB table `pool_creature` is empty."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); CreatureData const* data = sObjectMgr->GetCreatureData(guid); if (!data) { sLog->outError(LOG_FILTER_SQL, "`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id); continue; } if (pool_id > max_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_creature` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { sLog->outError(LOG_FILTER_SQL, "`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%u), skipped.", chance, guid, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(guid, chance); PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id]; cregroup.SetPoolId(pool_id); cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mCreatureSearchMap.insert(p); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u creatures in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // Gameobjects sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Gameobject Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_gameobject"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); GameObjectData const* data = sObjectMgr->GetGOData(guid); if (!data) { sLog->outError(LOG_FILTER_SQL, "`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id); continue; } GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(data->id); if (goinfo->type != GAMEOBJECT_TYPE_CHEST && goinfo->type != GAMEOBJECT_TYPE_GOOBER && goinfo->type != GAMEOBJECT_TYPE_FISHINGHOLE) { sLog->outError(LOG_FILTER_SQL, "`pool_gameobject` has a not lootable gameobject spawn (GUID: %u, type: %u) defined for pool id (%u), skipped.", guid, goinfo->type, pool_id); continue; } if (pool_id > max_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_gameobject` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (chance < 0 || chance > 100) { sLog->outError(LOG_FILTER_SQL, "`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%u), skipped.", chance, guid, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(guid, chance); PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id]; gogroup.SetPoolId(pool_id); gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mGameobjectSearchMap.insert(p); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u gameobject in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // Pool of pools sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Mother Pooling Data..."); { uint32 oldMSTime = getMSTime(); // 1 2 3 QueryResult result = WorldDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 pools in pools"); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 child_pool_id = fields[0].GetUInt32(); uint32 mother_pool_id = fields[1].GetUInt32(); float chance = fields[2].GetFloat(); if (mother_pool_id > max_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_pool` mother_pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", mother_pool_id); continue; } if (child_pool_id > max_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_pool` included pool_id (%u) is out of range compared to max pool id in `pool_template`, skipped.", child_pool_id); continue; } if (mother_pool_id == child_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_pool` pool_id (%u) includes itself, dead-lock detected, skipped.", child_pool_id); continue; } if (chance < 0 || chance > 100) { sLog->outError(LOG_FILTER_SQL, "`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%u), skipped.", chance, child_pool_id, mother_pool_id); continue; } PoolTemplateData* pPoolTemplateMother = &mPoolTemplate[mother_pool_id]; PoolObject plObject = PoolObject(child_pool_id, chance); PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id]; plgroup.SetPoolId(mother_pool_id); plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit); SearchPair p(child_pool_id, mother_pool_id); mPoolSearchMap.insert(p); ++count; } while (result->NextRow()); // Now check for circular reference for (uint32 i=0; i < max_pool_id; ++i) { std::set<uint32> checkedPools; for (SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second)) { checkedPools.insert(poolItr->first); if (checkedPools.find(poolItr->second) != checkedPools.end()) { std::ostringstream ss; ss<< "The pool(s) "; for (std::set<uint32>::const_iterator itr=checkedPools.begin(); itr != checkedPools.end(); ++itr) ss << *itr << ' '; ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool " << poolItr->first << " and child pool " << poolItr->second; sLog->outError(LOG_FILTER_SQL, "%s", ss.str().c_str()); mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first); mPoolSearchMap.erase(poolItr); --count; break; } } } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u pools in mother pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading Quest Pooling Data..."); { uint32 oldMSTime = getMSTime(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_QUEST_POOLS); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 quests in pools"); } else { PooledQuestRelationBounds creBounds; PooledQuestRelationBounds goBounds; enum eQuestTypes { QUEST_NONE = 0, QUEST_DAILY = 1, QUEST_WEEKLY = 2 }; std::map<uint32, int32> poolTypeMap; uint32 count = 0; do { Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 pool_id = fields[1].GetUInt32(); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); if (!quest) { sLog->outError(LOG_FILTER_SQL, "`pool_quest` has a non existing quest template (Entry: %u) defined for pool id (%u), skipped.", entry, pool_id); continue; } if (pool_id > max_pool_id) { sLog->outError(LOG_FILTER_SQL, "`pool_quest` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id); continue; } if (!quest->IsDailyOrWeekly()) { sLog->outError(LOG_FILTER_SQL, "`pool_quest` has an quest (%u) which is not daily or weekly in pool id (%u), use ExclusiveGroup instead, skipped.", entry, pool_id); continue; } if (poolTypeMap[pool_id] == QUEST_NONE) poolTypeMap[pool_id] = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY; int32 currType = quest->IsDaily() ? QUEST_DAILY : QUEST_WEEKLY; if (poolTypeMap[pool_id] != currType) { sLog->outError(LOG_FILTER_SQL, "`pool_quest` quest %u is %s but pool (%u) is specified for %s, mixing not allowed, skipped.", entry, currType == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY", pool_id, poolTypeMap[pool_id] == QUEST_DAILY ? "QUEST_DAILY" : "QUEST_WEEKLY"); continue; } creBounds = mQuestCreatureRelation.equal_range(entry); goBounds = mQuestGORelation.equal_range(entry); if (creBounds.first == creBounds.second && goBounds.first == goBounds.second) { sLog->outError(LOG_FILTER_SQL, "`pool_quest` lists entry (%u) as member of pool (%u) but is not started anywhere, skipped.", entry, pool_id); continue; } PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id]; PoolObject plObject = PoolObject(entry, 0.0f); PoolGroup<Quest>& questgroup = mPoolQuestGroups[pool_id]; questgroup.SetPoolId(pool_id); questgroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(entry, pool_id); mQuestSearchMap.insert(p); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u quests in pools in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Starting objects pooling system..."); { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool FROM pool_template" " LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry" " LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Pool handling system initialized, 0 pools spawned."); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 pool_entry = fields[0].GetUInt32(); uint32 pool_pool_id = fields[1].GetUInt32(); if (!CheckPool(pool_entry)) { if (pool_pool_id) // The pool is a child pool in pool_pool table. Ideally we should remove it from the pool handler to ensure it never gets spawned, // however that could recursively invalidate entire chain of mother pools. It can be done in the future but for now we'll do nothing. sLog->outError(LOG_FILTER_SQL, "Pool Id %u has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id %u and cannot be safely removed.", pool_entry, fields[2].GetUInt32()); else sLog->outError(LOG_FILTER_SQL, "Pool Id %u has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry); continue; } // Don't spawn child pools, they are spawned recursively by their parent pools if (!pool_pool_id) { SpawnPool(pool_entry); count++; } } while (result->NextRow()); sLog->outDebug(LOG_FILTER_POOLSYS, "Pool handling system initialized, %u pools spawned in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } }
// loads the extra item creation info from DB void LoadSkillExtraItemTable() { uint32 oldMSTime = getMSTime(); SkillExtraItemStore.clear(); // need for reload // 0 1 2 3 QueryResult result = WorldDatabase.Query("SELECT spellId, requiredSpecialization, additionalCreateChance, additionalMaxNum FROM skill_extra_item_template"); if (!result) { sLog->outErrorDb(">> Loaded 0 spell specialization definitions. DB table `skill_extra_item_template` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 spellId = fields[0].GetUInt32(); if (!sSpellMgr->GetSpellInfo(spellId)) { sLog->outError("Skill specialization %u has non-existent spell id in `skill_extra_item_template`!", spellId); continue; } uint32 requiredSpecialization = fields[1].GetUInt32(); if (!sSpellMgr->GetSpellInfo(requiredSpecialization)) { sLog->outError("Skill specialization %u have not existed required specialization spell id %u in `skill_extra_item_template`!", spellId, requiredSpecialization); continue; } float additionalCreateChance = fields[2].GetFloat(); if (additionalCreateChance <= 0.0f) { sLog->outError("Skill specialization %u has too low additional create chance in `skill_extra_item_template`!", spellId); continue; } uint8 additionalMaxNum = fields[3].GetUInt8(); if (!additionalMaxNum) { sLog->outError("Skill specialization %u has 0 max number of extra items in `skill_extra_item_template`!", spellId); continue; } SkillExtraItemEntry& skillExtraItemEntry = SkillExtraItemStore[spellId]; skillExtraItemEntry.requiredSpecialization = requiredSpecialization; skillExtraItemEntry.additionalCreateChance = additionalCreateChance; skillExtraItemEntry.additionalMaxNum = additionalMaxNum; ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u spell specialization definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
// ------------------- void CreatureEventAIMgr::LoadCreatureEventAI_Summons() { uint32 oldMSTime = getMSTime(); //Drop Existing EventSummon Map m_CreatureEventAI_Summon_Map.clear(); // Gather additional data for EventAI QueryResult result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons"); if (!result) { sLog->outString(">> Loaded 0 CreatureEventAI Summon definitions. DB table `creature_ai_summons` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field* fields = result->Fetch(); CreatureEventAI_Summon temp; uint32 i = fields[0].GetUInt32(); temp.position_x = fields[1].GetFloat(); temp.position_y = fields[2].GetFloat(); temp.position_z = fields[3].GetFloat(); temp.orientation = fields[4].GetFloat(); temp.SpawnTimeSecs = fields[5].GetUInt32(); if (!Trinity::IsValidMapCoord(temp.position_x, temp.position_y, temp.position_z, temp.orientation)) { sLog->outErrorDb("CreatureEventAI: Summon id %u have wrong coordinates (%f, %f, %f, %f), skipping.", i, temp.position_x, temp.position_y, temp.position_z, temp.orientation); continue; } //Add to map m_CreatureEventAI_Summon_Map[i] = temp; ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u CreatureEventAI summon definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
// ------------------- void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() { uint32 oldMSTime = getMSTime(); //Drop Existing EventAI List m_CreatureEventAI_Event_Map.clear(); // Gather event data QueryResult result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, " "event_param1, event_param2, event_param3, event_param4, " "action1_type, action1_param1, action1_param2, action1_param3, " "action2_type, action2_param1, action2_param2, action2_param3, " "action3_type, action3_param1, action3_param2, action3_param3 " "FROM creature_ai_scripts"); if (!result) { sLog->outString(">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field* fields = result->Fetch(); CreatureEventAI_Event temp; temp.event_id = EventAI_Type(fields[0].GetUInt32()); uint32 i = temp.event_id; temp.creature_id = fields[1].GetUInt32(); uint32 creature_id = temp.creature_id; uint32 e_type = fields[2].GetUInt32(); //Report any errors in event if (e_type >= EVENT_T_END) { sLog->outErrorDb("CreatureEventAI: Event %u have wrong type (%u), skipping.", i, e_type); continue; } temp.event_type = EventAI_Type(e_type); temp.event_inverse_phase_mask = fields[3].GetUInt32(); temp.event_chance = fields[4].GetUInt8(); temp.event_flags = fields[5].GetUInt8(); temp.raw.param1 = fields[6].GetUInt32(); temp.raw.param2 = fields[7].GetUInt32(); temp.raw.param3 = fields[8].GetUInt32(); temp.raw.param4 = fields[9].GetUInt32(); //Creature does not exist in database if (!sObjectMgr->GetCreatureTemplate(temp.creature_id)) { sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, temp.creature_id); continue; } //No chance of this event occuring if (temp.event_chance == 0) sLog->outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i); //Chance above 100, force it to be 100 else if (temp.event_chance > 100) { sLog->outErrorDb("CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i); temp.event_chance = 100; } //Individual event checks switch (temp.event_type) { case EVENT_T_TIMER: case EVENT_T_TIMER_OOC: if (temp.timer.initialMax < temp.timer.initialMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); if (temp.timer.repeatMax < temp.timer.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_HP: case EVENT_T_MANA: case EVENT_T_TARGET_HP: case EVENT_T_TARGET_MANA: if (temp.percent_range.percentMax > 100) sLog->outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i); if (temp.percent_range.percentMax <= temp.percent_range.percentMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i); if (temp.event_flags & EFLAG_REPEATABLE && !temp.percent_range.repeatMin && !temp.percent_range.repeatMax) { sLog->outErrorDb("CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); temp.event_flags &= ~EFLAG_REPEATABLE; } break; case EVENT_T_SPELLHIT: if (temp.spell_hit.spellId) { SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId); if (!spell) { sLog->outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); continue; } if ((temp.spell_hit.schoolMask & spell->SchoolMask) != spell->SchoolMask) sLog->outErrorDb("CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.spell_hit.schoolMask, i); } if (!temp.spell_hit.schoolMask) sLog->outErrorDb("CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i); if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_RANGE: if (temp.range.maxDist < temp.range.minDist) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i); if (temp.range.repeatMax < temp.range.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_OOC_LOS: if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_SPAWNED: switch (temp.spawned.condition) { case SPAWNED_EVENT_ALWAY: break; case SPAWNED_EVENT_MAP: if (!sMapStore.LookupEntry(temp.spawned.conditionValue1)) sLog->outErrorDb("CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'map specific' but with not existed map (%u) in param2. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1); break; case SPAWNED_EVENT_ZONE: if (!GetAreaEntryByAreaID(temp.spawned.conditionValue1)) sLog->outErrorDb("CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'area specific' but with not existed area (%u) in param2. Event will never repeat.", temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1); default: sLog->outErrorDb("CreatureEventAI: Creature %u are using invalid spawned event %u mode (%u) in param1", temp.creature_id, i, temp.spawned.condition); break; } break; case EVENT_T_FRIENDLY_HP: if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_FRIENDLY_IS_CC: if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_FRIENDLY_MISSING_BUFF: { SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId); if (!spell) { sLog->outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); continue; } if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; } case EVENT_T_KILL: if (temp.kill.repeatMax < temp.kill.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_TARGET_CASTING: if (temp.target_casting.repeatMax < temp.target_casting.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_SUMMONED_UNIT: if (!sObjectMgr->GetCreatureTemplate(temp.summon_unit.creatureId)) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.summon_unit.creatureId); if (temp.summon_unit.repeatMax < temp.summon_unit.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; case EVENT_T_QUEST_ACCEPT: case EVENT_T_QUEST_COMPLETE: if (!sObjectMgr->GetQuestTemplate(temp.quest.questId)) sLog->outErrorDb("CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId); sLog->outErrorDb("CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i); continue; case EVENT_T_AGGRO: case EVENT_T_DEATH: case EVENT_T_EVADE: case EVENT_T_REACHED_HOME: { if (temp.event_flags & EFLAG_REPEATABLE) { sLog->outErrorDb("CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i); temp.event_flags &= ~EFLAG_REPEATABLE; } break; } case EVENT_T_RECEIVE_EMOTE: { if (!sEmotesTextStore.LookupEntry(temp.receive_emote.emoteId)) { sLog->outErrorDb("CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.", temp.creature_id, i, temp.receive_emote.emoteId); continue; } if (temp.receive_emote.condition) { Condition cond; cond.mConditionType = ConditionType(temp.receive_emote.condition); cond.mConditionValue1 = temp.receive_emote.conditionValue1; cond.mConditionValue2 = temp.receive_emote.conditionValue2; if (!sConditionMgr->isConditionTypeValid(&cond)) { sLog->outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.", temp.creature_id, i, temp.receive_emote.condition); continue; } } if (!(temp.event_flags & EFLAG_REPEATABLE)) { sLog->outErrorDb("CreatureEventAI: Creature %u using event %u: EFLAG_REPEATABLE not set. Event must always be repeatable. Flag applied.", temp.creature_id, i); temp.event_flags |= EFLAG_REPEATABLE; } break; } case EVENT_T_BUFFED: case EVENT_T_TARGET_BUFFED: { SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.buffed.spellId); if (!spell) { sLog->outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i); continue; } if (temp.buffed.repeatMax < temp.buffed.repeatMin) sLog->outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; } case EVENT_T_RESET: break; default: sLog->outErrorDb("CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i); break; } for (uint32 j = 0; j < MAX_ACTIONS; j++) { uint16 action_type = fields[10+(j*4)].GetUInt16(); if (action_type >= ACTION_T_END) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type (%u), replace by ACTION_T_NONE.", i, j+1, action_type); temp.action[j].type = ACTION_T_NONE; continue; } CreatureEventAI_Action& action = temp.action[j]; action.type = EventAI_ActionType(action_type); action.raw.param1 = fields[11+(j*4)].GetUInt32(); action.raw.param2 = fields[12+(j*4)].GetUInt32(); action.raw.param3 = fields[13+(j*4)].GetUInt32(); //Report any errors in actions switch (action.type) { case ACTION_T_NONE: break; case ACTION_T_TEXT: { if (action.text.TextId1 < 0) { if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end()) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1); } if (action.text.TextId2 < 0) { if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end()) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1); if (!action.text.TextId1) sLog->outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1); } if (action.text.TextId3 < 0) { if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end()) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1); if (!action.text.TextId1 || !action.text.TextId2) sLog->outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1); } break; } case ACTION_T_SET_FACTION: if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId)) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId); action.set_faction.factionId = 0; } break; case ACTION_T_MORPH_TO_ENTRY_OR_MODEL: if (action.morph.creatureId !=0 || action.morph.modelId !=0) { if (action.morph.creatureId && !sObjectMgr->GetCreatureTemplate(action.morph.creatureId)) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatureId); action.morph.creatureId = 0; } if (action.morph.modelId) { if (action.morph.creatureId) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId, action.morph.creatureId); action.morph.modelId = 0; } else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId)) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId); action.morph.modelId = 0; } } } break; case ACTION_T_SOUND: if (!sSoundEntriesStore.LookupEntry(action.sound.soundId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId); break; case ACTION_T_EMOTE: if (!sEmotesStore.LookupEntry(action.emote.emoteId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId); break; case ACTION_T_RANDOM_SOUND: if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1); if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2); if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3); break; case ACTION_T_RANDOM_EMOTE: if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1); if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2); if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3); break; case ACTION_T_CAST: { const SpellInfo* spell = sSpellMgr->GetSpellInfo(action.cast.spellId); if (!spell) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId); /* FIXME: temp.raw.param3 not have event tipes with recovery time in it.... else { if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE) { //output as debug for now, also because there's no general rule all spells have RecoveryTime if (temp.event_param3 < spell->RecoveryTime) sLog->outDebug("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1, action.cast.spellId, spell->RecoveryTime, temp.event_param3); } } */ //Cast is always triggered if target is forced to cast on self if (action.cast.castFlags & CAST_FORCE_TARGET_SELF) action.cast.castFlags |= CAST_TRIGGERED; if (action.cast.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; } case ACTION_T_SUMMON: if (!sObjectMgr->GetCreatureTemplate(action.summon.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatureId); if (action.summon.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_THREAT_SINGLE_PCT: if (std::abs(action.threat_single_pct.percent) > 100) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent); if (action.threat_single_pct.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_THREAT_ALL_PCT: if (std::abs(action.threat_all_pct.percent) > 100) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent); break; case ACTION_T_QUEST_EVENT: if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event.questId)) { if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId); } else sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId); if (action.quest_event.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_CAST_EVENT: if (!sObjectMgr->GetCreatureTemplate(action.cast_event.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event.creatureId); if (!sSpellMgr->GetSpellInfo(action.cast_event.spellId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event.spellId); if (action.cast_event.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_SET_UNIT_FIELD: if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1); if (action.set_unit_field.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_SET_UNIT_FLAG: case ACTION_T_REMOVE_UNIT_FLAG: if (action.unit_flag.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_SET_PHASE: if (action.set_phase.phase >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); break; case ACTION_T_INC_PHASE: if (action.set_inc_phase.step == 0) sLog->outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1) sLog->outErrorDb("CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step); break; case ACTION_T_QUEST_EVENT_ALL: if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event_all.questId)) { if (!qid->HasFlag(QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId); } else sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId); break; case ACTION_T_CAST_EVENT_ALL: if (!sObjectMgr->GetCreatureTemplate(action.cast_event_all.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.cast_event_all.creatureId); if (!sSpellMgr->GetSpellInfo(action.cast_event_all.spellId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast_event_all.spellId); break; case ACTION_T_REMOVEAURASFROMSPELL: if (!sSpellMgr->GetSpellInfo(action.remove_aura.spellId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId); if (action.remove_aura.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3 if (action.random_phase.phase1 >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); if (action.random_phase.phase2 >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); if (action.random_phase.phase3 >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); break; case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax if (action.random_phase_range.phaseMin >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); if (action.random_phase_range.phaseMin >= MAX_PHASE) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1); if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1); std::swap(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax); // equal case processed at call } break; case ACTION_T_SUMMON_ID: if (!sObjectMgr->GetCreatureTemplate(action.summon_id.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.summon_id.creatureId); if (action.summon_id.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); if (m_CreatureEventAI_Summon_Map.find(action.summon_id.spawnId) == m_CreatureEventAI_Summon_Map.end()) sLog->outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, action.summon_id.spawnId); break; case ACTION_T_KILLED_MONSTER: if (!sObjectMgr->GetCreatureTemplate(action.killed_monster.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId); if (action.killed_monster.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_SET_INST_DATA: if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1); if (action.set_inst_data.value > 4/*SPECIAL*/) sLog->outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1); break; case ACTION_T_SET_INST_DATA64: if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1); if (action.set_inst_data64.target >= TARGET_T_END) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; case ACTION_T_UPDATE_TEMPLATE: if (!sObjectMgr->GetCreatureTemplate(action.update_template.creatureId)) sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId); break; case ACTION_T_SET_SHEATH: if (action.set_sheath.sheath >= MAX_SHEATH_STATE) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses wrong sheath state %u.", i, j+1, action.set_sheath.sheath); action.set_sheath.sheath = SHEATH_STATE_UNARMED; } break; case ACTION_T_SET_INVINCIBILITY_HP_LEVEL: if (action.invincibility_hp_level.is_percent) { if (action.invincibility_hp_level.hp_level > 100) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses wrong percent value %u.", i, j+1, action.invincibility_hp_level.hp_level); action.invincibility_hp_level.hp_level = 100; } } break; case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL: if (action.mount.creatureId != 0 || action.mount.modelId != 0) { if (action.mount.creatureId && !sObjectMgr->GetCreatureTemplate(action.mount.creatureId)) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses nonexistent Creature entry %u.", i, j+1, action.mount.creatureId); action.morph.creatureId = 0; } if (action.mount.modelId) { if (action.mount.creatureId) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.mount.modelId, action.mount.creatureId); action.mount.modelId = 0; } else if (!sCreatureDisplayInfoStore.LookupEntry(action.mount.modelId)) { sLog->outErrorDb("CreatureEventAI: Event %u Action %u uses nonexistent ModelId %u.", i, j+1, action.mount.modelId); action.mount.modelId = 0; } } } break; case ACTION_T_EVADE: //No Params case ACTION_T_FLEE_FOR_ASSIST: //No Params case ACTION_T_DIE: //No Params case ACTION_T_ZONE_COMBAT_PULSE: //No Params case ACTION_T_FORCE_DESPAWN: //No Params case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking) case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking) case ACTION_T_RANGED_MOVEMENT: //Distance, Angle case ACTION_T_CALL_FOR_HELP: //Distance break; case ACTION_T_RANDOM_SAY: case ACTION_T_RANDOM_YELL: case ACTION_T_RANDOM_TEXTEMOTE: sLog->outErrorDb("CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1); break; case ACTION_T_MOVE_RANDOM_POINT: case ACTION_T_SET_STAND_STATE: case ACTION_T_SET_PHASE_MASK: case ACTION_T_SET_VISIBILITY: case ACTION_T_SET_ACTIVE: case ACTION_T_SET_AGGRESSIVE: case ACTION_T_ATTACK_START_PULSE: case ACTION_T_SUMMON_GO: break; default: sLog->outErrorDb("CreatureEventAI: Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j+1, action.type); break; } } //Add to list m_CreatureEventAI_Event_Map[creature_id].push_back(temp); ++count; } while (result->NextRow()); for (CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) { if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(itr->first)) { if (cInfo->AIName != "EventAI") { sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI', changing to EventAI", itr->first); const_cast<CreatureTemplate*>(cInfo)->AIName = "EventAI"; } } } sLog->outString(">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AchievementGlobalMgr::LoadRewards() { uint32 oldMSTime = getMSTime(); m_achievementRewards.clear(); // need for reload case // 0 1 2 3 4 5 6 QueryResult result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward"); if (!result) { sLog->outErrorDb(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); const AchievementEntry* pAchievement = sAchievementStore.LookupEntry(entry); if (!pAchievement) { sLog->outErrorDb("Table `achievement_reward` has wrong achievement (Entry: %u), ignore", entry); continue; } AchievementReward reward; reward.titleId[0] = fields[1].GetUInt32(); reward.titleId[1] = fields[2].GetUInt32(); reward.itemId = fields[3].GetUInt32(); reward.sender = fields[4].GetUInt32(); reward.subject = fields[5].GetString(); reward.text = fields[6].GetString(); // must be title or mail at least if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender) { sLog->outErrorDb("Table `achievement_reward` (Entry: %u) not have title or item reward data, ignore.", entry); continue; } if (pAchievement->requiredFaction == ACHIEVEMENT_FACTION_ANY && ((reward.titleId[0] == 0) != (reward.titleId[1] == 0))) sLog->outErrorDb("Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) for only one team.", entry, reward.titleId[0], reward.titleId[1]); if (reward.titleId[0]) { CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[0]); if (!titleEntry) { sLog->outErrorDb("Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[0]); reward.titleId[0] = 0; } } if (reward.titleId[1]) { CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[1]); if (!titleEntry) { sLog->outErrorDb("Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_H`, set to 0", entry, reward.titleId[1]); reward.titleId[1] = 0; } } //check mail data before item for report including wrong item case if (reward.sender) { if (!sObjectMgr->GetCreatureTemplate(reward.sender)) { sLog->outErrorDb("Table `achievement_reward` (Entry: %u) has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender); reward.sender = 0; } } else { if (reward.itemId) sLog->outErrorDb("Table `achievement_reward` (Entry: %u) does not have sender data but has item reward, item will not be rewarded.", entry); if (!reward.subject.empty()) sLog->outErrorDb("Table `achievement_reward` (Entry: %u) does not have sender data but has mail subject.", entry); if (!reward.text.empty()) sLog->outErrorDb("Table `achievement_reward` (Entry: %u) does not have sender data but has mail text.", entry); } if (reward.itemId) { if (!sObjectMgr->GetItemTemplate(reward.itemId)) { sLog->outErrorDb("Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will not contain item.", entry, reward.itemId); reward.itemId = 0; } } m_achievementRewards[entry] = reward; ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u achievement rewards in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AchievementGlobalMgr::LoadRewardLocales() { uint32 oldMSTime = getMSTime(); m_achievementRewardLocales.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT entry, subject_loc1, text_loc1, subject_loc2, text_loc2, subject_loc3, text_loc3, subject_loc4, text_loc4, " "subject_loc5, text_loc5, subject_loc6, text_loc6, subject_loc7, text_loc7, subject_loc8, text_loc8" " FROM locales_achievement_reward"); if (!result) { sLog->outString(">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty"); sLog->outString(); return; } do { Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); if (m_achievementRewards.find(entry) == m_achievementRewards.end()) { sLog->outErrorDb("Table `locales_achievement_reward` (Entry: %u) has locale strings for non-existing achievement reward.", entry); continue; } AchievementRewardLocale& data = m_achievementRewardLocales[entry]; for (int i = 1; i < TOTAL_LOCALES; ++i) { LocaleConstant locale = (LocaleConstant) i; ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1)].GetString(), locale, data.subject); ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1) + 1].GetString(), locale, data.text); } } while (result->NextRow()); sLog->outString(">> Loaded %lu achievement reward locale strings in %u ms", (unsigned long)m_achievementRewardLocales.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AchievementGlobalMgr::LoadCompletedAchievements() { uint32 oldMSTime = getMSTime(); QueryResult result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); if (!result) { sLog->outString(">> Loaded 0 completed achievements. DB table `character_achievement` is empty."); sLog->outString(); return; } do { Field *fields = result->Fetch(); uint32 achievementId = fields[0].GetUInt32(); const AchievementEntry* achievement = sAchievementStore.LookupEntry(achievementId); if (!achievement) { // Remove non existent achievements from all characters sLog->outError("Non-existing achievement %u data removed from table `character_achievement`.", achievementId); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEVMENT); stmt->setUInt16(0, uint16(achievementId)); CharacterDatabase.Execute(stmt); continue; } else if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) m_allCompletedAchievements.insert(achievementId); } while (result->NextRow()); sLog->outString(">> Loaded %lu completed achievements in %u ms", (unsigned long)m_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AchievementGlobalMgr::LoadAchievementCriteriaData() { uint32 oldMSTime = getMSTime(); m_criteriaDataMap.clear(); // need for reload case QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM achievement_criteria_data"); if (!result) { sLog->outString(">> Loaded 0 additional achievement criteria data. DB table `achievement_criteria_data` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field *fields = result->Fetch(); uint32 criteria_id = fields[0].GetUInt32(); AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id); if (!criteria) { sLog->outErrorDb("Table `achievement_criteria_data` has data for non-existing criteria (Entry: %u), ignore.", criteria_id); continue; } uint32 dataType = fields[1].GetUInt8(); const char* scriptName = fields[4].GetCString(); uint32 scriptId = 0; if (strcmp(scriptName, "")) // not empty { if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT) sLog->outErrorDb("Table `achievement_criteria_data` has ScriptName set for non-scripted data type (Entry: %u, type %u), useless data.", criteria_id, dataType); else scriptId = sObjectMgr->GetScriptId(scriptName); } AchievementCriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId); if (!data.IsValid(criteria)) continue; // this will allocate empty data set storage AchievementCriteriaDataSet& dataSet = m_criteriaDataMap[criteria_id]; dataSet.SetCriteriaId(criteria_id); // add real data only for not NONE data types if (data.dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE) dataSet.Add(data); // counting data by and data types ++count; } while (result->NextRow()); // post loading checks for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) { AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); if (!criteria) continue; switch (criteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: { AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); if (!achievement) continue; // exist many achievements with this criteria, use at this moment hardcoded check to skill simple case if (achievement->ID == 1282) break; continue; } case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: // need skip generic cases if (criteria->additionalRequirements[0].additionalRequirement_type != ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE) continue; break; case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases if (criteria->do_emote.count == 0) continue; break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: // skip statistics if (criteria->win_duel.duelCount == 0) continue; break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: // need skip generic cases if (criteria->loot_type.lootTypeCount != 1) continue; break; case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL: // any cases break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements { AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); if (!achievement) continue; if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK) continue; break; } case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: break; default: // type not use DB data, ignore continue; } if (!GetCriteriaDataSet(criteria) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, entryId, NULL)) sLog->outErrorDb("Table `achievement_criteria_data` does not have expected data for criteria (Entry: %u Type: %u) for achievement %u.", criteria->ID, criteria->requiredType, criteria->referredAchievement); } sLog->outString(">> Loaded %u additional achievement criteria data in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
//========================================================== void AchievementGlobalMgr::LoadAchievementCriteriaList() { uint32 oldMSTime = getMSTime(); if (sAchievementCriteriaStore.GetNumRows() == 0) { sLog->outErrorDb(">> Loaded 0 achievement criteria."); sLog->outString(); return; } for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) { AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); if (!criteria) continue; m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria); m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria); if (criteria->timeLimit) m_AchievementCriteriasByTimedType[criteria->timedCriteriaStartType].push_back(criteria); } sLog->outString(">> Loaded %lu achievement criteria in %u ms", (unsigned long)m_AchievementCriteriasByType->size(), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void GuildMgr::LoadGuilds() { // 1. Load all guilds sLog->outString("Loading guilds definitions..."); { uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT g.guildid, g.name, g.leaderguid, g.EmblemStyle, g.EmblemColor, g.BorderStyle, g.BorderColor, " // 7 8 9 10 11 12 "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, COUNT(gbt.guildid) " "FROM guild g LEFT JOIN guild_bank_tab gbt ON g.guildid = gbt.guildid GROUP BY g.guildid ORDER BY g.guildid ASC"); if (!result) { sLog->outString(">> Loaded 0 guild definitions. DB table `guild` is empty."); sLog->outString(); return; } else { uint32 count = 0; do { Field* fields = result->Fetch(); Guild* guild = new Guild(); if (!guild->LoadFromDB(fields)) { delete guild; continue; } QueryResult gNews = CharacterDatabase.PQuery("SELECT type, date, value1, value2, source_guid, flags FROM guild_news WHERE guildid = %u ORDER BY date DESC", guild->GetId()); if (gNews) { Field* fields = gNews->Fetch(); guild->LoadGuildNewsFromDB(fields); } AddGuild(guild); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 2. Load all guild ranks sLog->outString("Loading guild ranks..."); { uint32 oldMSTime = getMSTime(); // Delete orphaned guild rank entries before loading the valid ones CharacterDatabase.DirectExecute("DELETE gr FROM guild_rank gr LEFT JOIN guild g ON gr.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 QueryResult result = CharacterDatabase.Query("SELECT guildid, rid, rname, rights, BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC"); if (!result) { sLog->outString(">> Loaded 0 guild ranks. DB table `guild_rank` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadRankFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild ranks in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 3. Load all guild members sLog->outString("Loading guild members..."); { uint32 oldMSTime = getMSTime(); // Delete orphaned guild member entries before loading the valid ones CharacterDatabase.DirectExecute("DELETE gm FROM guild_member gm LEFT JOIN guild g ON gm.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT guildid, gm.guid, rank, pnote, offnote, BankResetTimeMoney, BankRemMoney, " // 7 8 9 10 11 12 "BankResetTimeTab0, BankRemSlotsTab0, BankResetTimeTab1, BankRemSlotsTab1, BankResetTimeTab2, BankRemSlotsTab2, " // 13 14 15 16 17 18 "BankResetTimeTab3, BankRemSlotsTab3, BankResetTimeTab4, BankRemSlotsTab4, BankResetTimeTab5, BankRemSlotsTab5, " // 19 20 21 22 23 24 "c.name, c.level, c.class, c.zone, c.account, c.logout_time " "FROM guild_member gm LEFT JOIN characters c ON c.guid = gm.guid ORDER BY guildid ASC"); if (!result) { sLog->outString(">> Loaded 0 guild members. DB table `guild_member` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadMemberFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild members int %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 4. Load all guild bank tab rights sLog->outString("Loading bank tab rights..."); { uint32 oldMSTime = getMSTime(); // Delete orphaned guild bank right entries before loading the valid ones CharacterDatabase.DirectExecute("DELETE gbr FROM guild_bank_right gbr LEFT JOIN guild g ON gbr.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 QueryResult result = CharacterDatabase.Query("SELECT guildid, TabId, rid, gbright, SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC"); if (!result) { sLog->outString(">> Loaded 0 guild bank tab rights. DB table `guild_bank_right` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadBankRightFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u bank tab rights in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 5. Load all event logs sLog->outString("Loading guild event logs..."); { uint32 oldMSTime = getMSTime(); CharacterDatabase.DirectPExecute("DELETE FROM guild_eventlog WHERE LogGuid > %u", sWorld->getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); // 0 1 2 3 4 5 6 QueryResult result = CharacterDatabase.Query("SELECT guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp FROM guild_eventlog ORDER BY TimeStamp DESC, LogGuid DESC"); if (!result) { sLog->outString(">> Loaded 0 guild event logs. DB table `guild_eventlog` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadEventLogFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild event logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 6. Load all bank event logs sLog->outString("Loading guild bank event logs..."); { uint32 oldMSTime = getMSTime(); // Remove log entries that exceed the number of allowed entries per guild CharacterDatabase.DirectPExecute("DELETE FROM guild_bank_eventlog WHERE LogGuid > %u", sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); // 0 1 2 3 4 5 6 7 8 QueryResult result = CharacterDatabase.Query("SELECT guildid, TabId, LogGuid, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp FROM guild_bank_eventlog ORDER BY TimeStamp DESC, LogGuid DESC"); if (!result) { sLog->outString(">> Loaded 0 guild bank event logs. DB table `guild_bank_eventlog` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadBankEventLogFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild bank event logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 7. Load all guild bank tabs sLog->outString("Loading guild bank tabs..."); { uint32 oldMSTime = getMSTime(); // Delete orphaned guild bank tab entries before loading the valid ones CharacterDatabase.DirectExecute("DELETE gbt FROM guild_bank_tab gbt LEFT JOIN guild g ON gbt.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 QueryResult result = CharacterDatabase.Query("SELECT guildid, TabId, TabName, TabIcon, TabText FROM guild_bank_tab ORDER BY guildid ASC, TabId ASC"); if (!result) { sLog->outString(">> Loaded 0 guild bank tabs. DB table `guild_bank_tab` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[0].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadBankTabFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild bank tabs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 8. Fill all guild bank tabs sLog->outString("Filling bank tabs with items..."); { uint32 oldMSTime = getMSTime(); // Delete orphan guild bank items CharacterDatabase.DirectExecute("DELETE gbi FROM guild_bank_item gbi LEFT JOIN guild g ON gbi.guildId = g.guildId WHERE g.guildId IS NULL"); // 0 1 2 3 4 5 6 7 8 9 10 QueryResult result = CharacterDatabase.Query("SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, " // 11 12 13 14 15 "guildid, TabId, SlotId, item_guid, itemEntry FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid"); if (!result) { sLog->outString(">> Loaded 0 guild bank tab items. DB table `guild_bank_item` or `item_instance` is empty."); sLog->outString(); } else { uint32 count = 0; do { Field* fields = result->Fetch(); uint32 guildId = fields[11].GetUInt32(); if (Guild* guild = GetGuildById(guildId)) guild->LoadBankItemFromDB(fields); ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u guild bank tab items in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } } // 9. Validate loaded guild data sLog->outString("Validating data of loaded guilds..."); { uint32 oldMSTime = getMSTime(); for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) { Guild* guild = itr->second; if (guild) { if (!guild->Validate()) { RemoveGuild(guild->GetId()); delete guild; } } } sLog->outString(">> Validated data of loaded guilds in %u ms", GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } }
// ------------------- void CreatureEventAIMgr::LoadCreatureEventAI_Texts() { uint32 oldMSTime = getMSTime(); // Drop Existing Text Map, only done once and we are ready to add data from multiple sources. m_CreatureEventAI_TextMap.clear(); // Load EventAI Text sObjectMgr->LoadTrinityStrings("creature_ai_texts", MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID); // Gather Additional data from EventAI Texts QueryResult result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); if (!result) { sLog->outString(">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty."); sLog->outString(); return; } uint32 count = 0; do { Field* fields = result->Fetch(); StringTextData temp; int32 i = fields[0].GetInt32(); temp.SoundId = fields[1].GetInt32(); temp.Type = fields[2].GetInt32(); temp.Language = fields[3].GetInt32(); temp.Emote = fields[4].GetInt32(); // range negative if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID) { sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is not in valid range(%d-%d)", i, MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID); continue; } // range negative (must not happen, loaded from same table) if (!sObjectMgr->GetTrinityStringLocale(i)) { sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` not found", i); continue; } if (temp.SoundId) { if (!sSoundEntriesStore.LookupEntry(temp.SoundId)) sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.", i, temp.SoundId); } if (!GetLanguageDescByID(temp.Language)) sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.", i, temp.Language); if (temp.Type > CHAT_TYPE_ZONE_YELL) sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.", i, temp.Type); if (temp.Emote) { if (!sEmotesStore.LookupEntry(temp.Emote)) sLog->outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Emote %u but emote does not exist.", i, temp.Emote); } m_CreatureEventAI_TextMap[i] = temp; ++count; } while (result->NextRow()); sLog->outString(">> Loaded %u additional CreatureEventAI Texts data in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void SmartWaypointMgr::LoadFromDB() { uint32 oldMSTime = getMSTime(); waypoint_map.clear(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_LOAD_SMARTAI_WP); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { sLog->outString(">> Loaded 0 SmartAI Waypoint Paths. DB table `waypoints` is empty."); sLog->outString(); return; } uint32 count = 0; uint32 total = 0; WPPath* path = NULL; uint32 last_entry = 0; uint32 last_id = 1; do { Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 id = fields[1].GetUInt32(); float x, y, z; x = fields[2].GetFloat(); y = fields[3].GetFloat(); z = fields[4].GetFloat(); WayPoint* wp = new WayPoint(id, x, y, z); if (last_entry != entry) { path = new WPPath; last_id = 1; } if (last_id != id) { sLog->outErrorDb("SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, last_id); } last_id++; (*path)[id] = wp; if (last_entry != entry) { count++; waypoint_map[entry] = path; } last_entry = entry; total++; } while (result->NextRow()); sLog->outString(">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void LoadSkillDiscoveryTable() { uint32 oldMSTime = getMSTime(); SkillDiscoveryStore.clear(); // need for reload // 0 1 2 3 QueryResult result = WorldDatabase.Query("SELECT spellId, reqSpell, reqSkillValue, chance FROM skill_discovery_template"); if (!result) { sLog->outError(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty."); return; } uint32 count = 0; std::ostringstream ssNonDiscoverableEntries; std::set<uint32> reportedReqSpells; do { Field* fields = result->Fetch(); uint32 spellId = fields[0].GetUInt32(); int32 reqSkillOrSpell = fields[1].GetInt32(); uint32 reqSkillValue = fields[2].GetUInt16(); float chance = fields[3].GetFloat(); if (chance <= 0) // chance { ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " reqSkillValue = " << reqSkillValue << " chance = " << chance << "(chance problem)\n"; continue; } if (reqSkillOrSpell > 0) // spell case { uint32 absReqSkillOrSpell = uint32(reqSkillOrSpell); SpellInfo const* reqSpellInfo = sSpellMgr->GetSpellInfo(absReqSkillOrSpell); if (!reqSpellInfo) { if (reportedReqSpells.find(absReqSkillOrSpell) == reportedReqSpells.end()) { sLog->outError(LOG_FILTER_SQL, "Spell (ID: %u) have not existed spell (ID: %i) in `reqSpell` field in `skill_discovery_template` table", spellId, reqSkillOrSpell); reportedReqSpells.insert(absReqSkillOrSpell); } continue; } // mechanic discovery if (reqSpellInfo->Mechanic != MECHANIC_DISCOVERY && // explicit discovery ability !reqSpellInfo->IsExplicitDiscovery()) { if (reportedReqSpells.find(absReqSkillOrSpell) == reportedReqSpells.end()) { sLog->outError(LOG_FILTER_SQL, "Spell (ID: %u) not have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc" " and not 100%% chance random discovery ability but listed for spellId %u (and maybe more) in `skill_discovery_template` table", absReqSkillOrSpell, spellId); reportedReqSpells.insert(absReqSkillOrSpell); } continue; } SkillDiscoveryStore[reqSkillOrSpell].push_back(SkillDiscoveryEntry(spellId, reqSkillValue, chance)); } else if (reqSkillOrSpell == 0) // skill case { SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId); if (bounds.first == bounds.second) { sLog->outError(LOG_FILTER_SQL, "Spell (ID: %u) not listed in `SkillLineAbility.dbc` but listed with `reqSpell`=0 in `skill_discovery_template` table", spellId); continue; } for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx) SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back(SkillDiscoveryEntry(spellId, reqSkillValue, chance)); } else { sLog->outError(LOG_FILTER_SQL, "Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table", spellId); continue; } ++count; } while (result->NextRow()); if (!ssNonDiscoverableEntries.str().empty()) sLog->outError(LOG_FILTER_SQL, "Some items can't be successfully discovered: have in chance field value < 0.000001 in `skill_discovery_template` DB table . List:\n%s", ssNonDiscoverableEntries.str().c_str()); // report about empty data for explicit discovery spells for (uint32 spell_id = 1; spell_id < sSpellMgr->GetSpellInfoStoreSize(); ++spell_id) { SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell_id); if (!spellEntry) continue; // skip not explicit discovery spells if (!spellEntry->IsExplicitDiscovery()) continue; if (SkillDiscoveryStore.find(int32(spell_id)) == SkillDiscoveryStore.end()) sLog->outError(LOG_FILTER_SQL, "Spell (ID: %u) is 100%% chance random discovery ability but not have data in `skill_discovery_template` table", spell_id); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u skill discovery definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void MapManager::LoadTransports() { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT guid, entry, name, period, ScriptName FROM transports"); if (!result) { sLog->outString(">> Loaded 0 transports. DB table `transports` is empty!"); sLog->outString(); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 lowguid = fields[0].GetUInt32(); uint32 entry = fields[1].GetUInt32(); std::string name = fields[2].GetString(); uint32 period = fields[3].GetUInt32(); uint32 scriptId = sObjectMgr->GetScriptId(fields[4].GetCString()); const GameObjectTemplate* goinfo = sObjectMgr->GetGameObjectTemplate(entry); if (!goinfo) { sLog->outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); continue; } if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) { sLog->outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); continue; } // sLog->outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); std::set<uint32> mapsUsed; Transport* t = new Transport(period, scriptId); if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) // skip transports with empty waypoints list { sLog->outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.", goinfo->moTransport.taxiPathId); delete t; continue; } float x = t->m_WayPoints[0].x; float y = t->m_WayPoints[0].y; float z = t->m_WayPoints[0].z; uint32 mapid = t->m_WayPoints[0].mapid; float o = 1.0f; // creates the Gameobject if (!t->Create(lowguid, entry, mapid, x, y, z, o, 100, 0)) { delete t; continue; } m_Transports.insert(t); for (std::set<uint32>::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) m_TransportsByMap[*i].insert(t); //If we someday decide to use the grid to track transports, here: t->SetMap(sMapMgr->CreateBaseMap(mapid)); t->AddToWorld(); ++count; } while (result->NextRow()); // check transport data DB integrity result = WorldDatabase.Query("SELECT gameobject.guid, gameobject.id, transports.name FROM gameobject, transports WHERE gameobject.id = transports.entry"); if (result) // wrong data found { do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint32 entry = fields[1].GetUInt32(); std::string name = fields[2].GetString(); sLog->outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports must not have any records in `gameobject` or its behavior will be unpredictable/bugged.", entry, name.c_str(), guid); } while (result->NextRow()); } sLog->outString(">> Loaded %u transports in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void CreatureTextMgr::LoadCreatureTexts() { uint32 oldMSTime = getMSTime(); mTextMap.clear(); // for reload case //all currently used temp texts are NOT reset QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound, TextRange FROM creature_text"); if (!result) { sLog.outString(">> Loaded 0 ceature texts. DB table `creature_text` is empty."); return; } uint32 textCount = 0; do { Field* fields = result->Fetch(); CreatureTextEntry temp; temp.entry = fields[0].GetUInt32(); temp.group = fields[1].GetUInt8(); temp.id = fields[2].GetUInt8(); temp.text = fields[3].GetString(); temp.type = ChatMsg(fields[4].GetUInt8()); temp.lang = Language(fields[5].GetUInt8()); temp.probability = fields[6].GetFloat(); temp.emote = Emote(fields[7].GetUInt32()); temp.duration = fields[8].GetUInt32(); temp.sound = fields[9].GetUInt32(); temp.TextRange = CreatureTextRange(fields[10].GetUInt8()); if (temp.sound) { if (!sSoundEntriesStore.LookupEntry(temp.sound)) { sLog.outError("CreatureTextMgr: Entry %u, Group %u in table `creature_text` has Sound %u but sound does not exist.", temp.entry, temp.group, temp.sound); temp.sound = 0; } } if (!GetLanguageDescByID(temp.lang)) { sLog.outError("CreatureTextMgr: Entry %u, Group %u in table `creature_text` using Language %u but Language does not exist.", temp.entry, temp.group, uint32(temp.lang)); temp.lang = LANG_UNIVERSAL; } if (temp.type >= MAX_CHAT_MSG_TYPE) { sLog.outError("CreatureTextMgr: Entry %u, Group %u in table `creature_text` has Type %u but this Chat Type does not exist.", temp.entry, temp.group, uint32(temp.type)); temp.type = CHAT_MSG_SAY; } if (temp.emote) { if (!sEmotesStore.LookupEntry(temp.emote)) { sLog.outError("CreatureTextMgr: Entry %u, Group %u in table `creature_text` has Emote %u but emote does not exist.", temp.entry, temp.group, uint32(temp.emote)); temp.emote = EMOTE_ONESHOT_NONE; } } if (temp.TextRange > TEXT_RANGE_WORLD) { sLog.outError("CreatureTextMgr: Entry %u, Group %u, Id %u in table `creature_text` has incorrect TextRange %u.", temp.entry, temp.group, temp.id, temp.TextRange); temp.TextRange = TEXT_RANGE_NORMAL; } // add the text into our entry's group mTextMap[temp.entry][temp.group].push_back(temp); ++textCount; } while (result->NextRow()); sLog.outString(">> Loaded %u creature texts for %lu creatures in %u ms", textCount, mTextMap.size(), GetMSTimeDiffToNow(oldMSTime)); }
void CreatureTextMgr::LoadCreatureTextLocales() { uint32 oldMSTime = getMSTime(); mLocaleTextMap.clear(); // for reload case QueryResult result = WorldDatabase.Query("SELECT entry, groupid, id, text_loc1, text_loc2, text_loc3, text_loc4, text_loc5, text_loc6, text_loc7, text_loc8 FROM locales_creature_text"); if (!result) return; uint32 textCount = 0; do { Field* fields = result->Fetch(); CreatureTextLocale& loc = mLocaleTextMap[CreatureTextId(fields[0].GetUInt32(), uint32(fields[1].GetUInt8()), uint32(fields[2].GetUInt8()))]; for (uint8 i = TOTAL_LOCALES - 1; i > 0; --i) { LocaleConstant locale = LocaleConstant(i); ObjectMgr::AddLocaleString(fields[3 + i - 1].GetString(), locale, loc.Text); } ++textCount; } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u creature localized texts in %u ms", textCount, GetMSTimeDiffToNow(oldMSTime)); }
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, sCharTitlesStore, dbcPath, "CharTitles.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc"); if (ChatChannelsEntry* chan = const_cast<ChatChannelsEntry*>(sChatChannelsStore.LookupEntry(26))) chan->flags = 0x40009; 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(availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemExtendedCostStore, dbcPath, "ItemExtendedCost.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemLimitCategoryStore, dbcPath, "ItemLimitCategory.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomPropertiesStore, dbcPath, "ItemRandomProperties.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemRandomSuffixStore, dbcPath, "ItemRandomSuffix.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemSetStore, dbcPath, "ItemSet.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLFGDungeonStore, dbcPath, "LFGDungeons.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLightStore, dbcPath, "Light.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLiquidTypeStore, dbcPath, "LiquidType.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sLockStore, dbcPath, "Lock.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMailTemplateStore, dbcPath, "MailTemplate.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc"); // fill data for (uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i) if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) sMapDifficultyMap[MAKE_PAIR32(entry->MapId, entry->Difficulty)] = MapDifficulty(entry->resetTime, entry->maxPlayers, entry->areaTriggerText[0] != '\0'); sMapDifficultyStore.Clear(); LoadDBC(availableDbcLocales, bad_dbc_files, sMovieStore, dbcPath, "Movie.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sOverrideSpellDataStore, dbcPath, "OverrideSpellData.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc"); for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestXPStore, dbcPath, "QuestXP.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestFactionRewardStore, dbcPath, "QuestFactionReward.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sRandomPropertiesPointsStore, dbcPath, "RandPropPoints.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatDistributionStore, dbcPath, "ScalingStatDistribution.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sScalingStatValuesStore, dbcPath, "ScalingStatValues.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineStore, dbcPath, "SkillLine.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSkillLineAbilityStore, dbcPath, "SkillLineAbility.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, 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->path] < entry->index + 1) pathLength[entry->path] = entry->index + 1; } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for (uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); // fill data for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) sTaxiPathNodesByPath[entry->path].set(entry->index, 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 AuctionHouseMgr::LoadAuctionItems() { uint32 oldMSTime = getMSTime(); // data needs to be at first place for Item::LoadFromDB PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTION_ITEMS); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 auction items. DB table `auctionhouse` or `item_instance` is empty!"); return; } uint32 count = 0; do { Field* fields = result->Fetch(); uint32 item_guid = fields[11].GetUInt32(); uint32 itemEntry = fields[12].GetUInt32(); ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry); if (!proto) { sLog->outError(LOG_FILTER_GENERAL, "AuctionHouseMgr::LoadAuctionItems: Unknown item (GUID: %u id: #%u) in auction, skipped.", item_guid, itemEntry); continue; } Item* item = NewItemOrBag(proto); if (!item->LoadFromDB(item_guid, 0, fields, itemEntry)) { delete item; continue; } AddAItem(item); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u auction items in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void OutdoorPvPMgr::InitOutdoorPvP() { uint32 oldMSTime = getMSTime(); // 0 1 QueryResult result = WorldDatabase.Query("SELECT TypeId, ScriptName FROM outdoorpvp_template"); if (!result) { sLog->outErrorDb(">> Loaded 0 outdoor PvP definitions. DB table `outdoorpvp_template` is empty."); sLog->outString(); return; } uint32 count = 0; uint32 typeId = 0; do { Field* fields = result->Fetch(); typeId = fields[0].GetUInt8(); if (DisableMgr::IsDisabledFor(DISABLE_TYPE_OUTDOORPVP, typeId, NULL)) continue; if (typeId >= MAX_OUTDOORPVP_TYPES) { sLog->outErrorDb("Invalid OutdoorPvPTypes value %u in outdoorpvp_template; skipped.", typeId); continue; } OutdoorPvPData* data = new OutdoorPvPData(); OutdoorPvPTypes realTypeId = OutdoorPvPTypes(typeId); data->TypeId = realTypeId; data->ScriptId = sObjectMgr->GetScriptId(fields[1].GetCString()); m_OutdoorPvPDatas[realTypeId] = data; ++count; } while (result->NextRow()); OutdoorPvP* pvp; for (uint8 i = 1; i < MAX_OUTDOORPVP_TYPES; ++i) { OutdoorPvPDataMap::iterator iter = m_OutdoorPvPDatas.find(OutdoorPvPTypes(i)); if (iter == m_OutdoorPvPDatas.end()) { sLog->outErrorDb("Could not initialize OutdoorPvP object for type ID %u; no entry in database.", uint32(i)); continue; } pvp = sScriptMgr->CreateOutdoorPvP(iter->second); if (!pvp) { sLog->outError("Could not initialize OutdoorPvP object for type ID %u; got NULL pointer from script.", uint32(i)); continue; } if (!pvp->SetupOutdoorPvP()) { sLog->outError("Could not initialize OutdoorPvP object for type ID %u; SetupOutdoorPvP failed.", uint32(i)); delete pvp; continue; } m_OutdoorPvPSet.push_back(pvp); } sLog->outString(">> Loaded %u outdoor PvP definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AuctionHouseMgr::DeleteExpiredAuctionsAtStartup() { // Deletes expired auctions. Should be called at server start before loading auctions. // DO NOT USE after auctions are already loaded since this deletes from the DB // and assumes the auctions HAVE NOT been loaded into a list or AuctionEntryMap yet uint32 oldMSTime = getMSTime(); uint32 expirecount = 0; time_t curTime = sWorld->GetGameTime(); // Query the DB to see if there are any expired auctions PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_EXPIRED_AUCTIONS); stmt->setUInt32(0, (uint32)curTime+60); PreparedQueryResult expAuctions = CharacterDatabase.Query(stmt); if (!expAuctions) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> No expired auctions to delete"); return; } do { Field* fields = expAuctions->Fetch(); AuctionEntry* auction = new AuctionEntry(); // Can't use LoadFromDB() because it assumes the auction map is loaded if (!auction->LoadFromFieldList(fields)) { // For some reason the record in the DB is broken (possibly corrupt // faction info). Delete the object and move on. delete auction; continue; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction->bidder==0) { // Cancel the auction, there was no bidder sAuctionMgr->SendAuctionExpiredMail(auction, trans); } else { // Send the item to the winner and money to seller sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); } // Call the appropriate AuctionHouseObject script // ** Do we need to do this while core is still loading? ** sScriptMgr->OnAuctionExpire(GetAuctionsMap(auction->factionTemplateId), auction); // Delete the auction from the DB auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); // Release memory delete auction; ++expirecount; } while (expAuctions->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Deleted %u expired auctions in %u ms", expirecount, GetMSTimeDiffToNow(oldMSTime)); }
void SmartWaypointMgr::LoadFromDB() { uint32 oldMSTime = getMSTime(); for (UNORDERED_MAP<uint32, WPPath*>::iterator itr = waypoint_map.begin(); itr != waypoint_map.end(); ++itr) { for (WPPath::iterator pathItr = itr->second->begin(); pathItr != itr->second->end(); ++pathItr) delete pathItr->second; delete itr->second; } waypoint_map.clear(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_SMARTAI_WP); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 SmartAI Waypoint Paths. DB table `waypoints` is empty."); return; } uint32 count = 0; uint32 total = 0; uint32 last_entry = 0; uint32 last_id = 1; do { Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 id = fields[1].GetUInt32(); float x, y, z; x = fields[2].GetFloat(); y = fields[3].GetFloat(); z = fields[4].GetFloat(); if (last_entry != entry) { waypoint_map[entry] = new WPPath(); last_id = 1; count++; } if (last_id != id) TC_LOG_ERROR("sql.sql", "SmartWaypointMgr::LoadFromDB: Path entry %u, unexpected point id %u, expected %u.", entry, id, last_id); last_id++; (*waypoint_map[entry])[id] = new WayPoint(id, x, y, z); last_entry = entry; total++; } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime)); }
void TicketMgr::LoadSurveys() { // we don't actually load anything into memory here as there's no reason to _lastSurveyId = 0; uint32 oldMSTime = getMSTime(); if (QueryResult result = CharacterDatabase.Query("SELECT MAX(surveyId) FROM gm_surveys")) _lastSurveyId = (*result)[0].GetUInt32(); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded GM Survey count from database in %u ms", GetMSTimeDiffToNow(oldMSTime)); }
void InfoMgr::Initialize() { ASSERT(m_charInfos.size() == 0); sLog->outInfo(LOG_FILTER_SERVER_LOADING, "\n\nInitializing InfoMgr..."); uint32 count; uint32 allStart = getMSTime(); // General stuff uint32 start = allStart; count = 0; if (QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, account, level, zone FROM characters WHERE account != 0")) { do { Field *fields = result->Fetch(); UpdateCharBase(fields[0].GetUInt32() /* guid */, fields[1].GetString() /* name */, fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt32() /* account */, fields[6].GetUInt8() /* level */, fields[7].GetUInt16() /* zone */); ++count; } while (result->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded base for %u characters (%ums)", count, GetMSTimeDiffToNow(start)); // MMR start = getMSTime(); count = 0; if (QueryResult mmrResult = CharacterDatabase.Query("SELECT guid, matchMakerRating, slot FROM character_arena_stats WHERE guid != 0")) { do { Field *fields = mmrResult->Fetch(); UpdateCharMMR(fields[0].GetUInt32() /* guid */, fields[1].GetUInt32() /* MMR */, fields[2].GetUInt8() /* slot */); ++count; } while (mmrResult->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded MMR for %u characters (%ums)", count, GetMSTimeDiffToNow(start)); // Guilds start = getMSTime(); count = 0; if (QueryResult guildResult = CharacterDatabase.Query("SELECT guildid, guid FROM guild_member")) { do { Field *fields = guildResult->Fetch(); UpdateCharGuild(fields[1].GetUInt32(), fields[0].GetUInt32()); ++count; } while (guildResult->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded guild for %u characters (%ums)", count, GetMSTimeDiffToNow(start)); // Groups start = getMSTime(); count = 0; if (QueryResult groupResult = CharacterDatabase.Query("SELECT guid, memberGuid FROM group_member")) { do { Field *fields = groupResult->Fetch(); UpdateCharGroup(fields[1].GetUInt32(), fields[0].GetUInt32()); ++count; } while (groupResult->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded group for %u characters (%ums)", count, GetMSTimeDiffToNow(start)); // Arena teams start = getMSTime(); count = 0; if (QueryResult arenaResult = CharacterDatabase.Query("SELECT arena_team.arenateamid, arena_team.type, arena_team_member.guid FROM arena_team JOIN arena_team_member ON arena_team.arenateamid = arena_team_member.arenateamid")) { do { Field *fields = arenaResult->Fetch(); UpdateCharArenaTeam(fields[2].GetUInt32(), fields[0].GetUInt32(), ArenaTeam::GetSlotByType(fields[1].GetUInt8())); ++count; } while (arenaResult->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u arena teams (%ums)", count, GetMSTimeDiffToNow(start)); // Account char counts start = getMSTime(); count = 0; if (QueryResult charCountResult = CharacterDatabase.Query("SELECT account, COUNT(1) FROM characters WHERE account <> 0 GROUP BY account")) { do { Field *fields = charCountResult->Fetch(); SetAccountCharCount(fields[0].GetUInt32(), fields[1].GetUInt64()); ++count; } while (charCountResult->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded char count for %u accounts (%ums)", count, GetMSTimeDiffToNow(start)); // pets /*start = getMSTime(); count = 0; if (QueryResult pets = CharacterDatabase.Query("SELECT id, entry, owner, modelid, CreatedBySpell, PetType, Reactstate, name, renamed, slot, curhealth, curmana, curhappiness, savetime, abdata, level, exp FROM character_pet")) { do { Field *fields = pets->Fetch(); UpdatePet(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt32(), fields[3].GetUInt32(), fields[4].GetUInt32(), fields[5].GetUInt32(), fields[6].GetUInt8(), fields[7].GetString(), fields[8].GetUInt8(), fields[9].GetUInt8(), fields[10].GetUInt32(), fields[11].GetUInt32(), fields[12].GetUInt32(), fields[13].GetUInt32(), fields[14].GetString(), fields[15].GetUInt8(), fields[16].GetUInt32()); ++count; } while (pets->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded base for %u pets (%ums)", count, GetMSTimeDiffToNow(start)); start = getMSTime(); count = 0; if (QueryResult petAuras = CharacterDatabase.Query("SELECT guid, caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM pet_aura WHERE guid != 0 AND caster_guid != 0")) { do { Field *fields = petAuras->Fetch(); UpdatePetAuras(fields[0].GetUInt32(), fields[1].GetUInt64(), fields[2].GetUInt32(), fields[3].GetUInt8(), fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetInt32(), fields[7].GetInt32(), fields[8].GetInt32(), fields[9].GetInt32(), fields[10].GetInt32(), fields[11].GetInt32(), fields[12].GetInt32(), fields[13].GetInt32(), fields[14].GetUInt8()); ++count; } while (petAuras->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u petauras (%ums)", count, GetMSTimeDiffToNow(start)); start = getMSTime(); count = 0; if (QueryResult petSpells = CharacterDatabase.Query("SELECT guid, spell, active FROM pet_spell WHERE guid != 0")) { do { Field *fields = petSpells->Fetch(); UpdatePetSpells(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt8()); ++count; } while (petSpells->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u petSpells (%ums)", count, GetMSTimeDiffToNow(start)); start = getMSTime(); count = 0; if (QueryResult petSpellCooldowns = CharacterDatabase.Query("SELECT guid, spell, time FROM pet_spell_cooldown WHERE guid != 0")) { do { Field *fields = petSpellCooldowns->Fetch(); UpdatePetSpellCooldowns(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt32()); ++count; } while (petSpellCooldowns->NextRow()); } sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u petSpellCooldowns (%ums)", count, GetMSTimeDiffToNow(start)); // remove this if you want to use petsMap, f.i. find SavedPet by Guid petsMap.clear();*/ sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Done initializing InfoMgr. (%ums)", GetMSTimeDiffToNow(allStart)); }
void SmartAIMgr::LoadSmartAIFromDB() { uint32 oldMSTime = getMSTime(); for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; i++) mEventMap[i].clear(); //Drop Existing SmartAI List PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_SMART_SCRIPTS); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 SmartAI scripts. DB table `smartai_scripts` is empty."); return; } uint32 count = 0; do { Field* fields = result->Fetch(); SmartScriptHolder temp; temp.entryOrGuid = fields[0].GetInt32(); SmartScriptType source_type = (SmartScriptType)fields[1].GetUInt8(); if (source_type >= SMART_SCRIPT_TYPE_MAX) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: invalid source_type (%u), skipped loading.", uint32(source_type)); continue; } if (temp.entryOrGuid >= 0) { switch (source_type) { case SMART_SCRIPT_TYPE_CREATURE: { if (!sObjectMgr->GetCreatureTemplate((uint32)temp.entryOrGuid)) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) does not exist, skipped loading.", uint32(temp.entryOrGuid)); continue; } break; } case SMART_SCRIPT_TYPE_GAMEOBJECT: { if (!sObjectMgr->GetGameObjectTemplate((uint32)temp.entryOrGuid)) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: GameObject entry (%u) does not exist, skipped loading.", uint32(temp.entryOrGuid)); continue; } break; } case SMART_SCRIPT_TYPE_AREATRIGGER: { if (!sAreaTriggerStore.LookupEntry((uint32)temp.entryOrGuid)) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: AreaTrigger entry (%u) does not exist, skipped loading.", uint32(temp.entryOrGuid)); continue; } break; } case SMART_SCRIPT_TYPE_TIMED_ACTIONLIST: break;//nothing to check, really default: TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: not yet implemented source_type %u", (uint32)source_type); continue; } } else { if (!sObjectMgr->GetCreatureData(uint32(abs(temp.entryOrGuid)))) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr::LoadSmartAIFromDB: Creature guid (%u) does not exist, skipped loading.", uint32(abs(temp.entryOrGuid))); continue; } } temp.source_type = source_type; temp.event_id = fields[2].GetUInt16(); temp.link = fields[3].GetUInt16(); temp.event.type = (SMART_EVENT)fields[4].GetUInt8(); temp.event.event_phase_mask = fields[5].GetUInt8(); temp.event.event_chance = fields[6].GetUInt8(); temp.event.event_flags = fields[7].GetUInt8(); temp.event.raw.param1 = fields[8].GetUInt32(); temp.event.raw.param2 = fields[9].GetUInt32(); temp.event.raw.param3 = fields[10].GetUInt32(); temp.event.raw.param4 = fields[11].GetUInt32(); temp.action.type = (SMART_ACTION)fields[12].GetUInt8(); temp.action.raw.param1 = fields[13].GetUInt32(); temp.action.raw.param2 = fields[14].GetUInt32(); temp.action.raw.param3 = fields[15].GetUInt32(); temp.action.raw.param4 = fields[16].GetUInt32(); temp.action.raw.param5 = fields[17].GetUInt32(); temp.action.raw.param6 = fields[18].GetUInt32(); temp.target.type = (SMARTAI_TARGETS)fields[19].GetUInt8(); temp.target.raw.param1 = fields[20].GetUInt32(); temp.target.raw.param2 = fields[21].GetUInt32(); temp.target.raw.param3 = fields[22].GetUInt32(); temp.target.x = fields[23].GetFloat(); temp.target.y = fields[24].GetFloat(); temp.target.z = fields[25].GetFloat(); temp.target.o = fields[26].GetFloat(); //check target if (!IsTargetValid(temp)) continue; // check all event and action params if (!IsEventValid(temp)) continue; // creature entry / guid not found in storage, create empty event list for it and increase counters if (mEventMap[source_type].find(temp.entryOrGuid) == mEventMap[source_type].end()) { ++count; SmartAIEventList eventList; mEventMap[source_type][temp.entryOrGuid] = eventList; } // store the new event mEventMap[source_type][temp.entryOrGuid].push_back(temp); } while (result->NextRow()); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u SmartAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void LoadFromDB() { uint32 oldMSTime = getMSTime(); QueryResult result = CharacterDatabase.Query("SELECT name, crc FROM addons"); if (result) { uint32 count = 0; do { Field* fields = result->Fetch(); std::string name = fields[0].GetString(); uint32 crc = fields[1].GetUInt32(); m_knownAddons.push_back(SavedAddon(name, crc)); ++count; } while (result->NextRow()); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u known addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } else TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 known addons. DB table `addons` is empty!"); oldMSTime = getMSTime(); result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons"); if (result) { uint32 count = 0; uint32 dbcMaxBannedAddon = sBannedAddOnsStore.GetNumRows(); do { Field* fields = result->Fetch(); BannedAddon addon; addon.Id = fields[0].GetUInt32() + dbcMaxBannedAddon; addon.Timestamp = uint32(fields[3].GetUInt64()); std::string name = fields[1].GetString(); std::string version = fields[2].GetString(); MD5(reinterpret_cast<uint8 const*>(name.c_str()), name.length(), addon.NameMD5); MD5(reinterpret_cast<uint8 const*>(version.c_str()), version.length(), addon.VersionMD5); m_bannedAddons.push_back(addon); ++count; } while (result->NextRow()); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u banned addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } }