static bool HandleWpEventCommand(ChatHandler* handler, const char* args) { if (!*args) return false; char* show_str = strtok((char*)args, " "); std::string show = show_str; // Check if ((show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false; char* arg_id = strtok(NULL, " "); uint32 id = 0; if (show == "add") { if (arg_id) id = atoi(arg_id); if (id) { QueryResult result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid = %u", id); if (!result) { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT); stmt->setUInt32(0, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id); } else handler->PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", id); } else { QueryResult result = WorldDatabase.Query("SELECT MAX(guid) FROM waypoint_scripts"); id = result->Fetch()->GetUInt32(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_WAYPOINT_SCRIPT); stmt->setUInt32(0, id + 1); WorldDatabase.Execute(stmt); handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: |r|cff00ffff", id+1); } return true; } if (show == "listid") { if (!arg_id) { handler->PSendSysMessage("%s%s|r", "|cff33ffff", "Wp Event: You must provide waypoint script id."); return true; } id = atoi(arg_id); uint32 a2, a3, a4, a5, a6; float a8, a9, a10, a11; char const* a7; QueryResult result = WorldDatabase.PQuery("SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = %u", id); if (!result) { handler->PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id); return true; } Field* fields; do { fields = result->Fetch(); a2 = fields[0].GetUInt32(); a3 = fields[1].GetUInt32(); a4 = fields[2].GetUInt32(); a5 = fields[3].GetUInt32(); a6 = fields[4].GetUInt32(); a7 = fields[5].GetCString(); a8 = fields[6].GetFloat(); a9 = fields[7].GetFloat(); a10 = fields[8].GetFloat(); a11 = fields[9].GetFloat(); handler->PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, datatext: |r|cff00ffff%s|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } while (result->NextRow()); } if (show == "del") { id = atoi(arg_id); QueryResult result = WorldDatabase.PQuery("SELECT guid FROM waypoint_scripts WHERE guid = %u", id); if (result) { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_SCRIPT); stmt->setUInt32(0, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: Waypoint script removed: ", id); } else handler->PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id); return true; } if (show == "mod") { if (!arg_id) { handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r"); return true; } id = atoi(arg_id); if (!id) { handler->SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r"); return true; } char* arg_2 = strtok(NULL, " "); if (!arg_2) { handler->SendSysMessage("|cffff33ffERROR: No argument present.|r"); return true; } std::string arg_string = arg_2; if ((arg_string != "setid") && (arg_string != "delay") && (arg_string != "command") && (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx") && (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")) { handler->SendSysMessage("|cffff33ffERROR: No valid argument present.|r"); return true; } char* arg_3; std::string arg_str_2 = arg_2; arg_3 = strtok(NULL, " "); if (!arg_3) { handler->SendSysMessage("|cffff33ffERROR: No additional argument present.|r"); return true; } if (arg_str_2 == "setid") { uint32 newid = atoi(arg_3); handler->PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r", "|cff00ff00", "Wp Event: Wypoint scipt guid: ", newid, " id changed: ", id); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_ID); stmt->setUInt32(0, newid); stmt->setUInt32(1, id); WorldDatabase.Execute(stmt); return true; } else { QueryResult result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'", id); if (!result) { handler->SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r"); return true; } if (arg_str_2 == "posx") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_X); stmt->setFloat(0, float(atof(arg_3))); stmt->setUInt32(1, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id); return true; } else if (arg_str_2 == "posy") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Y); stmt->setFloat(0, float(atof(arg_3))); stmt->setUInt32(1, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id); return true; } else if (arg_str_2 == "posz") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_Z); stmt->setFloat(0, float(atof(arg_3))); stmt->setUInt32(1, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id); return true; } else if (arg_str_2 == "orientation") { PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_SCRIPT_O); stmt->setFloat(0, float(atof(arg_3))); stmt->setUInt32(1, id); WorldDatabase.Execute(stmt); handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id); return true; } else if (arg_str_2 == "dataint") { WorldDatabase.PExecute("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'", arg_2, atoi(arg_3), id); // Query can't be a prepared statement handler->PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id); return true; } else { std::string arg_str_3 = arg_3; WorldDatabase.EscapeString(arg_str_3); WorldDatabase.PExecute("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'", arg_2, arg_str_3.c_str(), id); // Query can't be a prepared statement } } handler->PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r", "|cff00ff00", "Waypoint script:", id, arg_2, "updated."); } return true; }
void InstanceSaveManager::LoadResetTimes() { time_t now = time(NULL); time_t today = (now / DAY) * DAY; // NOTE: Use DirectPExecute for tables that will be queried later // get the current reset times for normal instances (these may need to be updated) // these are only kept in memory for InstanceSaves that are loaded later // resettime = 0 in the DB for raid/heroic instances so those are skipped typedef std::pair<uint32 /*PAIR32(map, difficulty)*/, time_t> ResetTimeMapDiffType; typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType; InstResetTimeMapDiffType instResetTime; // index instance ids by map/difficulty pairs for fast reset warning send typedef std::multimap<uint32 /*PAIR32(map, difficulty)*/, uint32 /*instanceid*/ > ResetTimeMapDiffInstances; ResetTimeMapDiffInstances mapDiffResetInstances; QueryResult result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance ORDER BY id ASC"); if(result) { do { Field* fields = result->Fetch(); uint32 instanceId = fields[0].GetUInt32(); // Instances are pulled in ascending order from db and nextInstanceId is initialized with 1, // so if the instance id is used, increment until we find the first unused one for a potential new instance if(sMapMgr->GetNextInstanceId() == instanceId) sMapMgr->SetNextInstanceId(instanceId + 1); // Mark instance id as being used sMapMgr->RegisterInstanceId(instanceId); if(time_t resettime = time_t(fields[3].GetUInt32())) { uint32 mapid = fields[1].GetUInt16(); uint32 difficulty = fields[2].GetUInt8(); instResetTime[instanceId] = ResetTimeMapDiffType(MAKE_PAIR32(mapid, difficulty), resettime); mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid, difficulty), instanceId)); } } while(result->NextRow()); // update reset time for normal instances with the max creature respawn time + X hours if(PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_GET_MAX_CREATURE_RESPAWNS))) { do { Field* fields = result->Fetch(); uint32 instance = fields[1].GetUInt32(); time_t resettime = time_t(fields[0].GetUInt32() + 2 * HOUR); InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance); if(itr != instResetTime.end() && itr->second.second != resettime) { CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance); itr->second.second = resettime; } } while(result->NextRow()); } // schedule the reset times for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) if(itr->second.second > now) ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first), Difficulty(PAIR32_HIPART(itr->second.first)), itr->first)); } // load the global respawn times for raid/heroic instances uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); if(result) { do { Field* fields = result->Fetch(); uint32 mapid = fields[0].GetUInt16(); Difficulty difficulty = Difficulty(fields[1].GetUInt32()); uint64 oldresettime = fields[2].GetUInt32(); MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty); if(!mapDiff) { sLog->outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid, difficulty); continue; } // update the reset time if the hour in the configs changes uint64 newresettime = (oldresettime / DAY) * DAY + diff; if(oldresettime != newresettime) CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '%u' WHERE mapid = '%u' AND difficulty = '%u'", uint32(newresettime), mapid, difficulty); SetResetTimeFor(mapid, difficulty, newresettime); } while(result->NextRow()); } ResetTimeMapDiffInstances::const_iterator in_itr; // calculate new global reset times for expired instances and those that have never been reset yet // add the global reset times to the priority queue for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) { uint32 map_diff_pair = itr->first; uint32 mapid = PAIR32_LOPART(map_diff_pair); Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); MapDifficulty const* mapDiff = &itr->second; if(!mapDiff->resetTime) continue; // the reset_delay must be at least one day uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY); if(period < DAY) period = DAY; time_t t = GetResetTimeFor(mapid, difficulty); if(!t) { // initialize the reset time t = today + period + diff; CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u', '%u', '%u')", mapid, difficulty, (uint32)t); } if(t < now) { // assume that expired instances have already been cleaned // calculate the next reset time t = (t / DAY) * DAY; t += ((today - t) / period + 1) * period + diff; CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); } SetResetTimeFor(mapid, difficulty, t); // schedule the global reset/warning uint8 type; for(type = 1; type < 4; ++type) if(t - ResetTimeDelay[type-1] > now) break; ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, mapid, difficulty, 0)); for(in_itr = mapDiffResetInstances.lower_bound(map_diff_pair); in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr) ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, mapid, difficulty, in_itr->second)); } }
void AchievementGlobalMgr::LoadRewards() { 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) { barGoLink bar(1); bar.step(); sLog.outString(""); sLog.outErrorDb(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty."); return; } barGoLink bar(result->GetRowCount()); do { bar.step(); Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); if (!sAchievementStore.LookupEntry(entry)) { 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].GetCppString(); reward.text = fields[6].GetCppString(); if ((reward.titleId[0]==0)!=(reward.titleId[1]==0)) sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) only for one from teams.", entry, reward.titleId[0], reward.titleId[1]); // 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 (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_A`, 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 (!objmgr.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) not have sender data but have item reward, item will not rewarded", entry); if (!reward.subject.empty()) sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail subject.", entry); if (!reward.text.empty()) sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail text.", entry); } if (reward.itemId) { if (!objmgr.GetItemPrototype(reward.itemId)) { sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will be without item.", entry, reward.itemId); reward.itemId = 0; } } m_achievementRewards[entry] = reward; } while (result->NextRow()); delete result; sLog.outString(); sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); }
void CreatureGroupManager::LoadCreatureFormations() { //Clear existing map CreatureGroupMap.clear(); //Check Integrity of the table QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`leaderGUID`) FROM `creature_formations`"); if(!result) { sLog.outErrorDb(" ...an error occured while loading the table `creature_formations` ( maybe it doesn't exist ?)\n"); return; } delete result; //Get group data result = WorldDatabase.PQuery("SELECT `leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI` FROM `creature_formations` ORDER BY `leaderGUID`"); if(!result) { sLog.outErrorDb("The table `creature_formations` is empty or corrupted"); return; } uint32 total_records = result->GetRowCount(); barGoLink bar( total_records); Field *fields; FormationInfo *group_member; //Loading data... do { fields = result->Fetch(); bar.step(); //Load group member data group_member = new FormationInfo; group_member->leaderGUID = fields[0].GetUInt32(); uint32 memberGUID = fields[1].GetUInt32(); group_member->groupAI = fields[4].GetUInt8(); //If creature is group leader we may skip loading of dist/angle if(group_member->leaderGUID != memberGUID) { group_member->follow_dist = fields[2].GetUInt32(); group_member->follow_angle = fields[3].GetUInt32(); } // check data correctness { QueryResult* result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE guid = %u", group_member->leaderGUID); if(!result) { sLog.outErrorDb("creature_formations table leader guid %u incorrect (not exist)", group_member->leaderGUID); continue; } result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE guid = %u", memberGUID); if(!result) { sLog.outErrorDb("creature_formations table member guid %u incorrect (not exist)", memberGUID); continue; } } CreatureGroupMap[memberGUID] = group_member; } while(result->NextRow()) ; sLog.outString(); sLog.outString( ">> Loaded %u creatures in formations", total_records ); sLog.outString(); //Free some heap delete result; }
void SystemMgr::LoadScriptTexts() { outstring_log("evo-X: Loading Script Texts..."); LoadMangosStrings(SD2Database,"script_texts",TEXT_SOURCE_RANGE,1+(TEXT_SOURCE_RANGE*2)); QueryResult* pResult = SD2Database.PQuery("SELECT entry, sound, type, language, emote FROM script_texts"); outstring_log("evo-X: Loading Script Texts additional data..."); if (pResult) { barGoLink bar(pResult->GetRowCount()); uint32 uiCount = 0; do { bar.step(); Field* pFields = pResult->Fetch(); StringTextData pTemp; int32 iId = pFields[0].GetInt32(); pTemp.uiSoundId = pFields[1].GetUInt32(); pTemp.uiType = pFields[2].GetUInt32(); pTemp.uiLanguage = pFields[3].GetUInt32(); pTemp.uiEmote = pFields[4].GetUInt32(); if (iId >= 0) { error_db_log("evo-X: Entry %i in table `script_texts` is not a negative value.", iId); continue; } if (iId > TEXT_SOURCE_RANGE || iId <= TEXT_SOURCE_RANGE*2) { error_db_log("evo-X: Entry %i in table `script_texts` is out of accepted entry range for table.", iId); continue; } if (pTemp.uiSoundId) { if (!GetSoundEntriesStore()->LookupEntry(pTemp.uiSoundId)) error_db_log("evo-X: Entry %i in table `script_texts` has soundId %u but sound does not exist.", iId, pTemp.uiSoundId); } if (!GetLanguageDescByID(pTemp.uiLanguage)) error_db_log("evo-X: Entry %i in table `script_texts` using Language %u but Language does not exist.", iId, pTemp.uiLanguage); if (pTemp.uiType > CHAT_TYPE_ZONE_YELL) error_db_log("evo-X: Entry %i in table `script_texts` has Type %u but this Chat Type does not exist.", iId, pTemp.uiType); m_mTextDataMap[iId] = pTemp; ++uiCount; } while (pResult->NextRow()); outstring_log(""); outstring_log(">> Loaded %u additional Script Texts data.", uiCount); } else { barGoLink bar(1); bar.step(); outstring_log(""); outstring_log(">> Loaded 0 additional Script Texts data. DB table `script_texts` is empty."); } }
void MapPersistentStateManager::LoadCreatureRespawnTimes() { // remove outdated data CharacterDatabase.DirectExecute("DELETE FROM creature_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); uint32 count = 0; // 0 1 2 3 4 5 6 QueryResult* result = CharacterDatabase.Query("SELECT guid, respawntime, map, instance, difficulty, resettime, encountersMask FROM creature_respawn LEFT JOIN instance ON instance = id"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 creature respawn time."); return; } BarGoLink bar(result->GetRowCount()); do { Field* fields = result->Fetch(); bar.step(); uint32 loguid = fields[0].GetUInt32(); uint64 respawn_time = fields[1].GetUInt64(); uint32 mapId = fields[2].GetUInt32(); uint32 instanceId = fields[3].GetUInt32(); uint8 difficulty = fields[4].GetUInt8(); time_t resetTime = (time_t)fields[5].GetUInt64(); uint32 completedEncounters = fields[6].GetUInt32(); CreatureData const* data = sObjectMgr.GetCreatureData(loguid); if (!data) continue; MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); if (!mapEntry) continue; if (instanceId) // In instance - mapId must be data->mapid and mapEntry must be Instanceable { if (mapId != data->mapid || !mapEntry->Instanceable()) continue; } else // Not in instance, mapEntry must not be Instanceable { if (mapEntry->Instanceable()) continue; } if (difficulty >= (!mapEntry->Instanceable() ? REGULAR_DIFFICULTY + 1 : (mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))) continue; MapPersistentState* state = AddPersistentState(mapEntry, instanceId, Difficulty(difficulty), resetTime, mapEntry->IsDungeon(), true, true, completedEncounters); if (!state) continue; state->SetCreatureRespawnTime(loguid, time_t(respawn_time)); ++count; } while (result->NextRow()); delete result; sLog.outString(">> Loaded %u creature respawn times", count); sLog.outString(); }
void WorldSession::HandleTurnInPetitionOpcode (WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); // ok WorldPacket data; uint64 petitionguid; uint32 ownerguidlo; std::string name; recv_data >> petitionguid; sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); // data QueryResult result = CharacterDatabase.PQuery("SELECT ownerguid, name FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if (result) { Field *fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); } else { sLog->outError("petition table has broken data!"); return; } if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32) PETITION_TURN_ALREADY_IN_GUILD; // already in guild _player->GetSession()->SendPacket(&data); return; } if (_player->GetGUIDLow() != ownerguidlo) return; // signs uint8 signs; result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if (result) signs = uint8(result->GetRowCount()); else signs = 0; if (signs < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32) PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures... SendPacket(&data); return; } if (sObjectMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); return; } // and at last charter item check Item *item = _player->GetItemByGuid(petitionguid); if (!item) return; // delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // register guild and add guildmaster sObjectMgr->AddGuild(guild); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); guild->AddMember(fields[0].GetUInt64()); result->NextRow(); } SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); CharacterDatabase.CommitTransaction(trans); // created sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32) PETITION_TURN_OK; SendPacket(&data); }
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) { pPlayer->PlayerTalkClass->ClearMenus(); switch(uiAction) { case GOSSIP_ACTION_INFO_DEF+1: { pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_BATTLE, BOUNTY_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5, "", 0, true); pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_BATTLE, BOUNTY_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6, "", 0, true); pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_BATTLE, BOUNTY_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7, "", 0, true); pPlayer->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_BATTLE, BOUNTY_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8, "", 0, true); pPlayer->PlayerTalkClass->SendGossipMenu(365, pCreature->GetGUID()); break; } case GOSSIP_ACTION_INFO_DEF+2: { QueryResult Bounties = CharacterDatabase.PQuery("SELECT * FROM bounties"); if(!Bounties) { pPlayer->PlayerTalkClass->SendCloseGossip(); return false; } #if SET_CURRENCY == 0 if( Bounties->GetRowCount() > 1) { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); do { Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " gold"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); }while(Bounties->NextRow()); } else { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " gold"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); } #endif #if SET_CURRENCY == 1 if( Bounties->GetRowCount() > 1) { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); do { Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " honor"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); }while(Bounties->NextRow()); } else { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " honor"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); } #endif #if SET_CURRENCY == 2 if( Bounties->GetRowCount() > 1) { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); do { Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " coins"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); }while(Bounties->NextRow()); } else { pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, "Bounties: ", GOSSIP_SENDER_MAIN, 1); Field * fields = Bounties->Fetch(); std::string option; QueryResult name = CharacterDatabase.PQuery("SELECT name FROM characters WHERE guid='%u'", fields[0].GetUInt64()); Field * names = name->Fetch(); option = names[0].GetString(); option +=" "; option += fields[1].GetString(); option += " coins"; pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_BATTLE, option, GOSSIP_SENDER_MAIN, 1); } #endif pPlayer->PlayerTalkClass->SendGossipMenu(878, pCreature->GetGUID()); break; } case GOSSIP_ACTION_INFO_DEF+3: { pPlayer->PlayerTalkClass->SendCloseGossip(); break; } case GOSSIP_ACTION_INFO_DEF+4: { CharacterDatabase.PExecute("TRUNCATE TABLE bounties"); pPlayer->PlayerTalkClass->SendCloseGossip(); break; } } return true; }
static bool HandleGameObjectTargetCommand(ChatHandler* handler, char const* args) { Player* player = handler->GetSession()->GetPlayer(); QueryResult result; GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr->GetActiveEventList(); if (*args) { // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r char* id = handler->extractKeyFromLink((char*)args, "Hgameobject_entry"); if (!id) return false; uint32 objectId = atol(id); if (objectId) result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), objectId); else { std::string name = id; WorldDatabase.EscapeString(name); result = WorldDatabase.PQuery( "SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ " "FROM gameobject, gameobject_template WHERE gameobject_template.entry = gameobject.id AND map = %i AND name "_LIKE_" "_CONCAT3_("'%%'", "'%s'", "'%%'")" ORDER BY order_ ASC LIMIT 1", player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), name.c_str()); } } else { std::ostringstream eventFilter; eventFilter << " AND (eventEntry IS NULL "; bool initString = true; for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr) { if (initString) { eventFilter << "OR eventEntry IN (" << *itr; initString = false; } else eventFilter << ',' << *itr; } if (!initString) eventFilter << "))"; else eventFilter << ')'; result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, phaseMask, " "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " "LEFT OUTER JOIN game_event_gameobject on gameobject.guid = game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10", handler->GetSession()->GetPlayer()->GetPositionX(), handler->GetSession()->GetPlayer()->GetPositionY(), handler->GetSession()->GetPlayer()->GetPositionZ(), handler->GetSession()->GetPlayer()->GetMapId(), eventFilter.str().c_str()); } if (!result) { handler->SendSysMessage(LANG_COMMAND_TARGETOBJNOTFOUND); return true; } bool found = false; float x, y, z, o; uint32 guidLow, id; uint16 mapId, phase; uint32 poolId; do { Field* fields = result->Fetch(); guidLow = fields[0].GetUInt32(); id = fields[1].GetUInt32(); x = fields[2].GetFloat(); y = fields[3].GetFloat(); z = fields[4].GetFloat(); o = fields[5].GetFloat(); mapId = fields[6].GetUInt16(); phase = fields[7].GetUInt16(); poolId = sPoolMgr->IsPartOfAPool<GameObject>(guidLow); if (!poolId || sPoolMgr->IsSpawnedObject<GameObject>(guidLow)) found = true; } while (result->NextRow() && !found); if (!found) { handler->PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); return false; } GameObjectTemplate const* objectInfo = sObjectMgr->GetGameObjectTemplate(id); if (!objectInfo) { handler->PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST, id); return false; } GameObject* target = handler->GetSession()->GetPlayer()->GetMap()->GetGameObject(MAKE_NEW_GUID(guidLow, id, HIGHGUID_GAMEOBJECT)); handler->PSendSysMessage(LANG_GAMEOBJECT_DETAIL, guidLow, objectInfo->name.c_str(), guidLow, id, x, y, z, mapId, o, phase); if (target) { int32 curRespawnDelay = int32(target->GetRespawnTimeEx() - time(NULL)); if (curRespawnDelay < 0) curRespawnDelay = 0; std::string curRespawnDelayStr = secsToTimeString(curRespawnDelay, true); std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str()); } return true; }
void LootMgr::LoadLootTables(const char* szTableName, LootStore* LootTable) { vector< pair< uint32, vector< tempy > > > db_cache; vector< pair< uint32, vector< tempy > > >::iterator itr; db_cache.reserve(10000); LootStore::iterator tab; QueryResult* result = WorldDatabase.Query("SELECT * FROM %s ORDER BY entryid ASC", szTableName); if(!result) { sLog.Error("LootMgr", "Loading loot from table %s failed.", szTableName); return; } uint32 entry_id = 0; uint32 last_entry = 0; uint32 total = (uint32) result->GetRowCount(); int pos = 0; vector< tempy > ttab; tempy t; do { Field* fields = result->Fetch(); entry_id = fields[ 0 ].GetUInt32(); if(entry_id < last_entry) { sLog.Error("LootMgr", "WARNING: Out of order loot table being loaded."); return; } if(entry_id != last_entry) { if(last_entry != 0) db_cache.push_back(make_pair(last_entry, ttab)); ttab.clear(); } t.itemid = fields[ 1 ].GetUInt32(); t.chance = fields[ 2 ].GetFloat(); t.chance_2 = fields[ 3 ].GetFloat(); t.chance3 = fields[ 4 ].GetFloat(); t.chance4 = fields[ 5 ].GetFloat(); t.mincount = fields[ 6 ].GetUInt32(); t.maxcount = fields[ 7 ].GetUInt32(); ttab.push_back(t); last_entry = entry_id; } while(result->NextRow()); //last list was not pushed in if(last_entry != 0 && ttab.size()) db_cache.push_back(make_pair(last_entry, ttab)); pos = 0; total = (uint32)db_cache.size(); ItemPrototype* proto; uint32 itemid; for(itr = db_cache.begin(); itr != db_cache.end(); ++itr) { entry_id = (*itr).first; if(LootTable->end() == LootTable->find(entry_id)) { StoreLootList list; list.count = static_cast< uint32 >(itr->second.size()); list.items = new StoreLootItem[list.count]; uint32 ind = 0; for(vector< tempy >::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) { //Omit items that are not in db to prevent future bugs itemid = itr2->itemid; proto = ItemPrototypeStorage.LookupEntry(itemid); if(!proto) { list.items[ind].item.itemproto = NULL; Log.Error("LootMgr", "Loot for %u contains non-existant item %u . (%s)", entry_id, itemid, szTableName); } else { list.items[ind].item.itemproto = proto; list.items[ind].item.displayid = proto->DisplayInfoID; list.items[ind].chance = itr2->chance; list.items[ind].chance2 = itr2->chance_2; list.items[ind].chance3 = itr2->chance3; list.items[ind].chance4 = itr2->chance4; list.items[ind].mincount = itr2->mincount; list.items[ind].maxcount = itr2->maxcount; if( proto->HasFlag( ITEM_FLAG_FREE_FOR_ALL ) ) list.items[ ind ].ffa_loot = 1; else list.items[ ind ].ffa_loot = 0; if(LootTable == &GOLoot) { if(proto->Class == ITEM_CLASS_QUEST) { sQuestMgr.SetGameObjectLootQuest(itr->first, itemid); quest_loot_go[entry_id].insert(proto->ItemId); } } } ind++; } (*LootTable)[entry_id] = list; } } sLog.outString(" %d loot templates loaded from %s", db_cache.size(), szTableName); delete result; }
void SQLStorage::Load () { uint32 maxi; Field *fields; QueryResult *result = sDatabase.PQuery("SELECT MAX(`%s`) FROM `%s`",entry_field,table); if(!result) { sLog.outError("Error loading `%s` table (not exist?)\n",table); exit(1); // Stop server at loading non exited table or not accessable table } maxi= (*result)[0].GetUInt32()+1; delete result; result = sDatabase.PQuery("SELECT COUNT(*) FROM `%s`",table); if(result) { fields = result->Fetch(); RecordCount=fields[0].GetUInt32(); delete result; } else RecordCount = 0; result = sDatabase.PQuery("SELECT * FROM `%s`",table); if(!result) { sLog.outError("`%s` table is empty!\n",table); RecordCount = 0; return; } uint32 recordsize=0; uint32 offset=0; if(iNumFields!=result->GetFieldCount()) { RecordCount = 0; sLog.outError("Error in `%s` table, probably sql file format was updated (there should be %d fields in sql).\n",table,iNumFields); delete result; exit(1); // Stop server at loading broken or non-compatiable table. } if(sizeof(char*)==sizeof(uint32)) recordsize=4*iNumFields; else { //get struct size uint32 sc=0; for(uint32 x=0;x<iNumFields;x++) if(format[x]==FT_STRING) sc++; recordsize=(iNumFields-sc)*4+sc*sizeof(char*); } char** newIndex=new char*[maxi]; memset(newIndex,0,maxi*sizeof(char*)); char * _data= new char[RecordCount *recordsize]; uint32 count=0; barGoLink bar( RecordCount ); do { fields = result->Fetch(); bar.step(); char *p=(char*)&_data[recordsize*count]; newIndex[fields[0].GetUInt32()]=p; offset=0; for(uint32 x=0;x<iNumFields;x++) switch(format[x]) { case FT_INT: *((uint32*)(&p[offset]))=fields[x].GetUInt32(); offset+=sizeof(uint32); break; case FT_FLOAT: *((float*)(&p[offset]))=fields[x].GetFloat(); offset+=sizeof(float); break; case FT_STRING: char const* tmp = fields[x].GetString(); char* st; if(!tmp) { st=new char[1]; *st=0; } else { uint32 l=strlen(tmp)+1; st=new char[l]; memcpy(st,tmp,l); } *((char**)(&p[offset]))=st; offset+=sizeof(char*); break; } count++; }while( result->NextRow() ); delete result; pIndex =newIndex; MaxEntry=maxi; data=_data; }
void LootMgr::LoadLootProp() { QueryResult* result = WorldDatabase.Query("SELECT * FROM item_randomprop_groups"); uint32 id, eid; RandomProps* rp; ItemRandomSuffixEntry* rs; float ch; if(result) { map<uint32, RandomPropertyVector>::iterator itr; do { id = result->Fetch()[0].GetUInt32(); eid = result->Fetch()[1].GetUInt32(); ch = result->Fetch()[2].GetFloat(); rp = dbcRandomProps.LookupEntryForced(eid); if(rp == NULL) { sLog.Error("LoadLootProp", "RandomProp group %u references non-existent randomprop %u.", id, eid); continue; } itr = _randomprops.find(id); if(itr == _randomprops.end()) { RandomPropertyVector v; v.push_back(make_pair(rp, ch)); _randomprops.insert(make_pair(id, v)); } else { itr->second.push_back(make_pair(rp, ch)); } } while(result->NextRow()); delete result; } result = WorldDatabase.Query("SELECT * FROM item_randomsuffix_groups"); if(result) { map<uint32, RandomSuffixVector>::iterator itr; do { id = result->Fetch()[0].GetUInt32(); eid = result->Fetch()[1].GetUInt32(); ch = result->Fetch()[2].GetFloat(); rs = dbcItemRandomSuffix.LookupEntryForced(eid); if(rs == NULL) { sLog.Error("LoadLootProp", "RandomSuffix group %u references non-existent randomsuffix %u.", id, eid); continue; } itr = _randomsuffix.find(id); if(itr == _randomsuffix.end()) { RandomSuffixVector v; v.push_back(make_pair(rs, ch)); _randomsuffix.insert(make_pair(id, v)); } else { itr->second.push_back(make_pair(rs, ch)); } } while(result->NextRow()); delete result; } }
static bool HandleWpShowCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // first arg: on, off, first, last char* show_str = strtok((char*)args, " "); if (!show_str) return false; // second arg: GUID (optional, if a creature is selected) char* guid_str = strtok((char*)NULL, " "); uint32 pathid = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a PathID? if (!guid_str) { // No PathID provided // -> Player must have selected a creature if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } pathid = target->GetWaypointPath(); } else { // PathID provided // Warn if player also selected a creature // -> Creature selection is ignored <- if (target) handler->SendSysMessage(LANG_WAYPOINT_CREATSELECTED); pathid = atoi((char*)guid_str); } std::string show = show_str; uint32 Maxpoint; //handler->PSendSysMessage("wpshow - show: %s", show); // Show info for the selected waypoint if (show == "info") { // Check if the user did specify a visual waypoint if (target->GetEntry() != VISUAL_WAYPOINT) { handler->PSendSysMessage(LANG_WAYPOINT_VP_SELECT); handler->SetSentErrorMessage(true); return false; } QueryResult result = WorldDatabase.PQuery("SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow()); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM); return true; } handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r"); do { Field* fields = result->Fetch(); pathid = fields[0].GetUInt32(); uint32 point = fields[1].GetUInt32(); uint32 delay = fields[2].GetUInt32(); uint32 flag = fields[3].GetUInt32(); uint32 ev_id = fields[4].GetUInt32(); uint32 ev_chance = fields[5].GetUInt32(); handler->PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid); handler->PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay); handler->PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag); handler->PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id); handler->PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance); } while (result->NextRow()); return true; } if (show == "on") { QueryResult result = WorldDatabase.PQuery("SELECT point, position_x, position_y, position_z FROM waypoint_data WHERE id = '%u'", pathid); if (!result) { handler->SendSysMessage("|cffff33ffPath no found.|r"); handler->SetSentErrorMessage(true); return false; } handler->PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid); // Delete all visuals for this NPC QueryResult result2 = WorldDatabase.PQuery("SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid); if (result2) { bool hasError = false; do { Field* fields = result2->Fetch(); uint32 wpguid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpguid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpguid); hasError = true; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); stmt->setUInt32(0, wpguid); WorldDatabase.Execute(stmt); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result2->NextRow()); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } } do { Field* fields = result->Fetch(); uint32 point = fields[0].GetUInt32(); float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); float o = chr->GetOrientation(); Creature* wpCreature = new Creature; if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; return false; } // Set "wpguid" column to the visual waypoint PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); stmt->setInt32(0, int32(wpCreature->GetGUIDLow())); stmt->setUInt32(1, pathid); stmt->setUInt32(2, point); WorldDatabase.Execute(stmt); wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); if (!wpCreature->LoadCreatureFromDB(wpCreature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; return false; } if (target) { wpCreature->SetDisplayId(target->GetDisplayId()); wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); wpCreature->SetLevel(point > STRONG_MAX_LEVEL ? STRONG_MAX_LEVEL : point); } } while (result->NextRow()); handler->SendSysMessage("|cff00ff00Showing the current creature's path.|r"); return true; } if (show == "first") { handler->PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid); QueryResult result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z FROM waypoint_data WHERE point='1' AND id = '%u'", pathid); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); } return true; } if (show == "last") { handler->PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid); QueryResult result = WorldDatabase.PQuery("SELECT MAX(point) FROM waypoint_data WHERE id = '%u'", pathid); if (result) Maxpoint = (*result)[0].GetUInt32(); else Maxpoint = 0; result = WorldDatabase.PQuery("SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE point ='%u' AND id = '%u'", Maxpoint, pathid); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid); handler->SetSentErrorMessage(true); return false; } Field* fields = result->Fetch(); float x = fields[0].GetFloat(); float y = fields[1].GetFloat(); float z = fields[2].GetFloat(); float o = fields[3].GetFloat(); uint32 id = VISUAL_WAYPOINT; Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); Creature* creature = new Creature; if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; return false; } if (target) { creature->SetDisplayId(target->GetDisplayId()); creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); } return true; } if (show == "off") { QueryResult result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1); if (!result) { handler->SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); handler->SetSentErrorMessage(true); return false; } bool hasError = false; do { Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(guid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); hasError = true; PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE); stmt->setUInt32(0, guid); WorldDatabase.Execute(stmt); } else { creature->CombatStop(); creature->DeleteFromDB(); creature->AddObjectToRemoveList(); } } while (result->NextRow()); // set "wpguid" column to "empty" - no visual waypoint spawned PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WOLRD_UPD_ALL_WAYPOINT_DATA_WPGUID); WorldDatabase.Execute(stmt); //WorldDatabase.PExecute("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); if (hasError) { handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR1); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR2); handler->PSendSysMessage(LANG_WAYPOINT_TOOFAR3); } handler->SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); return true; } handler->PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r"); return true; }
static bool HandleWpModifyCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // first arg: add del text emote spell waittime move char* show_str = strtok((char*)args, " "); if (!show_str) { return false; } std::string show = show_str; // Check // Remember: "show" must also be the name of a column! if ((show != "delay") && (show != "action") && (show != "action_chance") && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd") ) { return false; } // Next arg is: <PATHID> <WPNUM> <ARGUMENT> char* arg_str = NULL; // Did user provide a GUID // or did the user select a creature? // -> variable lowguid is filled with the GUID of the NPC uint32 pathid = 0; uint32 point = 0; uint32 wpGuid = 0; Creature* target = handler->getSelectedCreature(); if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); return false; } // The visual waypoint wpGuid = target->GetGUIDLow(); // User did select a visual waypoint? // Check the creature QueryResult result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE wpguid = %u", wpGuid); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); // Select waypoint number from database // Since we compare float values, we have to deal with // some difficulties. // Here we search for all waypoints that only differ in one from 1 thousand // (0.001) - There is no other way to compare C++ floats with mySQL floats // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html const char* maxDIFF = "0.01"; result = WorldDatabase.PQuery("SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s) and (abs(position_y - %f) <= %s) and (abs(position_z - %f) <= %s)", target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); if (!result) { handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); return true; } } do { Field* fields = result->Fetch(); pathid = fields[0].GetUInt32(); point = fields[1].GetUInt32(); } while (result->NextRow()); // We have the waypoint number and the GUID of the "master npc" // Text is enclosed in "<>", all other arguments not arg_str = strtok((char*)NULL, " "); // Check for argument if (show != "del" && show != "move" && arg_str == NULL) { handler->PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); return false; } if (show == "del" && target) { handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); // wpCreature Creature* wpCreature = NULL; if (wpGuid != 0) { wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->CombatStop(); wpCreature->DeleteFromDB(); wpCreature->AddObjectToRemoveList(); } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); stmt->setUInt32(0, pathid); stmt->setUInt32(1, point); WorldDatabase.Execute(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POINT); stmt->setUInt32(0, pathid); stmt->setUInt32(1, point); WorldDatabase.Execute(stmt); handler->PSendSysMessage(LANG_WAYPOINT_REMOVED); return true; } // del if (show == "move" && target) { handler->PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid); Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); { // wpCreature Creature* wpCreature = NULL; // What to do: // Move the visual spawnpoint // Respawn the owner of the waypoints if (wpGuid != 0) { wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT)); wpCreature->CombatStop(); wpCreature->DeleteFromDB(); wpCreature->AddObjectToRemoveList(); // re-create Creature* wpCreature2 = new Creature; if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0, 0, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; return false; } wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); //TODO: Should we first use "Create" then use "LoadFromDB"? if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetDBTableGUIDLow(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; return false; } //sMapMgr->GetMap(npcCreature->GetMapId())->Add(wpCreature2); } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION); stmt->setFloat(0, chr->GetPositionX()); stmt->setFloat(1, chr->GetPositionY()); stmt->setFloat(2, chr->GetPositionZ()); stmt->setUInt32(3, pathid); stmt->setUInt32(4, point); WorldDatabase.Execute(stmt); handler->PSendSysMessage(LANG_WAYPOINT_CHANGED); } return true; } // move const char *text = arg_str; if (text == 0) { // show_str check for present in list of correct values, no sql injection possible WorldDatabase.PExecute("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'", show_str, pathid, point); // Query can't be a prepared statement } else { // show_str check for present in list of correct values, no sql injection possible std::string text2 = text; WorldDatabase.EscapeString(text2); WorldDatabase.PExecute("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'", show_str, text2.c_str(), pathid, point); // Query can't be a prepared statement } handler->PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); return true; }
void LoadDataFromDataBase() { MultiKillLoaded = true; MultiKillInfo.clear(); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Loading MultiKill..."); uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.PQuery("SELECT `Count`, `BuffFirst`, `Gold`, `Sound`, `TrinityStringId`, `Honor`, `Type`, `KillCredit`, `BuffSecond` FROM `world_multikill`"); if (!result) { TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> `world_multikill` is empty"); return; } uint16 count = 0; MultiKillMin = 0; MultiKillMax = 0; do { Field* fields = result->Fetch(); MultiKillTemplate MultiKillTemp; MultiKillTemp.Count = fields[0].GetUInt8(); MultiKillTemp.BuffFirst = fields[1].GetUInt32(); MultiKillTemp.Gold = fields[2].GetUInt16(); MultiKillTemp.Sound = fields[3].GetUInt32(); MultiKillTemp.Text = fields[4].GetUInt32(); MultiKillTemp.Honor = fields[5].GetUInt32(); MultiKillTemp.Type = fields[6].GetUInt8(); MultiKillTemp.KillCredit = fields[7].GetUInt32(); MultiKillTemp.BuffSecond = fields[8].GetUInt32(); if (MultiKillTemp.Type > KILL_TYPE_FIRST) { TC_LOG_ERROR(LOG_FILTER_SQL, "MultiKill: KillType (Type: %u) non-existing", MultiKillTemp.Type); continue; } if (MultiKillTemp.Type == KILL_TYPE_FIRST && MultiKillTemp.Count != 0) { TC_LOG_ERROR(LOG_FILTER_SQL, "MultiKill: FirstKill (Type: %u) need count = 0", MultiKillTemp.Type); continue; } if (MultiKillTemp.BuffFirst != 0 && !sSpellMgr->GetSpellInfo(MultiKillTemp.BuffFirst)) { TC_LOG_ERROR(LOG_FILTER_SQL, "MultiKill: BuffFirst spell (ID: %u) non-existing", MultiKillTemp.BuffFirst); MultiKillTemp.BuffFirst = 0; } if (MultiKillTemp.BuffSecond != 0 && !sSpellMgr->GetSpellInfo(MultiKillTemp.BuffSecond)) { TC_LOG_ERROR(LOG_FILTER_SQL, "MultiKill: BuffSecond spell (ID: %u) non-existing", MultiKillTemp.BuffSecond); MultiKillTemp.BuffSecond = 0; } if (MultiKillTemp.Type == KILL_TYPE_MULTI && (MultiKillMin == 0 || MultiKillMin > MultiKillTemp.Count)) MultiKillMin = MultiKillTemp.Count; if (MultiKillTemp.Type == KILL_TYPE_MULTI && (MultiKillMax == 0 || MultiKillMax < MultiKillTemp.Count)) MultiKillMax = MultiKillTemp.Count; MultiKillInfo.push_back(MultiKillTemp); ++count; } while (result->NextRow()); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u count for MultiKill in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty."); 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].GetUInt8(); //Report any errors in event if (e_type >= EVENT_T_END) { sLog->outError(LOG_FILTER_SQL, "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].GetInt32(); temp.event_chance = fields[4].GetUInt32(); temp.event_flags = fields[5].GetUInt32(); temp.raw.param1 = fields[6].GetInt32(); temp.raw.param2 = fields[7].GetInt32(); temp.raw.param3 = fields[8].GetInt32(); temp.raw.param4 = fields[9].GetInt32(); CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); //Creature does not exist in database if (!cInfo) { sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id); continue; } // Only on the first script if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty()) sLog->outError(LOG_FILTER_SQL, "Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id); //No chance of this event occuring if (temp.event_chance == 0) sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId); sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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.ConditionType = ConditionTypes(temp.receive_emote.condition); cond.ConditionValue1 = temp.receive_emote.conditionValue1; cond.ConditionValue2 = temp.receive_emote.conditionValue2; if (!sConditionMgr->isConditionTypeValid(&cond)) { sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); break; } default: sLog->outError(LOG_FILTER_SQL, "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)].GetUInt8(); if (action_type >= ACTION_T_END) { sLog->outError(LOG_FILTER_SQL, "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)].GetInt32(); action.raw.param2 = fields[12+(j*4)].GetInt32(); action.raw.param3 = fields[13+(j*4)].GetInt32(); //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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1); if (!action.text.TextId1) sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1); if (!action.text.TextId1 || !action.text.TextId2) sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1); break; } case ACTION_T_SUMMON: if (!sObjectMgr->GetCreatureTemplate(action.summon.creatureId)) sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void DungeonResetScheduler::LoadResetTimes() { time_t now = time(NULL); time_t today = (now / DAY) * DAY; time_t nextWeek = today + (7 * DAY); // NOTE: Use DirectPExecute for tables that will be queried later // get the current reset times for normal instances (these may need to be updated) // these are only kept in memory for InstanceSaves that are loaded later // resettime = 0 in the DB for raid/heroic instances so those are skipped typedef std::pair < uint32 /*PAIR32(map,difficulty)*/, time_t > ResetTimeMapDiffType; typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType; InstResetTimeMapDiffType instResetTime; QueryResult* result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0"); if (result) { do { if (time_t resettime = time_t((*result)[3].GetUInt64())) { uint32 id = (*result)[0].GetUInt32(); uint32 mapid = (*result)[1].GetUInt32(); uint32 difficulty = (*result)[2].GetUInt32(); MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry || !mapEntry->IsDungeon() || !GetMapDifficultyData(mapid, Difficulty(difficulty))) { sMapPersistentStateMgr.DeleteInstanceFromDB(id); continue; } instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid, difficulty), resettime); } } while (result->NextRow()); delete result; // update reset time for normal instances with the max creature respawn time + X hours result = CharacterDatabase.Query("SELECT MAX(respawntime), instance FROM creature_respawn WHERE instance > 0 GROUP BY instance"); if (result) { do { Field* fields = result->Fetch(); time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); uint32 instance = fields[1].GetUInt32(); InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance); if (itr != instResetTime.end() && itr->second.second != resettime) { CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '" UI64FMTD "' WHERE id = '%u'", uint64(resettime), instance); itr->second.second = resettime; } } while (result->NextRow()); delete result; } // schedule the reset times for (InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) if (itr->second.second > now) ScheduleReset(true, itr->second.second, DungeonResetEvent(RESET_EVENT_NORMAL_DUNGEON, PAIR32_LOPART(itr->second.first), Difficulty(PAIR32_HIPART(itr->second.first)), itr->first)); } // load the global respawn times for raid/heroic instances uint32 diff = sWorld.getConfig(CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR) * HOUR; result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); if (result) { do { Field* fields = result->Fetch(); uint32 mapid = fields[0].GetUInt32(); Difficulty difficulty = Difficulty(fields[1].GetUInt32()); uint64 oldresettime = fields[2].GetUInt64(); MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry || !mapEntry->IsDungeon() || !GetMapDifficultyData(mapid, difficulty)) { sLog.outError("MapPersistentStateManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid, difficulty); continue; } // update the reset time if the hour in the configs changes uint64 newresettime = (oldresettime / DAY) * DAY + diff; if (oldresettime != newresettime) CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty); SetResetTimeFor(mapid, difficulty, newresettime); } while (result->NextRow()); delete result; } // clean expired instances, references to them will be deleted in CleanupInstances // must be done before calculating new reset times m_InstanceSaves._CleanupExpiredInstancesAtTime(now); // calculate new global reset times for expired instances and those that have never been reset yet // add the global reset times to the priority queue for (MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) { uint32 map_diff_pair = itr->first; uint32 mapid = PAIR32_LOPART(map_diff_pair); Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); MapDifficultyEntry const* mapDiff = itr->second; // skip mapDiff without global reset time if (!mapDiff->resetTime) continue; // only raid/heroic maps have a global reset time MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry || !mapEntry->IsDungeon()) continue; uint32 period = GetMaxResetTimeFor(mapDiff); time_t t = GetResetTimeFor(mapid, difficulty); if (!t) { // initialize the reset time t = today + period + diff; CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','" UI64FMTD "')", mapid, difficulty, (uint64)t); } if (t < now || t > nextWeek) { // assume that expired instances have already been cleaned // calculate the next reset time t = (t / DAY) * DAY; t += ((today - t) / period + 1) * period + diff; CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); } SetResetTimeFor(mapid, difficulty, t); // schedule the global reset/warning ResetEventType type = RESET_EVENT_INFORM_1; for (; type < RESET_EVENT_INFORM_LAST; type = ResetEventType(type + 1)) if (t > time_t(now + resetEventTypeDelay[type])) break; ScheduleReset(true, t - resetEventTypeDelay[type], DungeonResetEvent(type, mapid, difficulty, 0)); } }
// ------------------- 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 0 1 2 3 4 QueryResult result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); if (!result) { sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty."); return; } uint32 count = 0; do { Field* fields = result->Fetch(); StringTextData temp; int32 i = fields[0].GetInt32(); temp.SoundId = fields[1].GetUInt32(); temp.Type = fields[2].GetUInt8(); temp.Language = fields[3].GetUInt8(); temp.Emote = fields[4].GetUInt16(); // range negative if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID) { sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` not found", i); continue; } if (temp.SoundId) { if (!sSoundEntriesStore.LookupEntry(temp.SoundId)) sLog->outError(LOG_FILTER_SQL, "CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.", i, temp.SoundId); } if (!GetLanguageDescByID(temp.Language)) sLog->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outError(LOG_FILTER_SQL, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u additional CreatureEventAI Texts data in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void WorldSession::HandlePetitionBuyOpcode (WorldPacket & recv_data) { if (_player->GetGuildId()) return; sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_BUY"); recv_data.hexlike(); uint64 guidNPC; uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client std::string name; recv_data >> guidNPC; // NPC GUID recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint64>(); // 0 recv_data >> name; // name recv_data.read_skip<std::string>(); // some string recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint16>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 recv_data.read_skip<uint32>(); // 0 for (int i = 0; i < 10; ++i) recv_data.read_skip<std::string>(); recv_data >> clientIndex; // index recv_data.read_skip<uint32>(); // 0 sLog->outDebug(LOG_FILTER_NETWORKIO, "Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str()); // prevent cheating Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC, UNIT_NPC_FLAG_PETITIONER); if (!pCreature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); return; } if (!pCreature->isTabardDesigner()) return; // remove fake death if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); uint32 charterid = GUILD_CHARTER; uint64 cost = GUILD_CHARTER_COST; if (sObjectMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_INVALID, name); return; } ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(charterid); if (!pProto) { _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); return; } if (!_player->HasEnoughMoney(cost)) { //player hasn't got enough money _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0); return; } ItemPosCountVec dest; uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); if (msg != EQUIP_ERR_OK) { _player->SendBuyError(msg, pCreature, charterid, 0); return; } _player->ModifyMoney(-(int32) cost); Item *charter = _player->StoreNewItem(dest, charterid, true); if (!charter) return; charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false); // a petition is invalid, if both the owner and the type matches // we checked above, if this player is in an arenateam, so this must be // datacorruption QueryResult result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u'", _player->GetGUIDLow()); std::ostringstream ssInvalidPetitionGUIDs; if (result) { do { Field *fields = result->Fetch(); ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , "; } while (result->NextRow()); } // delete petitions with the same guid as this one ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'"; sLog->outDebug(LOG_FILTER_NETWORKIO, "Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); CharacterDatabase.EscapeString(name); SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); trans->PAppend("INSERT INTO petition (ownerguid, petitionguid, name) VALUES ('%u', '%u', '%s')", _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str()); CharacterDatabase.CommitTransaction(trans); }
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].GetUInt32(); 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 skil 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 GuildMgr::LoadGuilds() { // 1. Load all guilds sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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 13 14 15 "g.BackgroundColor, g.info, g.motd, g.createdate, g.BankMoney, g.level, g.experience, g.todayExperience, 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild definitions. DB table `guild` is empty."); return; } else { uint32 count = 0; do { Field* fields = result->Fetch(); Guild* guild = new Guild(); if (!guild->LoadFromDB(fields)) { delete guild; continue; } AddGuild(guild); ++count; } while (result->NextRow()); sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 2. Load all guild ranks sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild ranks. DB table `guild_rank` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild ranks in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 3. Load all guild members sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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 gm.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 "BankResetTimeTab6, BankRemSlotsTab6, BankResetTimeTab7, BankRemSlotsTab7, " // 23 24 25 26 27 28 "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild members. DB table `guild_member` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild members int %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 4. Load all guild bank tab rights sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild bank tab rights. DB table `guild_bank_right` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u bank tab rights in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 5. Load all event logs sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild event logs. DB table `guild_eventlog` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild event logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 6. Load all bank event logs sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild bank event logs. DB table `guild_bank_eventlog` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild bank event logs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 7. Load all guild bank tabs sLog->outInfo(LOG_FILTER_SERVER_LOADING, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild bank tabs. DB table `guild_bank_tab` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild bank tabs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 8. Fill all guild bank tabs sLog->outInfo(LOG_FILTER_GUILD, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 guild bank tab items. DB table `guild_bank_item` or `item_instance` is empty."); } 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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u guild bank tab items in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } } // 9. Load guild achievements { PreparedQueryResult achievementResult; PreparedQueryResult criteriaResult; for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT); stmt->setUInt32(0, itr->first); achievementResult = CharacterDatabase.Query(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA); stmt->setUInt32(0, itr->first); criteriaResult = CharacterDatabase.Query(stmt); itr->second->GetAchievementMgr().LoadFromDB(achievementResult, criteriaResult); } } // 10. Loading Guild news sLog->outInfo(LOG_FILTER_GENERAL, "Loading Guild News"); { for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_GUILD_NEWS); stmt->setInt32(0, itr->first); itr->second->GetNewsLog().LoadFromDB(CharacterDatabase.Query(stmt)); } } // 11. Validate loaded guild data sLog->outInfo(LOG_FILTER_GENERAL, "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->outInfo(LOG_FILTER_SERVER_LOADING, ">> Validated data of loaded guilds in %u ms", GetMSTimeDiffToNow(oldMSTime)); } }
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 SystemMgr::LoadScriptWaypoints() { // Drop Existing Waypoint list m_mPointMoveMap.clear(); uint64 uiCreatureCount = 0; // Load Waypoints QueryResult* pResult = SD2Database.PQuery("SELECT COUNT(entry) FROM script_waypoint GROUP BY entry"); if (pResult) { uiCreatureCount = pResult->GetRowCount(); delete pResult; } outstring_log("evo-X: Loading Script Waypoints for %u creature(s)...", uiCreatureCount); pResult = SD2Database.PQuery("SELECT entry, pointid, location_x, location_y, location_z, waittime FROM script_waypoint ORDER BY pointid"); if (pResult) { barGoLink bar(pResult->GetRowCount()); uint32 uiNodeCount = 0; do { bar.step(); Field* pFields = pResult->Fetch(); ScriptPointMove pTemp; pTemp.uiCreatureEntry = pFields[0].GetUInt32(); uint32 uiEntry = pTemp.uiCreatureEntry; pTemp.uiPointId = pFields[1].GetUInt32(); pTemp.fX = pFields[2].GetFloat(); pTemp.fY = pFields[3].GetFloat(); pTemp.fZ = pFields[4].GetFloat(); pTemp.uiWaitTime = pFields[5].GetUInt32(); CreatureInfo const* pCInfo = GetCreatureTemplateStore(pTemp.uiCreatureEntry); if (!pCInfo) { error_db_log("evo-X: DB table script_waypoint has waypoint for non-existant creature entry %u", pTemp.uiCreatureEntry); continue; } if (!pCInfo->ScriptID) error_db_log("evo-X: DB table script_waypoint has waypoint for creature entry %u, but creature does not have ScriptName defined and then useless.", pTemp.uiCreatureEntry); m_mPointMoveMap[uiEntry].push_back(pTemp); ++uiNodeCount; } while (pResult->NextRow()); delete pResult; outstring_log(""); outstring_log(">> Loaded %u Script Waypoint nodes.", uiNodeCount); } else { barGoLink bar(1); bar.step(); outstring_log(""); outstring_log(">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); } }
void PoolManager::LoadFromDB() { QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM pool_template"); if (!result) { sLog.outString(">> Table pool_template is empty."); sLog.outString(); return; } else { Field *fields = result->Fetch(); max_pool_id = fields[0].GetUInt16(); delete result; } mPoolTemplate.resize(max_pool_id + 1); result = WorldDatabase.Query("SELECT entry,max_limit FROM pool_template"); if (!result) { mPoolTemplate.clear(); sLog.outString(">> Table pool_template is empty:"); return; } uint32 count = 0; do { ++count; Field *fields = result->Fetch(); uint16 pool_id = fields[0].GetUInt16(); PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id]; pPoolTemplate.MaxLimit = fields[1].GetUInt32(); } while (result->NextRow()); sLog.outString( ">> Loaded %u objects pools", count ); delete result; // Creatures mPoolCreatureGroups.resize(max_pool_id + 1); mCreatureSearchMap.clear(); // 1 2 3 result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_creature"); count = 0; if (!result) { sLog.outString(">> Loaded %u creatures in pools", count ); } else { do { Field *fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint16 pool_id = fields[1].GetUInt16(); float chance = fields[2].GetFloat(); CreatureData const* data = sObjectMgr.GetCreatureData(guid); if (!data) { sLog.outErrorDb("`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.outErrorDb("`pool_creature` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id); continue; } if (chance < 0 || chance > 100) { sLog.outErrorDb("`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%i), skipped.", chance, guid, pool_id); continue; } PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id]; ++count; 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); } while (result->NextRow()); sLog.outString( ">> Loaded %u creatures in pools", count ); delete result; } // Gameobjects mPoolGameobjectGroups.resize(max_pool_id + 1); mGameobjectSearchMap.clear(); // 1 2 3 result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_gameobject"); count = 0; if (!result) { sLog.outString(">> Loaded %u gameobject in pools", count ); } else { do { Field *fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); uint16 pool_id = fields[1].GetUInt16(); float chance = fields[2].GetFloat(); GameObjectData const* data = sObjectMgr.GetGOData(guid); if (!data) { sLog.outErrorDb("`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id ); continue; } GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(data->id); if (goinfo->type != GAMEOBJECT_TYPE_CHEST && goinfo->type != GAMEOBJECT_TYPE_GOOBER && goinfo->type != GAMEOBJECT_TYPE_FISHINGHOLE) { sLog.outErrorDb("`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.outErrorDb("`pool_gameobject` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id); continue; } if (chance < 0 || chance > 100) { sLog.outErrorDb("`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%i), skipped.", chance, guid, pool_id); continue; } PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id]; ++count; 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); } while( result->NextRow() ); sLog.outString( ">> Loaded %u gameobject in pools", count ); delete result; } // Pool of pools mPoolPoolGroups.resize(max_pool_id + 1); // 1 2 3 result = WorldDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool"); count = 0; if( !result ) { sLog.outString(">> Loaded %u pools in pools", count ); } else { do { Field *fields = result->Fetch(); uint16 child_pool_id = fields[0].GetUInt16(); uint16 mother_pool_id = fields[1].GetUInt16(); float chance = fields[2].GetFloat(); if (mother_pool_id > max_pool_id) { sLog.outErrorDb("`pool_pool` mother_pool id (%i) 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.outErrorDb("`pool_pool` included pool_id (%i) 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.outErrorDb("`pool_pool` pool_id (%i) includes itself, dead-lock detected, skipped.",child_pool_id); continue; } if (chance < 0 || chance > 100) { sLog.outErrorDb("`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%i), skipped.", chance, child_pool_id, mother_pool_id); continue; } PoolTemplateData *pPoolTemplateMother = &mPoolTemplate[mother_pool_id]; ++count; 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); } while( result->NextRow() ); // Now check for circular reference for(uint16 i=0; i<max_pool_id; ++i) { std::set<uint16> 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<uint16>::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.outErrorDb("%s", ss.str().c_str()); mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first); mPoolSearchMap.erase(poolItr); --count; break; } } } sLog.outString( ">> Loaded %u pools in mother pools", count ); delete result; } }
void MapManager::LoadTransports() { uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT guid, entry, name, period, ScriptName FROM transports"); if (!result) { TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 transports. DB table `transports` is empty!"); 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()); GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry); if (!goinfo) { TC_LOG_ERROR(LOG_FILTER_SQL, "Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); continue; } if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) { TC_LOG_ERROR(LOG_FILTER_SQL, "Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); continue; } // TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "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 { TC_LOG_ERROR(LOG_FILTER_SQL, "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, 255, 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(); TC_LOG_ERROR(LOG_FILTER_SQL, "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()); } TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u transports in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); }
void WaypointManager::Load() { uint32 total_paths = 0; uint32 total_nodes = 0; uint32 total_behaviors = 0; std::set<uint32> movementScriptSet; for (ScriptMapMap::const_iterator itr = sCreatureMovementScripts.second.begin(); itr != sCreatureMovementScripts.second.end(); ++itr) { movementScriptSet.insert(itr->first); } // creature_movement QueryResult* result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 paths. DB table `creature_movement` is empty."); } else { total_paths = (uint32)result->GetRowCount(); BarGoLink bar(total_paths); do { bar.step(); Field* fields = result->Fetch(); uint32 id = fields[0].GetUInt32(); uint32 count = fields[1].GetUInt32(); total_nodes += count; } while (result->NextRow()); sLog.outString(); sLog.outString(">> Paths loaded"); delete result; // 0 1 2 3 4 5 6 result = WorldDatabase.Query("SELECT id, point, position_x, position_y, position_z, waittime, script_id," // 7 8 9 10 11 12 13 14 15 16 "textid1, textid2, textid3, textid4, textid5, emote, spell, orientation, model1, model2 FROM creature_movement"); BarGoLink barRow((int)result->GetRowCount()); // error after load, we check if creature guid corresponding to the path id has proper MovementType std::set<uint32> creatureNoMoveType; do { barRow.step(); Field* fields = result->Fetch(); uint32 id = fields[0].GetUInt32(); uint32 point = fields[1].GetUInt32(); const CreatureData* cData = sObjectMgr.GetCreatureData(id); if (!cData) { sLog.outErrorDb("Table creature_movement contain path for creature guid %u, but this creature guid does not exist. Skipping.", id); continue; } if (cData->movementType != WAYPOINT_MOTION_TYPE) { creatureNoMoveType.insert(id); } WaypointPath& path = m_pathMap[id]; WaypointNode& node = path[point]; node.x = fields[2].GetFloat(); node.y = fields[3].GetFloat(); node.z = fields[4].GetFloat(); node.orientation = fields[14].GetFloat(); node.delay = fields[5].GetUInt32(); node.script_id = fields[6].GetUInt32(); // prevent using invalid coordinates if (!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) { QueryResult* result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id); if (result1) sLog.outErrorDb("Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).", id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y); else sLog.outErrorDb("Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).", id, point, node.x, node.y); MaNGOS::NormalizeMapCoord(node.x); MaNGOS::NormalizeMapCoord(node.y); if (result1) { node.z = sTerrainMgr.LoadTerrain(result1->Fetch()[1].GetUInt32())->GetHeightStatic(node.x, node.y, node.z); delete result1; } WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point); } if (node.script_id) { if (sCreatureMovementScripts.second.find(node.script_id) == sCreatureMovementScripts.second.end()) { sLog.outErrorDb("Table creature_movement for id %u, point %u have script_id %u that does not exist in `dbscripts_on_creature_movement`, ignoring", id, point, node.script_id); continue; } movementScriptSet.erase(node.script_id); } // WaypointBehavior can be dropped in time. Script_id added may 2010 and can handle all the below behavior. WaypointBehavior be; be.model1 = fields[15].GetUInt32(); be.model2 = fields[16].GetUInt32(); be.emote = fields[12].GetUInt32(); be.spell = fields[13].GetUInt32(); for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) { be.textid[i] = fields[7 + i].GetInt32(); if (be.textid[i]) { if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID) { sLog.outErrorDb("Table `creature_movement` Id %u, point %u has textid%u has value %d out of range. Must be in %u-%u", id, point, i + 1, be.textid[i], MIN_DB_SCRIPT_STRING_ID, MAX_DB_SCRIPT_STRING_ID - 1); be.textid[i] = 0; } } } if (be.spell && ! sSpellStore.LookupEntry(be.spell)) { sLog.outErrorDb("Table creature_movement references unknown spellid %u. Skipping id %u with point %u.", be.spell, id, point); be.spell = 0; } if (be.emote) { if (!sEmotesStore.LookupEntry(be.emote)) { sLog.outErrorDb("Waypoint path %u (Point %u) are using emote %u, but emote does not exist.", id, point, be.emote); } } // save memory by not storing empty behaviors if (!be.isEmpty()) { node.behavior = new WaypointBehavior(be); ++total_behaviors; } else { node.behavior = NULL; } } while (result->NextRow()); if (!creatureNoMoveType.empty()) { for (std::set<uint32>::const_iterator itr = creatureNoMoveType.begin(); itr != creatureNoMoveType.end(); ++itr) { const CreatureData* cData = sObjectMgr.GetCreatureData(*itr); const CreatureInfo* cInfo = ObjectMgr::GetCreatureTemplate(cData->id); sLog.outErrorDb("Table creature_movement has waypoint for creature guid %u (entry %u), but MovementType is not WAYPOINT_MOTION_TYPE(2). Creature will not use this path.", *itr, cData->id); if (cInfo->MovementType == WAYPOINT_MOTION_TYPE) { sLog.outErrorDb(" creature_template for this entry has MovementType WAYPOINT_MOTION_TYPE(2), did you intend to use creature_movement_template ?"); } } } sLog.outString(); sLog.outString(">> Waypoints and behaviors loaded"); sLog.outString(); sLog.outString(">>> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors); delete result; } // creature_movement_template result = WorldDatabase.Query("SELECT entry, COUNT(point) FROM creature_movement_template GROUP BY entry"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 path templates. DB table `creature_movement_template` is empty."); } else { total_nodes = 0; total_behaviors = 0; total_paths = (uint32)result->GetRowCount(); BarGoLink barRow(total_paths); do { barRow.step(); Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 count = fields[1].GetUInt32(); total_nodes += count; } while (result->NextRow()); delete result; sLog.outString(); sLog.outString(">> Path templates loaded"); // 0 1 2 3 4 5 6 result = WorldDatabase.Query("SELECT entry, point, position_x, position_y, position_z, waittime, script_id," // 7 8 9 10 11 12 13 14 15 16 "textid1, textid2, textid3, textid4, textid5, emote, spell, orientation, model1, model2 FROM creature_movement_template"); BarGoLink bar(result->GetRowCount()); do { bar.step(); Field* fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 point = fields[1].GetUInt32(); const CreatureInfo* cInfo = ObjectMgr::GetCreatureTemplate(entry); if (!cInfo) { sLog.outErrorDb("Table creature_movement_template references unknown creature template %u. Skipping.", entry); continue; } WaypointPath& path = m_pathTemplateMap[entry]; WaypointNode& node = path[point]; node.x = fields[2].GetFloat(); node.y = fields[3].GetFloat(); node.z = fields[4].GetFloat(); node.orientation = fields[14].GetFloat(); node.delay = fields[5].GetUInt32(); node.script_id = fields[6].GetUInt32(); // prevent using invalid coordinates if (!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) { sLog.outErrorDb("Table creature_movement_template for entry %u (point %u) are using invalid coordinates position_x: %f, position_y: %f)", entry, point, node.x, node.y); MaNGOS::NormalizeMapCoord(node.x); MaNGOS::NormalizeMapCoord(node.y); sLog.outErrorDb("Table creature_movement_template for entry %u (point %u) are auto corrected to normalized position_x=%f, position_y=%f", entry, point, node.x, node.y); WorldDatabase.PExecute("UPDATE creature_movement_template SET position_x = '%f', position_y = '%f' WHERE entry = %u AND point = %u", node.x, node.y, entry, point); } if (node.script_id) { if (sCreatureMovementScripts.second.find(node.script_id) == sCreatureMovementScripts.second.end()) { sLog.outErrorDb("Table creature_movement_template for entry %u, point %u have script_id %u that does not exist in `dbscripts_on_creature_movement`, ignoring", entry, point, node.script_id); continue; } movementScriptSet.erase(node.script_id); } WaypointBehavior be; be.model1 = fields[15].GetUInt32(); be.model2 = fields[16].GetUInt32(); be.emote = fields[12].GetUInt32(); be.spell = fields[13].GetUInt32(); for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) { be.textid[i] = fields[7 + i].GetUInt32(); if (be.textid[i]) { if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID) { sLog.outErrorDb("Table `creature_movement_template` Entry %u, point %u has textid%u has value %d out of range. Must be in %u-%u", entry, point, i + 1, be.textid[i], MIN_DB_SCRIPT_STRING_ID, MAX_DB_SCRIPT_STRING_ID - 1); be.textid[i] = 0; } } } if (be.spell && ! sSpellStore.LookupEntry(be.spell)) { sLog.outErrorDb("Table creature_movement_template references unknown spellid %u. Skipping id %u with point %u.", be.spell, entry, point); be.spell = 0; } if (be.emote) { if (!sEmotesStore.LookupEntry(be.emote)) { sLog.outErrorDb("Waypoint template path %u (point %u) are using emote %u, but emote does not exist.", entry, point, be.emote); } } // save memory by not storing empty behaviors if (!be.isEmpty()) { node.behavior = new WaypointBehavior(be); ++total_behaviors; } else { node.behavior = NULL; } } while (result->NextRow()); delete result; sLog.outString(); sLog.outString(">> Waypoint templates loaded"); sLog.outString(); sLog.outString(">>> Loaded %u path templates with %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors); } if (!movementScriptSet.empty()) { for (std::set<uint32>::const_iterator itr = movementScriptSet.begin(); itr != movementScriptSet.end(); ++itr) { sLog.outErrorDb("Table `dbscripts_on_creature_movement` contain unused script, id %u.", *itr); } } }
void AchievementGlobalMgr::LoadRewardLocales() { 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) { barGoLink bar(1); bar.step(); sLog.outString(""); sLog.outString(">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty."); return; } barGoLink bar(result->GetRowCount()); do { Field *fields = result->Fetch(); bar.step(); 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 not existed achievement reward .", entry); continue; } AchievementRewardLocale& data = m_achievementRewardLocales[entry]; for(int i = 1; i < MAX_LOCALE; ++i) { std::string str = fields[1+2*(i-1)].GetCppString(); if(!str.empty()) { int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); if(idx >= 0) { if(data.subject.size() <= idx) data.subject.resize(idx+1); data.subject[idx] = str; } } str = fields[1+2*(i-1)+1].GetCppString(); if(!str.empty()) { int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); if(idx >= 0) { if(data.text.size() <= idx) data.text.resize(idx+1); data.text[idx] = str; } } } } while (result->NextRow()); delete result; sLog.outString(); sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); }
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->outErrorDb(">> Loaded 0 skill discovery definitions. DB table `skill_discovery_template` is empty."); sLog->outString(); 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].GetUInt32(); 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); SpellEntry const* reqSpellEntry = sSpellStore.LookupEntry(absReqSkillOrSpell); if (!reqSpellEntry) { if (reportedReqSpells.find(absReqSkillOrSpell) == reportedReqSpells.end()) { sLog->outErrorDb("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 (reqSpellEntry->GetMechanic() != MECHANIC_DISCOVERY && // explicit discovery ability !IsExplicitDiscoverySpell(reqSpellEntry)) { if (reportedReqSpells.find(absReqSkillOrSpell) == reportedReqSpells.end()) { sLog->outErrorDb("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->outErrorDb("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->outErrorDb("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->outErrorDb("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 < sSpellStore.GetNumRows(); ++spell_id) { SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell_id); if (!spellEntry) continue; // skip not explicit discovery spells if (!IsExplicitDiscoverySpell(spellEntry)) continue; if (SkillDiscoveryStore.find(int32(spell_id)) == SkillDiscoveryStore.end()) sLog->outErrorDb("Spell (ID: %u) is 100%% chance random discovery ability but not have data in `skill_discovery_template` table", spell_id); } sLog->outString(">> Loaded %u skill discovery definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); }
void AuctionHouseMgr::LoadAuctions() { QueryResult* result = CharacterDatabase.Query("SELECT COUNT(*) FROM auction"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } Field* fields = result->Fetch(); uint32 AuctionCount = fields[0].GetUInt32(); delete result; if (!AuctionCount) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } result = CharacterDatabase.Query("SELECT id,houseid,itemguid,item_template,item_count,item_randompropertyid,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit FROM auction"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } BarGoLink bar(AuctionCount); typedef std::map<uint32, std::wstring> PlayerNames; PlayerNames playerNames; // caching for load time do { fields = result->Fetch(); bar.step(); AuctionEntry* auction = new AuctionEntry; auction->Id = fields[0].GetUInt32(); uint32 houseid = fields[1].GetUInt32(); auction->itemGuidLow = fields[2].GetUInt32(); auction->itemTemplate = fields[3].GetUInt32(); auction->itemCount = fields[4].GetUInt32(); auction->itemRandomPropertyId = fields[5].GetUInt32(); auction->owner = fields[6].GetUInt32(); if (auction->owner) { std::wstring& plWName = playerNames[auction->owner]; if (plWName.empty()) { std::string plName; if (!sObjectMgr.GetPlayerNameByGUID(ObjectGuid(HIGHGUID_PLAYER, auction->owner), plName)) plName = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN); Utf8toWStr(plName, plWName); } auction->ownerName = plWName; } auction->buyout = fields[7].GetUInt32(); auction->expireTime = time_t(fields[8].GetUInt64()); auction->bidder = fields[9].GetUInt32(); auction->bid = fields[10].GetUInt32(); auction->startbid = fields[11].GetUInt32(); auction->deposit = fields[12].GetUInt32(); auction->auctionHouseEntry = NULL; // init later // check if sold item exists for guid // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) Item* pItem = GetAItem(auction->itemGuidLow); if (!pItem) { auction->DeleteFromDB(); sLog.outError("Auction %u has not a existing item : %u, deleted", auction->Id, auction->itemGuidLow); delete auction; continue; } // overwrite by real item data if ((auction->itemTemplate != pItem->GetEntry()) || (auction->itemCount != pItem->GetCount()) || (auction->itemRandomPropertyId != pItem->GetItemRandomPropertyId())) { auction->itemTemplate = pItem->GetEntry(); auction->itemCount = pItem->GetCount(); auction->itemRandomPropertyId = pItem->GetItemRandomPropertyId(); // No SQL injection (no strings) CharacterDatabase.PExecute("UPDATE auction SET item_template = %u, item_count = %u, item_randompropertyid = %i WHERE itemguid = %u", auction->itemTemplate, auction->itemCount, auction->itemRandomPropertyId, auction->itemGuidLow); } auction->auctionHouseEntry = sAuctionHouseStore.LookupEntry(houseid); if (!auction->auctionHouseEntry) { // need for send mail, use goblin auctionhouse auction->auctionHouseEntry = sAuctionHouseStore.LookupEntry(7); // Attempt send item back to owner std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->itemTemplate << ":" << auction->itemRandomPropertyId << ":" << AUCTION_CANCELED; if (auction->itemGuidLow) { RemoveAItem(auction->itemGuidLow); auction->itemGuidLow = 0; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str(), "")// TODO: fix body .AddItem(pItem) .SendMailTo(MailReceiver(ObjectGuid(HIGHGUID_PLAYER, auction->owner)), auction, MAIL_CHECK_MASK_COPIED); } auction->DeleteFromDB(); delete auction; continue; } GetAuctionsMap(auction->auctionHouseEntry)->AddAuction(auction); } while (result->NextRow()); delete result; sLog.outString(); sLog.outString(">> Loaded %u auctions", AuctionCount); }
// Writing - High-level functions void PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) { GUIDs const* guids = NULL; char const* fieldname = NULL; switch ( type ) { case DTT_ITEM: fieldname = "guid"; guids = &items; break; case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break; case DTT_PET: fieldname = "owner"; break; case DTT_PET_TABLE: fieldname = "guid"; guids = &pets; break; case DTT_MAIL: fieldname = "receiver"; break; case DTT_MAIL_ITEM: fieldname = "mail_id"; guids = &mails; break; case DTT_ITEM_TEXT: fieldname = "id"; guids = &texts; break; default: fieldname = "guid"; break; } // for guid set stop if set is empty if(guids && guids->empty()) return; // nothing to do // setup for guids case start position GUIDs::const_iterator guids_itr; if(guids) guids_itr = guids->begin(); do { std::string wherestr; if(guids) // set case, get next guids string wherestr = GenerateWhereStr(fieldname,*guids,guids_itr); else // not set case, get single guid string wherestr = GenerateWhereStr(fieldname,guid); QueryResult *result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str()); if(!result) return; do { // collect guids switch ( type ) { case DTT_INVENTORY: StoreGUID(result,3,items); break; // item guid collection case DTT_ITEM: StoreGUID(result,0,ITEM_FIELD_ITEM_TEXT_ID,texts); break; // item text id collection case DTT_PET: StoreGUID(result,0,pets); break; // pet guid collection case DTT_MAIL: StoreGUID(result,0,mails); // mail id collection StoreGUID(result,6,texts); break; // item text id collection case DTT_MAIL_ITEM: StoreGUID(result,1,items); break; // item guid collection default: break; } dump += CreateDumpString(tableTo, result); dump += "\n"; } while (result->NextRow()); delete result; } while(guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids }