void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_BUY"); ObjectGuid npcGuid; uint32 nameLen = 0; std::string name; npcGuid[6] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); npcGuid[2] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[7] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); nameLen = recvData.ReadBits(7); npcGuid[0] = recvData.ReadBit(); recvData.FlushBits(); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(npcGuid[6]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[1]); name = recvData.ReadString(nameLen); sLog->outDebug(LOG_FILTER_NETWORKIO, "Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(npcGuid), name.c_str()); // prevent cheating Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_PETITIONER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(npcGuid)); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); uint32 charterid = 0; uint32 cost = 0; uint32 type = 0; if (creature->isTabardDesigner()) { // if tabard designer, then trying to buy a guild charter. // do not let if already in guild. if (_player->GetGuildId()) return; charterid = GUILD_CHARTER; cost = GUILD_CHARTER_COST; type = GUILD_CHARTER_TYPE; } if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, name); return; } } ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(charterid); if (!pProto) { _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); return; } if (!_player->HasEnoughMoney(uint64(cost))) { //player hasn't got enough money _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, charterid, 0); return; } ItemPosCountVec dest; InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, NULL, NULL, charterid); 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 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt8(1, type); PreparedQueryResult result = CharacterDatabase.Query(stmt); 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()); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt32(1, charter->GetGUIDLow()); stmt->setString(2, name); stmt->setUInt8(3, uint8(type)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); }
void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime) { // global reset for all instances of the given map MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry->Instanceable()) return; time_t now = time(NULL); if (!warn) { MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty); if (!mapDiff || !mapDiff->resetTime) { sLog->outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); return; } // calculate the next reset time uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; uint32 period = mapDiff->resetTime; if (period < DAY) period = DAY; uint32 next_reset = uint32(((resetTime + MINUTE) / DAY * DAY) + period + diff); SetResetTimeFor(mapid, difficulty, next_reset); SetExtendedResetTimeFor(mapid, difficulty, next_reset + period); ScheduleReset(time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty)); // update it in the DB PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt32(0, next_reset); stmt->setUInt16(1, uint16(mapid)); stmt->setUInt8(2, uint8(difficulty)); CharacterDatabase.Execute(stmt); // remove all binds to instances of the given map and delete from db (delete per instance id, no mass deletion!) // do this after new reset time is calculated for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(), itr2; itr != m_instanceSaveById.end(); ) { itr2 = itr++; if (itr2->second->GetMapId() == mapid && itr2->second->GetDifficulty() == difficulty) _ResetSave(itr2); } } // now loop all existing maps to warn / reset Map const* map = sMapMgr->CreateBaseMap(mapid); MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); MapInstanced::InstancedMaps::iterator mitr; uint32 timeLeft; for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) { Map* map2 = mitr->second; if (!map2->IsDungeon() || map2->GetDifficulty() != difficulty) continue; if (warn) { if (now >= resetTime) timeLeft = 0; else timeLeft = uint32(resetTime - now); map2->ToInstanceMap()->SendResetWarnings(timeLeft); } else { InstanceSave* save = GetInstanceSave(map2->GetInstanceId()); map2->ToInstanceMap()->Reset(INSTANCE_RESET_GLOBAL, (save ? &(save->m_playerList) : NULL)); } } }
void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_PETITION_BUY"); uint64 guidNPC; uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client std::string name; recvData >> guidNPC; // NPC GUID recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint64>(); // 0 recvData >> name; // name recvData.read_skip<std::string>(); // some string recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint16>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 for (int i = 0; i < 10; ++i) recvData.read_skip<std::string>(); recvData >> clientIndex; // index recvData.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* creature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC, UNIT_NPC_FLAG_PETITIONER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC)); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); uint32 charterid = 0; uint32 cost = 0; uint32 type = 0; if (creature->isTabardDesigner()) { // if tabard designer, then trying to buy a guild charter. // do not let if already in guild. if (_player->GetGuildId()) return; charterid = GUILD_CHARTER; cost = GUILD_CHARTER_COST; type = GUILD_CHARTER_TYPE; } else { // TODO: find correct opcode if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); return; } switch (clientIndex) // arenaSlot+1 as received from client (1 from 3 case) { case 1: charterid = ARENA_TEAM_CHARTER_2v2; cost = ARENA_TEAM_CHARTER_2v2_COST; type = ARENA_TEAM_CHARTER_2v2_TYPE; break; case 2: charterid = ARENA_TEAM_CHARTER_3v3; cost = ARENA_TEAM_CHARTER_3v3_COST; type = ARENA_TEAM_CHARTER_3v3_TYPE; break; case 3: charterid = ARENA_TEAM_CHARTER_5v5; cost = ARENA_TEAM_CHARTER_5v5_COST; type = ARENA_TEAM_CHARTER_5v5_TYPE; break; default: sLog->outDebug(LOG_FILTER_NETWORKIO, "unknown selection at buy arena petition: %u", clientIndex); return; } if (_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } } if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, name); return; } } else { if (sArenaTeamMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); return; } } ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(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, creature, charterid, 0); return; } ItemPosCountVec dest; InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, NULL, NULL, charterid); 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 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt8(1, type); PreparedQueryResult result = CharacterDatabase.Query(stmt); 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()); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt32(1, charter->GetGUIDLow()); stmt->setString(2, name); stmt->setUInt8(3, uint8(type)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); }
void InstanceSaveManager::LoadResetTimes() { time_t now = GameTime::GetGameTime(); 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; typedef std::pair<ResetTimeMapDiffInstances::const_iterator, ResetTimeMapDiffInstances::const_iterator> ResetTimeMapDiffInstancesBounds; ResetTimeMapDiffInstances mapDiffResetInstances; if (QueryResult result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance ORDER BY id ASC")) { do { Field* fields = result->Fetch(); uint32 instanceId = fields[0].GetUInt32(); // Mark instance id as being used sMapMgr->RegisterInstanceId(instanceId); if (time_t resettime = time_t(fields[3].GetUInt64())) { 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()); // 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; if (QueryResult result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset")) { do { Field* fields = result->Fetch(); uint32 mapid = fields[0].GetUInt16(); Difficulty difficulty = Difficulty(fields[1].GetUInt8()); uint64 oldresettime = fields[2].GetUInt64(); MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty); if (!mapDiff) { TC_LOG_ERROR("misc", "InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); CharacterDatabase.DirectExecute(stmt); continue; } // update the reset time if the hour in the configs changes uint64 newresettime = (oldresettime / DAY) * DAY + diff; if (oldresettime != newresettime) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt64(0, uint64(newresettime)); stmt->setUInt16(1, uint16(mapid)); stmt->setUInt8(2, uint8(difficulty)); CharacterDatabase.DirectExecute(stmt); } InitializeResetTimeFor(mapid, difficulty, newresettime); } while (result->NextRow()); } // 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; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); stmt->setUInt64(2, uint64(t)); CharacterDatabase.DirectExecute(stmt); } 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; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt64(0, uint64(t)); stmt->setUInt16(1, uint16(mapid)); stmt->setUInt8(2, uint8(difficulty)); CharacterDatabase.DirectExecute(stmt); } InitializeResetTimeFor(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)); ResetTimeMapDiffInstancesBounds range = mapDiffResetInstances.equal_range(map_diff_pair); for (; range.first != range.second; ++range.first) ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, mapid, difficulty, range.first->second)); } }
static bool HandleAddDisables(ChatHandler* handler, char const* args, uint8 disableType) { char* entryStr = strtok((char*)args, " "); if (!entryStr || !atoi(entryStr)) return false; char* flagsStr = strtok(NULL, " "); uint8 flags = flagsStr ? uint8(atoi(flagsStr)) : 0; char* commentStr = strtok(NULL, ""); if (!commentStr) return false; std::string disableComment = commentStr; uint32 entry = uint32(atoi(entryStr)); std::string disableTypeStr = ""; switch (disableType) { case DISABLE_TYPE_SPELL: { if (!sSpellMgr->GetSpellInfo(entry)) { handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "spell"; break; } case DISABLE_TYPE_QUEST: { if (!sObjectMgr->GetQuestTemplate(entry)) { handler->PSendSysMessage(LANG_COMMAND_QUEST_NOTFOUND, entry); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "quest"; break; } case DISABLE_TYPE_MAP: { if (!sMapStore.LookupEntry(entry)) { handler->PSendSysMessage(LANG_COMMAND_NOMAPFOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "map"; break; } case DISABLE_TYPE_BATTLEGROUND: { if (!sBattlemasterListStore.LookupEntry(entry)) { handler->PSendSysMessage(LANG_COMMAND_NO_BATTLEGROUND_FOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "battleground"; break; } case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: { if (!sAchievementMgr->GetAchievementCriteria(entry)) { handler->PSendSysMessage(LANG_COMMAND_NO_ACHIEVEMENT_CRITERIA_FOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "achievement criteria"; break; } case DISABLE_TYPE_OUTDOORPVP: { if (entry > MAX_OUTDOORPVP_TYPES) { handler->PSendSysMessage(LANG_COMMAND_NO_OUTDOOR_PVP_FORUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "outdoorpvp"; break; } case DISABLE_TYPE_VMAP: { if (!sMapStore.LookupEntry(entry)) { handler->PSendSysMessage(LANG_COMMAND_NOMAPFOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "vmap"; break; } case DISABLE_TYPE_MMAP: { if (!sMapStore.LookupEntry(entry)) { handler->PSendSysMessage(LANG_COMMAND_NOMAPFOUND); handler->SetSentErrorMessage(true); return false; } disableTypeStr = "mmap"; break; } default: break; } PreparedStatement* stmt = NULL; stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_DISABLES); stmt->setUInt32(0, entry); stmt->setUInt8(1, disableType); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) { handler->PSendSysMessage("This %s (Id: %u) is already disabled.", disableTypeStr.c_str(), entry); handler->SetSentErrorMessage(true); return false; } stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_DISABLES); stmt->setUInt32(0, entry); stmt->setUInt8(1, disableType); stmt->setUInt16(2, flags); stmt->setString(3, disableComment); WorldDatabase.Execute(stmt); handler->PSendSysMessage("Add Disabled %s (Id: %u) for reason %s", disableTypeStr.c_str(), entry, disableComment.c_str()); return true; }
void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) { Player* pReceiver = receiver.GetPlayer(); // can be NULL Player* pSender = sObjectMgr->GetPlayerByLowGUID(sender.GetSenderId()); if (pReceiver) prepareItems(pReceiver, trans); // generate mail template items uint32 mailId = sObjectMgr->GenerateMailID(); time_t deliver_time = time(NULL) + deliver_delay; //expire time if COD 3 days, if no COD 30 days, if auction sale pending 1 hour uint32 expire_delay; // auction mail without any items and money if (sender.GetMailMessageType() == MAIL_AUCTION && m_items.empty() && !m_money) expire_delay = sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY); // mail from battlemaster (rewardmarks) should last only one day else if (sender.GetMailMessageType() == MAIL_CREATURE && sBattlegroundMgr->GetBattleMasterBG(sender.GetSenderId()) != BATTLEGROUND_TYPE_NONE) expire_delay = DAY; // default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master) else if (m_COD) expire_delay = 3 * DAY; else expire_delay = pSender && pSender->IsGameMaster() ? 90 * DAY : 30 * DAY; time_t expire_time = deliver_time + expire_delay; // Add to DB uint8 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL); stmt->setUInt32( index, mailId); stmt->setUInt8 (++index, uint8(sender.GetMailMessageType())); stmt->setInt8 (++index, int8(sender.GetStationery())); stmt->setUInt16(++index, GetMailTemplateId()); stmt->setUInt32(++index, sender.GetSenderId()); stmt->setUInt32(++index, receiver.GetPlayerGUIDLow()); stmt->setString(++index, GetSubject()); stmt->setString(++index, GetBody()); stmt->setBool (++index, !m_items.empty()); stmt->setUInt64(++index, uint64(expire_time)); stmt->setUInt64(++index, uint64(deliver_time)); stmt->setUInt32(++index, m_money); stmt->setUInt32(++index, m_COD); stmt->setUInt8 (++index, uint8(checked)); trans->Append(stmt); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* pItem = mailItemIter->second; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM); stmt->setUInt32(0, mailId); stmt->setUInt32(1, pItem->GetGUIDLow()); stmt->setUInt32(2, receiver.GetPlayerGUIDLow()); trans->Append(stmt); } // For online receiver update in game mail status and data if (pReceiver) { pReceiver->AddNewMailDeliverTime(deliver_time); if (pReceiver->IsMailsLoaded()) { Mail* m = new Mail; m->messageID = mailId; m->mailTemplateId = GetMailTemplateId(); m->subject = GetSubject(); m->body = GetBody(); m->money = GetMoney(); m->COD = GetCOD(); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; m->AddItem(item->GetGUIDLow(), item->GetEntry()); } m->messageType = sender.GetMailMessageType(); m->stationery = sender.GetStationery(); m->sender = sender.GetSenderId(); m->receiver = receiver.GetPlayerGUIDLow(); m->expire_time = expire_time; m->deliver_time = deliver_time; m->checked = checked; m->state = MAIL_STATE_UNCHANGED; pReceiver->AddMail(m); // to insert new mail to beginning of maillist if (!m_items.empty()) { for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) pReceiver->AddMItem(mailItemIter->second); } } else if (!m_items.empty()) { SQLTransaction temp = SQLTransaction(NULL); deleteIncludedItems(temp); } } else if (!m_items.empty()) { SQLTransaction temp = SQLTransaction(NULL); deleteIncludedItems(temp); } }
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) { uint8 type; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 recvData >> type >> unk2 >> bgTypeId_ >> unk >> action; if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Invalid BgType!", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action); return; } if (!_player->InBattlegroundQueue()) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue!", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action); return; } //get GroupQueueInfo from BattlegroundQueue BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, type); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); //we must use temporary variable, because GroupQueueInfo pointer can be deleted in BattlegroundQueue::RemovePlayer() function GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player not in queue (No player Group Info)!", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action); return; } // if action == 1, then instanceId is required if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Player is not invited to any bg!", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action); return; } Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID, bgTypeId); if (!bg) { if (action) { TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u. Cant find BG with id %u!", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action, ginfo.IsInvitedToBGInstanceGUID); return; } bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) { TC_LOG_ERROR("network", "BattlegroundHandler: bg_template not found for type id %u.", bgTypeId); return; } } TC_LOG_DEBUG("bg.battleground", "CMSG_BATTLEFIELD_PORT %s ArenaType: %u, Unk: %u, BgType: %u, Action: %u.", GetPlayerInfo().c_str(), type, unk2, bgTypeId_, action); // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; //some checks if player isn't cheating - it is not exactly cheating, but we cannot allow it if (action == 1 && ginfo.ArenaType == 0) { //if player is trying to enter battleground (not arena!) and he has deserter debuff, we must just remove him from queue if (!_player->CanJoinToBattleground(bg)) { //send bg command result to show nice message WorldPacket data2; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data2, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->SendDirectMessage(&data2); action = 0; TC_LOG_DEBUG("bg.battleground", "Player %s (%u) has a deserter debuff, do not port him to battleground!", _player->GetName().c_str(), _player->GetGUID().GetCounter()); } //if player don't match battleground max level, then do not allow him to enter! (this might happen when player leveled up during his waiting in queue if (_player->getLevel() > bg->GetMaxLevel()) { TC_LOG_ERROR("network", "Player %s (%u) has level (%u) higher than maxlevel (%u) of battleground (%u)! Do not port him to battleground!", _player->GetName().c_str(), _player->GetGUID().GetCounter(), _player->getLevel(), bg->GetMaxLevel(), bg->GetTypeID()); action = 0; } } uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); WorldPacket data; if (action) { // check Freeze debuff if (_player->HasAura(9454)) return; if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId)) return; // cheating? if (!_player->InBattleground()) _player->SetBattlegroundEntryPoint(); // resurrect the player if (!_player->IsAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } // stop taxi flight at port _player->FinishTaxiFlight(); sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), ginfo.Team); _player->SendDirectMessage(&data); // remove battleground queue status from BGmgr bgQueue.RemovePlayer(_player->GetGUID(), false); // this is still needed here if battleground "jumping" shouldn't add deserter debuff // also this is required to prevent stuck at old battleground after SetBattlegroundId set to new if (Battleground* currentBg = _player->GetBattleground()) currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); // set the destination instance id _player->SetBattlegroundId(bg->GetInstanceID(), bgTypeId); // set the destination team _player->SetBGTeam(ginfo.Team); // bg->HandleBeforeTeleportToBattleground(_player); sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); // add only in HandleMoveWorldPortAck() // bg->AddPlayer(_player, team); TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().GetCounter(), bg->GetInstanceID(), bg->GetTypeID(), bgQueueTypeId); } else // leave queue { if (bg->isArena() && bg->GetStatus() > STATUS_WAIT_QUEUE) return; // if player leaves rated arena match before match start, it is counted as he played but he lost if (ginfo.IsRated && ginfo.IsInvitedToBGInstanceGUID) { ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(ginfo.Team); if (at) { TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %s by opponents rating: %u, because he has left queue!", _player->GetGUID().ToString().c_str(), ginfo.OpponentsTeamRating); at->MemberLost(_player, ginfo.OpponentsMatchmakerRating); at->SaveToDB(); } } _player->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0); bgQueue.RemovePlayer(_player->GetGUID(), true); // player left queue, we should update it - do not update Arena Queue if (!ginfo.ArenaType) sBattlegroundMgr->ScheduleQueueUpdate(ginfo.ArenaMatchmakerRating, ginfo.ArenaType, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player %s (%u) left queue for bgtype %u, queue type %u.", _player->GetName().c_str(), _player->GetGUID().GetCounter(), bg->GetTypeID(), bgQueueTypeId); // track if player refuses to join the BG after being invited if (bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK); stmt->setUInt32(0, _player->GetGUID().GetCounter()); stmt->setUInt8(1, BG_DESERTION_TYPE_LEAVE_QUEUE); CharacterDatabase.Execute(stmt); } } }
void WorldSession::HandleStablePet(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Recv CMSG_STABLE_PET"); uint32 PetGUID; uint8 petnumber; ObjectGuid npcGUID; recvData >> PetGUID >> petnumber; recvData.ReadGuidMask(npcGUID, 5, 7, 3, 2, 6, 1, 0, 4); recvData.ReadGuidBytes(npcGUID, 0, 3, 2, 6, 5, 7, 4, 1); if (!CheckStableMaster(npcGUID)) { SendStableResult(STABLE_ERR_STABLE); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); PetSlots temp = GetPlayer()->GetSession()->checkPets(petnumber, PetGUID); // if (_player->GetPet() && (_player->GetPet()->GetCharmInfo()->GetPetNumber() == PetGUID || GetPlayer()->GetSlot() == temp.slot) && (_player->GetPet()->GetCharmInfo()->GetPetNumber() == temp.entry || GetPlayer()->GetSlot() == petnumber)) if (!GetPlayer()->GetPet()) { if (!GetPlayer()->GetSession()->movePet(petnumber, PetGUID)) { SendStableResult(STABLE_ERR_INVALID_SLOT); // Something whent wrong. return; } WorldPacket data(SMSG_PET_SLOT_UPDATED, 16); data << uint32(PetGUID); data << uint32(temp.slot); data << uint32(temp.entry); data << uint32(petnumber); SendPacket(&data); } else if (GetPlayer()->GetPet() && (GetPlayer()->GetPetSlot() != petnumber && GetPlayer()->GetPet()->GetCharmInfo()->GetPetNumber() != PetGUID)) { if (!GetPlayer()->GetSession()->movePet(petnumber, PetGUID)) { SendStableResult(STABLE_ERR_INVALID_SLOT); // Something whent wrong. return; } WorldPacket data(SMSG_PET_SLOT_UPDATED, 16); data << uint32(PetGUID); data << uint32(temp.slot); data << uint32(temp.entry); data << uint32(petnumber); SendPacket(&data); } else { SendStableResult(STABLE_ERR_INVALID_SLOT); // Dont reorder the active pet. return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, petnumber); stmt->setUInt32(1, _player->GetGUIDLow()); stmt->setUInt32(2, PetGUID); trans->Append(stmt); if ((temp.entry > 0 || temp.name.length() > 0) && temp.entry != PetGUID) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, temp.slot); stmt->setUInt32(1, _player->GetGUIDLow()); stmt->setUInt32(2, temp.entry); trans->Append(stmt); } CharacterDatabase.CommitTransaction(trans); SendStableResult(STABLE_SUCCESS_STABLE); }
static bool HandleNpcBotSpawnCommand(ChatHandler* handler, const char* args) { if (!*args) { handler->SendSysMessage(".npcbot spawn"); handler->SendSysMessage("Adds new npcbot spawn of given entry in world. You can shift-link the npc"); handler->SendSysMessage("Syntax: .npcbot spawn #entry"); handler->SetSentErrorMessage(true); return false; } char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); if (!charID) return false; uint32 id = atoi(charID); CreatureTemplate const* creInfo = sObjectMgr->GetCreatureTemplate(id); if (!creInfo) { handler->PSendSysMessage("creature %u does not exist!", id); handler->SetSentErrorMessage(true); return false; } if (!(creInfo->flags_extra & CREATURE_FLAG_EXTRA_NPCBOT)) { handler->PSendSysMessage("creature %u is not a npcbot!", id); handler->SetSentErrorMessage(true); return false; } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_NPCBOT_OWNER); //"SELECT owner FROM character_npcbot WHERE entry = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res1 = CharacterDatabase.Query(stmt); if (res1) { handler->PSendSysMessage("Npcbot %u already exists in `characters_npcbot` table!", id); handler->SendSysMessage("If you want to replace this bot to new location use '.npc move' command"); handler->SetSentErrorMessage(true); return false; } stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID); //"SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res2 = WorldDatabase.Query(stmt); if (res2) { handler->PSendSysMessage("Npcbot %u already exists in `creature` table!", id); handler->SetSentErrorMessage(true); return false; } Player* chr = handler->GetSession()->GetPlayer(); if (chr->GetTransport()) { handler->SendSysMessage("Cannot spawn bots on transport!"); handler->SetSentErrorMessage(true); return false; } float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); if (map->Instanceable()) { handler->SendSysMessage("Cannot spawn bots in instances!"); handler->SetSentErrorMessage(true); return false; } Creature* creature = new Creature(); if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) { delete creature; return false; } uint8 roleMask = BOT_ROLE_DPS; uint8 m_class = creature->GetCreatureTemplate()->trainer_class; if (!(m_class == CLASS_WARRIOR || m_class == CLASS_ROGUE || m_class == CLASS_PALADIN || m_class == CLASS_DEATH_KNIGHT || m_class == CLASS_SHAMAN || m_class == BOT_CLASS_BM)) roleMask |= BOT_ROLE_RANGED; if (m_class == CLASS_PRIEST || m_class == CLASS_DRUID || m_class == CLASS_SHAMAN || m_class == CLASS_PALADIN) roleMask |= BOT_ROLE_HEAL; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_NPCBOT); //"INSERT INTO characters_npcbot (entry, roles) VALUES (?, ?)", CONNECTION_SYNCH stmt->setUInt32(0, id); stmt->setUInt8(1, roleMask); CharacterDatabase.DirectExecute(stmt); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); uint32 db_guid = creature->GetSpawnId(); if (!creature->LoadBotCreatureFromDB(db_guid, map)) { handler->SendSysMessage("Cannot load npcbot from DB!"); handler->SetSentErrorMessage(true); //return false; delete creature; return false; } sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); handler->SendSysMessage("Npcbot successfully spawned."); return true; }
void Garrison::SaveToDB(SQLTransaction trans) { DeleteFromDB(_owner->GetGUID().GetCounter(), trans); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON); stmt->setUInt64(0, _owner->GetGUID().GetCounter()); stmt->setUInt32(1, _siteLevel->ID); stmt->setUInt32(2, _followerActivationsRemainingToday); trans->Append(stmt); for (uint32 building : _knownBuildings) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS); stmt->setUInt64(0, _owner->GetGUID().GetCounter()); stmt->setUInt32(1, building); trans->Append(stmt); } for (auto const& p : _plots) { Plot const& plot = p.second; if (plot.BuildingInfo.PacketInfo) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS); stmt->setUInt64(0, _owner->GetGUID().GetCounter()); stmt->setUInt32(1, plot.BuildingInfo.PacketInfo->GarrPlotInstanceID); stmt->setUInt32(2, plot.BuildingInfo.PacketInfo->GarrBuildingID); stmt->setUInt64(3, plot.BuildingInfo.PacketInfo->TimeBuilt); stmt->setBool(4, plot.BuildingInfo.PacketInfo->Active); trans->Append(stmt); } } for (auto const& p : _followers) { Follower const& follower = p.second; uint8 index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS); stmt->setUInt64(index++, follower.PacketInfo.DbID); stmt->setUInt64(index++, _owner->GetGUID().GetCounter()); stmt->setUInt32(index++, follower.PacketInfo.GarrFollowerID); stmt->setUInt32(index++, follower.PacketInfo.Quality); stmt->setUInt32(index++, follower.PacketInfo.FollowerLevel); stmt->setUInt32(index++, follower.PacketInfo.ItemLevelWeapon); stmt->setUInt32(index++, follower.PacketInfo.ItemLevelArmor); stmt->setUInt32(index++, follower.PacketInfo.Xp); stmt->setUInt32(index++, follower.PacketInfo.CurrentBuildingID); stmt->setUInt32(index++, follower.PacketInfo.CurrentMissionID); stmt->setUInt32(index++, follower.PacketInfo.FollowerStatus); trans->Append(stmt); uint8 slot = 0; for (GarrAbilityEntry const* ability : follower.PacketInfo.AbilityID) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES); stmt->setUInt64(0, follower.PacketInfo.DbID); stmt->setUInt32(1, ability->ID); stmt->setUInt8(2, slot++); trans->Append(stmt); } } }
void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime) { // global reset for all instances of the given map MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry->Instanceable()) return; TC_LOG_DEBUG("misc", "InstanceSaveManager::ResetOrWarnAll: Processing map %s (%u) on difficulty %u (warn? %u)", mapEntry->MapName->Str[sWorld->GetDefaultDbcLocale()], mapid, uint8(difficulty), warn); time_t now = time(NULL); if (!warn) { // calculate the next reset time time_t next_reset = GetSubsequentResetTime(mapid, difficulty, resetTime); if (!next_reset) return; // delete/promote instance binds from the DB, even if not loaded SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_CHAR_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_EXPIRE_CHAR_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); // promote loaded binds to instances of the given map for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) { if (itr->second->GetMapId() == mapid && itr->second->GetDifficultyID() == difficulty) _ResetSave(itr); else ++itr; } SetResetTimeFor(mapid, difficulty, next_reset); ScheduleReset(true, time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty, 0)); // Update it in the DB stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt32(0, next_reset); stmt->setUInt16(1, uint16(mapid)); stmt->setUInt8(2, uint8(difficulty)); CharacterDatabase.Execute(stmt); } // note: this isn't fast but it's meant to be executed very rarely Map const* map = sMapMgr->CreateBaseMap(mapid); // _not_ include difficulty MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); MapInstanced::InstancedMaps::iterator mitr; uint32 timeLeft; for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) { Map* map2 = mitr->second; if (!map2->IsDungeon()) continue; if (warn) { if (now >= resetTime) timeLeft = 0; else timeLeft = uint32(resetTime - now); ((InstanceMap*)map2)->SendResetWarnings(timeLeft); } else ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL); } /// @todo delete creature/gameobject respawn times even if the maps are not loaded }
void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) { uint8 arenaType; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 recvData >> arenaType >> unk2 >> bgTypeId_ >> unk >> action; // bgTypeId not valid if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) return; // player not in any queue, so can't really answer if (!_player->InBattlegroundQueue()) return; // get BattlegroundQueue for received BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenaType); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); // get group info from queue GroupQueueInfo ginfo; if (!bgQueue.GetPlayerGroupInfoData(_player->GetGUID(), &ginfo)) return; // to accept, player must be invited to particular battleground id if (!ginfo.IsInvitedToBGInstanceGUID && action == 1) return; Battleground* bg = sBattlegroundMgr->GetBattleground(ginfo.IsInvitedToBGInstanceGUID); // use template if leaving queue (instance might not be created yet) if (!bg && action == 0) bg = sBattlegroundMgr->GetBattlegroundTemplate(bgTypeId); if (!bg) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; // safety checks if (action == 1 && ginfo.ArenaType == 0) { // can't join with deserter, check it here right before joining to be sure if (!_player->CanJoinToBattleground()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); SendPacket(&data); action = 0; } if (_player->getLevel() > bg->GetMaxLevel()) action = 0; } // get player queue slot index for this bg (can be in up to 2 queues at the same time) uint32 queueSlot = _player->GetBattlegroundQueueIndex(bgQueueTypeId); WorldPacket data; switch (action) { case 1: // accept { // set entry point if not in battleground if (!_player->InBattleground()) _player->SetEntryPoint(); // resurrect the player if (!_player->IsAlive()) { _player->ResurrectPlayer(1.0f); _player->SpawnCorpseBones(); } TeamId teamId = ginfo.teamId; // remove player from all bg queues for (uint32 qslot = 0; qslot < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qslot) if (BattlegroundQueueTypeId q = _player->GetBattlegroundQueueTypeId(qslot)) { BattlegroundQueue& queue = sBattlegroundMgr->GetBattlegroundQueue(q); queue.RemovePlayer(_player->GetGUID(), (bgQueueTypeId == q), qslot); _player->RemoveBattlegroundQueueId(q); } // send status packet sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime(), bg->GetArenaType(), teamId); SendPacket(&data); _player->SetBattlegroundId(bg->GetInstanceID(), bg->GetBgTypeID(), queueSlot, true, bgTypeId == BATTLEGROUND_RB, teamId); sBattlegroundMgr->SendToBattleground(_player, ginfo.IsInvitedToBGInstanceGUID, bgTypeId); } break; case 0: // leave queue { bgQueue.RemovePlayer(_player->GetGUID(), false, queueSlot); _player->RemoveBattlegroundQueueId(bgQueueTypeId); // track if player refuses to join the BG after being invited if (bg->isBattleground() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS) && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN)) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt8(1, BG_DESERTION_TYPE_LEAVE_QUEUE); CharacterDatabase.Execute(stmt); } } break; default: break; } }
uint8 WorldSession::HandleLoadPetFromDBFirstCallback(PreparedQueryResult result, uint8 asynchLoadType) { if (!GetPlayer() || GetPlayer()->GetPet() || GetPlayer()->GetVehicle() || GetPlayer()->IsSpectator()) return PET_LOAD_ERROR; if (!result) return PET_LOAD_NO_RESULT; Field* fields = result->Fetch(); // Xinef: this can happen if fetch is called twice, impossibru. if (!fields) return PET_LOAD_ERROR; Player* owner = GetPlayer(); // update for case of current pet "slot = 0" uint32 petentry = fields[1].GetUInt32(); if (!petentry) return PET_LOAD_NO_RESULT; uint8 petSlot = fields[7].GetUInt8(); bool current = petSlot == PET_SAVE_AS_CURRENT; uint32 summon_spell_id = fields[15].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); // CANT BE NULL bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; uint32 pet_number = fields[0].GetUInt32(); uint32 savedhealth = fields[10].GetUInt32(); uint32 savedmana = fields[11].GetUInt32(); PetType pet_type = PetType(fields[16].GetUInt8()); // xinef: BG resurrect, overwrite saved value if (asynchLoadType == PET_LOAD_BG_RESURRECT) savedhealth = 1; if (pet_type == HUNTER_PET && savedhealth == 0 && asynchLoadType != PET_LOAD_SUMMON_DEAD_PET) { WorldPacket data(SMSG_CAST_FAILED, 1+4+1+4); data << uint8(0); data << uint32(883); data << uint8(SPELL_FAILED_TARGETS_DEAD); SendPacket(&data); owner->RemoveSpellCooldown(883, false); return PET_LOAD_ERROR; } // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) return PET_LOAD_ERROR; if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); if (!creatureInfo || !creatureInfo->IsTameable(owner->CanTameExoticPets())) return PET_LOAD_ERROR; } Map* map = owner->GetMap(); uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET); Pet* pet = new Pet(owner, pet_type); LoadPetFromDBQueryHolder* holder = new LoadPetFromDBQueryHolder(pet_number, current, uint32(time(NULL) - fields[14].GetUInt32()), fields[13].GetString(), savedhealth, savedmana); if (!pet->Create(guid, map, owner->GetPhaseMask(), petentry, pet_number) || !holder->Initialize()) { delete pet; delete holder; return PET_LOAD_ERROR; } float px, py, pz; owner->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); if (!pet->IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUIDLow(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY()); delete pet; delete holder; return PET_LOAD_ERROR; } pet->SetLoading(true); pet->Relocate(px, py, pz, owner->GetOrientation()); pet->setPetType(pet_type); pet->setFaction(owner->getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); if (pet->IsCritter()) { map->AddToMap(pet->ToCreature(), true); pet->SetLoading(false); // xinef, mine delete holder; return PET_LOAD_OK; } pet->GetCharmInfo()->SetPetNumber(pet_number, pet->IsPermanentPetFor(owner)); pet->SetDisplayId(fields[3].GetUInt32()); pet->SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt8(); pet->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); pet->SetName(fields[8].GetString()); switch (pet->getPetType()) { case SUMMON_PET: petlevel = owner->getLevel(); if (pet->IsPetGhoul()) pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x400); // class = rogue else pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus pet->SetSheath(SHEATH_STATE_MELEE); pet->SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) pet->SetMaxPower(POWER_HAPPINESS, pet->GetCreatePowers(POWER_HAPPINESS)); pet->SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); pet->setPowerType(POWER_FOCUS); break; default: if (!pet->IsPetGhoul()) sLog->outError("Pet have incorrect type (%u) for pet loading.", pet->getPetType()); break; } pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here pet->SetCreatorGUID(owner->GetGUID()); owner->SetMinion(pet, true); pet->InitStatsForLevel(petlevel); pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); pet->SynchronizeLevelWithOwner(); pet->SetReactState(ReactStates(fields[6].GetUInt8())); pet->SetCanModifyStats(true); // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (petSlot) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID); stmt->setUInt8(0, uint8(PET_SAVE_NOT_IN_SLOT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt8(2, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(3, pet_number); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt32(2, pet_number); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? if (summon_spell_id) { WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2)); data.append(owner->GetPackGUID()); data.append(owner->GetPackGUID()); data << uint8(0); data << uint32(summon_spell_id); data << uint32(256); // CAST_FLAG_UNKNOWN3 data << uint32(0); owner->SendMessageToSet(&data, true); } // do it as early as possible! pet->InitTalentForLevel(); // set original talents points before spell loading if (!is_temporary_summoned) pet->GetCharmInfo()->InitPetActionBar(); map->AddToMap(pet->ToCreature(), true); if (pet->getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); else { pet->SetHealth(savedhealth > pet->GetMaxHealth() ? pet->GetMaxHealth() : savedhealth); pet->SetPower(POWER_MANA, savedmana > pet->GetMaxPower(POWER_MANA) ? pet->GetMaxPower(POWER_MANA) : savedmana); } pet->SetAsynchLoadType(asynchLoadType); // xinef: clear any old result if (_loadPetFromDBSecondCallback.ready()) { SQLQueryHolder* param; _loadPetFromDBSecondCallback.get(param); delete param; } _loadPetFromDBSecondCallback.cancel(); _loadPetFromDBSecondCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); return PET_LOAD_OK; }
void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId) { int32 serverRealmId = realmId != -1 ? realmId : ConfigMgr::GetIntDefault("RealmID", 0); bool needDelete = false; if (!rbac) { needDelete = true; rbac = new RBACData(accountId, "", serverRealmId); rbac->LoadFromDB(); } // Get max security level and realm (checking current realm and -1) PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID); stmt->setUInt32(0, accountId); stmt->setInt32(1, serverRealmId); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) { do { Field* field = result->Fetch(); uint8 secLevel = field[0].GetUInt8(); int32 realmId = field[1].GetUInt32(); RBACGroupContainer const& groupsToRemove = _defaultSecGroups[secLevel]; for (RBACGroupContainer::const_iterator it = groupsToRemove.begin(); it != groupsToRemove.end(); ++it) rbac->RemoveGroup(*it, realmId); } while (result->NextRow()); } // Add new groups depending on the new security Level RBACGroupContainer const& groupsToAdd = _defaultSecGroups[securityLevel]; for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it) rbac->AddGroup(*it, realmId); if (needDelete) delete rbac; // Delete old security level from DB if (realmId == -1) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); stmt->setUInt32(0, accountId); LoginDatabase.Execute(stmt); } else { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); stmt->setUInt32(0, accountId); stmt->setUInt32(1, realmId); LoginDatabase.Execute(stmt); } // Add new security level if (securityLevel) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); stmt->setUInt32(0, accountId); stmt->setUInt8(1, securityLevel); stmt->setInt32(2, realmId); LoginDatabase.Execute(stmt); } }
static void HandleDisables(ChatHandler* handler, char const* args, uint8 disableType) { char* cEntry = strtok((char*)args, " "); if (!cEntry || !atoi(cEntry)) { handler->SendSysMessage("No entry specified."); return; } char* cFlags = strtok(NULL, " "); if (!cFlags || !atoi(cFlags)) { handler->SendSysMessage("No flags specified."); return; } char* cComment = strtok(NULL, ""); if (!cComment) { handler->SendSysMessage("No comment specified."); return; } std::string entryStr = cEntry; std::string disableComment = cComment; uint32 entry = (uint32)atoi(cEntry); uint8 flags = atoi(cFlags); std::string disableTypeStr = ""; switch (disableType) { case DISABLE_TYPE_SPELL: disableTypeStr = "spell"; break; case DISABLE_TYPE_MAP: disableTypeStr = "map"; break; case DISABLE_TYPE_BATTLEGROUND: disableTypeStr = "battleground"; break; case DISABLE_TYPE_ACHIEVEMENT_CRITERIA: disableTypeStr = "achievement criteria"; break; case DISABLE_TYPE_OUTDOORPVP: disableTypeStr = "outdoorpvp"; break; case DISABLE_TYPE_VMAP: disableTypeStr = "vmap"; break; } PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SELECT_DISABLES); stmt->setUInt32(0, entry); stmt->setUInt8(1, disableType); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) { handler->PSendSysMessage("This %s (id %u) is already disabled.", disableTypeStr.c_str(), entry); return; } PreparedStatement* stmt2 = WorldDatabase.GetPreparedStatement(WORLD_INSERT_DISABLES); stmt2->setUInt32(0, entry); stmt2->setUInt8(1, disableType); stmt2->setUInt16(2, flags); stmt2->setString(3, disableComment); WorldDatabase.Execute(stmt2); handler->PSendSysMessage("Disabled %s %u for reason %s", disableTypeStr.c_str(), entry, disableComment.c_str()); return; }
static bool HandleWpLoadCommand(ChatHandler* handler, const char* args) { if (!*args) return false; // optional char* path_number = NULL; if (*args) path_number = strtok((char*)args, " "); uint32 pathid = 0; uint32 guidLow = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a path_id? if (!path_number) return false; if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } if (target->GetEntry() == 1) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?"); handler->SetSentErrorMessage(true); return false; } pathid = atoi(path_number); if (!pathid) { handler->PSendSysMessage("%s%s|r", "|cffff33ff", "No valid path number provided."); return true; } guidLow = target->GetDBTableGUIDLow(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID); stmt->setUInt32(0, guidLow); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) { stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ADDON_PATH); stmt->setUInt32(0, pathid); stmt->setUInt32(1, guidLow); } else { stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE_ADDON); stmt->setUInt32(0, guidLow); stmt->setUInt32(1, pathid); } WorldDatabase.Execute(stmt); stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE); stmt->setUInt8(0, uint8(WAYPOINT_MOTION_TYPE)); stmt->setUInt32(1, guidLow); WorldDatabase.Execute(stmt); target->LoadPath(pathid); target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); target->GetMotionMaster()->Initialize(); target->MonsterSay("Path loaded.", 0, 0); return true; }
/// %Log the player out void WorldSession::LogoutPlayer(bool save) { // finish pending transfers before starting the logout while (_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); m_playerLogout = true; m_playerSave = save; if (_player) { if (uint64 lguid = _player->GetLootGUID()) DoLootRelease(lguid); ///- If the player just died before logging out, make him appear as a ghost //FIXME: logout must be delayed in case lost connection with client in time of combat if (_player->GetDeathTimer()) { _player->getHostileRefManager().deleteReferences(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) { // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION _player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); _player->KillPlayer(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } else if (_player->HasPendingBind()) { _player->RepopAtGraveyard(); _player->SetPendingBind(0, 0); } // pussywizard: leave whole bg on logout (character stays ingame when necessary) // pussywizard: GetBattleground() checked inside _player->LeaveBattleground(); // pussywizard: checked first time if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster()) _player->RepopAtGraveyard(); sOutdoorPvPMgr->HandlePlayerLeaveZone(_player, _player->GetZoneId()); // pussywizard: remove from battleground queues on logout for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) if (BattlegroundQueueTypeId bgQueueTypeId = _player->GetBattlegroundQueueTypeId(i)) { _player->RemoveBattlegroundQueueId(bgQueueTypeId); sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(_player->GetGUID(), false, i); // track if player logs out after invited to join BG if(_player->IsInvitedForBattlegroundInstance() && sWorld->getBoolConfig(CONFIG_BATTLEGROUND_TRACK_DESERTERS)) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_DESERTER_TRACK); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt8(1, BG_DESERTION_TYPE_INVITE_LOGOUT); CharacterDatabase.Execute(stmt); } } ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId())) guild->HandleMemberLogout(this); ///- Remove pet _player->RemovePet(NULL, PET_SAVE_AS_CURRENT); // pussywizard: on logout remove auras that are removed at map change (before saving to db) // there are some positive auras from boss encounters that can be kept by logging out and logging in after boss is dead, and may be used on next bosses _player->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. _player->UninviteFromGroup(); // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket) _player->RemoveFromGroup(); // pussywizard: checked second time after being removed from a group if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster()) _player->RepopAtGraveyard(); // Repop at GraveYard or other player far teleport will prevent saving player because of not present map // Teleport player immediately for correct player save while (_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); ///- empty buyback items and save the player in the database // some save parts only correctly work in case player present in map/player_lists (pets, etc) SavingSystemMgr::InsertToSavingSkipListIfNeeded(_player->GetNextSave()); // pussywizard if (save) { uint32 eslot; for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j) { eslot = j - BUYBACK_SLOT_START; _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), 0); _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0); _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0); } _player->SaveToDB(false, true); } ///- Leave all channels before player delete... _player->CleanupChannels(); //! Send update to group and reset stored max enchanting level if (_player->GetGroup()) { _player->GetGroup()->SendUpdate(); _player->GetGroup()->ResetMaxEnchantingLevel(); } //! Broadcast a logout message to the player's friends if (AccountMgr::IsGMAccount(GetSecurity())) // pussywizard: only for non-gms sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); sSocialMgr->RemovePlayerSocial(_player->GetGUIDLow()); //! Call script hook before deletion sScriptMgr->OnPlayerLogout(_player); sLog->outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName().c_str(), _player->GetGUIDLow(), _player->getLevel()); //! Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes _player->CleanupsBeforeDelete(); if (Map* _map = _player->FindMap()) { _map->RemovePlayerFromMap(_player, true); _map->AfterPlayerUnlinkFromMap(); } SetPlayer(NULL); // pointer already deleted //! Send the 'logout complete' packet to the client //! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); SendPacket(&data); #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); #endif //! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ACCOUNT_ONLINE); stmt->setUInt32(0, GetAccountId()); CharacterDatabase.Execute(stmt); } m_playerLogout = false; m_playerSave = false; LogoutRequest(0); }
bool ArenaTeam::AddMember(uint64 playerGuid) { std::string playerName; uint8 playerClass; // Check if arena team is full (Can't have more than type * 2 players) if (GetMembersSize() >= GetType() * 2) return false; // xinef: Get player name and class from player storage or global data storage Player* player = ObjectAccessor::FindPlayerInOrOutOfWorld(playerGuid); if (player) { playerClass = player->getClass(); playerName = player->GetName(); } else { GlobalPlayerData const* playerData = sWorld->GetGlobalPlayerData(GUID_LOPART(playerGuid)); if (!playerData) return false; playerName = playerData->name; playerClass = playerData->playerClass; } // Check if player is already in a similar arena team if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromStorage(GUID_LOPART(playerGuid), GetSlot()) != 0) { sLog->outError("Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType()); return false; } // Set player's personal rating uint32 personalRating = 0; if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0) personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING); else if (GetRating() >= 1000) personalRating = 1000; // xinef: zomg! sync query // Try to get player's match maker rating from db and fall back to config setting if not found PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING); stmt->setUInt32(0, GUID_LOPART(playerGuid)); stmt->setUInt8(1, GetSlot()); PreparedQueryResult result = CharacterDatabase.Query(stmt); uint16 matchMakerRating; uint16 maxMMR; if (result) { matchMakerRating = (*result)[0].GetUInt16(); uint16 Max = (*result)[1].GetUInt16(); maxMMR = std::max(Max, matchMakerRating); } else { matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING); maxMMR = matchMakerRating; } // Remove all player signatures from other petitions // This will prevent player from joining too many arena teams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(playerGuid, GetType()); // Feed data to the struct ArenaTeamMember newMember; //newMember.Name = playerName; newMember.Guid = playerGuid; newMember.Class = playerClass; newMember.SeasonGames = 0; newMember.WeekGames = 0; newMember.SeasonWins = 0; newMember.WeekWins = 0; newMember.PersonalRating = personalRating; newMember.MatchMakerRating = matchMakerRating; newMember.MaxMMR = maxMMR; Members.push_back(newMember); sWorld->UpdateGlobalPlayerArenaTeam(GUID_LOPART(playerGuid), GetSlot(), GetId()); // Save player's arena team membership to db stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER); stmt->setUInt32(0, TeamId); stmt->setUInt32(1, GUID_LOPART(playerGuid)); CharacterDatabase.Execute(stmt); // Inform player if online if (player) { player->SetInArenaTeam(TeamId, GetSlot(), GetType()); player->SetArenaTeamIdInvited(0); // Hide promote/remove buttons if (CaptainGuid != playerGuid) player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } return true; }
//add move for creature static bool HandleNpcAddMoveCommand(ChatHandler* handler, const char* args) { if (!*args) return false; char* guidStr = strtok((char*)args, " "); char* waitStr = strtok((char*)NULL, " "); uint32 lowGuid = atoi((char*)guidStr); Creature* creature = NULL; /* FIXME: impossible without entry if (lowguid) creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT)); */ // attempt check creature existence by DB data if (!creature) { CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid); if (!data) { handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid); handler->SetSentErrorMessage(true); return false; } } else { // obtain real GUID for DB operations lowGuid = creature->GetDBTableGUIDLow(); } int wait = waitStr ? atoi(waitStr) : 0; if (wait < 0) wait = 0; // Update movement type PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE); stmt->setUInt8(0, uint8(WAYPOINT_MOTION_TYPE)); stmt->setUInt32(1, lowGuid); WorldDatabase.Execute(stmt); if (creature && creature->GetWaypointPath()) { creature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); creature->GetMotionMaster()->Initialize(); if (creature->isAlive()) // dead creature will reset movement generator at respawn { creature->setDeathState(JUST_DIED); creature->Respawn(true); } creature->SaveToDB(); } handler->SendSysMessage(LANG_WAYPOINT_ADDED); return true; }
void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, time_t resetTime) { // global reset for all instances of the given map MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); if (!mapEntry->Instanceable()) return; time_t now = time(NULL); if (!warn) { MapDifficulty const* mapDiff = GetMapDifficultyData(mapid, difficulty); if (!mapDiff || !mapDiff->resetTime) { TC_LOG_ERROR(LOG_FILTER_GENERAL, "InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); return; } // remove all binds to instances of the given map for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) { if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) _ResetSave(itr); else ++itr; } // delete them from the DB, even if not loaded SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INSTANCE_BY_MAP_DIFF); stmt->setUInt16(0, uint16(mapid)); stmt->setUInt8(1, uint8(difficulty)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); // calculate the next reset time uint32 diff = sWorld->getIntConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY); if (period < DAY) period = DAY; uint32 next_reset = uint32(((resetTime + MINUTE) / DAY * DAY) + period + diff); SetResetTimeFor(mapid, difficulty, next_reset); ScheduleReset(true, time_t(next_reset-3600), InstResetEvent(1, mapid, difficulty, 0)); // Update it in the DB stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME); stmt->setUInt32(0, next_reset); stmt->setUInt16(1, uint16(mapid)); stmt->setUInt8(2, uint8(difficulty)); CharacterDatabase.Execute(stmt); } // note: this isn't fast but it's meant to be executed very rarely Map const* map = sMapMgr->CreateBaseMap(mapid); // _not_ include difficulty MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); MapInstanced::InstancedMaps::iterator mitr; uint32 timeLeft; for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) { Map* map2 = mitr->second; if (!map2->IsDungeon()) continue; if (warn) { if (now <= resetTime) timeLeft = 0; else timeLeft = uint32(now - resetTime); ((InstanceMap*)map2)->SendResetWarnings(timeLeft); } else ((InstanceMap*)map2)->Reset(INSTANCE_RESET_GLOBAL); } /// @todo delete creature/gameobject respawn times even if the maps are not loaded }
/// Set/Unset the expansion level for an account static bool HandleAccountSetAddonCommand(ChatHandler* handler, char const* args) { ///- Get the command line arguments char* account = strtok((char*)args, " "); char* exp = strtok(NULL, " "); if (!account) return false; std::string accountName; uint32 accountId; if (!exp) { Player* player = handler->getSelectedPlayer(); if (!player) return false; accountId = player->GetSession()->GetAccountId(); AccountMgr::GetName(accountId, accountName); exp = account; } else { ///- Convert Account name to Upper Format accountName = account; if (!AccountMgr::normalizeString(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } accountId = AccountMgr::GetId(accountName); if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } } // Let set addon state only for lesser (strong) security level // or to self account if (handler->GetSession() && handler->GetSession()->GetAccountId () != accountId && handler->HasLowerSecurityAccount(NULL, accountId, true)) return false; int expansion = atoi(exp); //get int anyway (0 if error) if (expansion < 0 || uint8(expansion) > sWorld->getIntConfig(CONFIG_EXPANSION)) return false; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPDATE_EXPANSION); stmt->setUInt8(0, expansion); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); handler->PSendSysMessage(LANG_ACCOUNT_SETADDON, accountName.c_str(), accountId, expansion); return true; }
bool ArenaTeam::AddMember(uint64 playerGuid) { std::string playerName; uint8 playerClass; // Check if arena team is full (Can't have more than type * 2 players) if (GetMembersSize() >= GetType() * 2) return false; // Get player name and class either from db or ObjectMgr Player* player = ObjectAccessor::FindPlayer(playerGuid); if (player) { playerClass = player->getClass(); playerName = player->GetName(); } else { // 0 1 // SELECT name, class FROM characters WHERE guid = ? PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_CLASS); stmt->setUInt32(0, GUID_LOPART(playerGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return false; playerName = (*result)[0].GetString(); playerClass = (*result)[1].GetUInt8(); } // Check if player is already in a similar arena team if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) { TC_LOG_DEBUG("bg.arena", "Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType()); return false; } // Set player's personal rating uint32 personalRating = 0; if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) > 0) personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING); else if (GetRating() >= 1000) personalRating = 1000; // Try to get player's match maker rating from db and fall back to config setting if not found PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING); stmt->setUInt32(0, GUID_LOPART(playerGuid)); stmt->setUInt8(1, GetSlot()); PreparedQueryResult result = CharacterDatabase.Query(stmt); uint32 matchMakerRating; if (result) matchMakerRating = (*result)[0].GetUInt16(); else matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING); // Remove all player signatures from other petitions // This will prevent player from joining too many arena teams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(playerGuid, GetType()); // Feed data to the struct ArenaTeamMember newMember; newMember.Name = playerName; newMember.Guid = playerGuid; newMember.Class = playerClass; newMember.SeasonGames = 0; newMember.WeekGames = 0; newMember.SeasonWins = 0; newMember.WeekWins = 0; newMember.PersonalRating = personalRating; newMember.MatchMakerRating = matchMakerRating; Members.push_back(newMember); // Save player's arena team membership to db stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER); stmt->setUInt32(0, TeamId); stmt->setUInt32(1, GUID_LOPART(playerGuid)); CharacterDatabase.Execute(stmt); // Inform player if online if (player) { player->SetInArenaTeam(TeamId, GetSlot(), GetType()); player->SetArenaTeamIdInvited(0); // Hide promote/remove buttons if (CaptainGuid != playerGuid) player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } TC_LOG_DEBUG("bg.arena", "Player: %s [GUID: %u] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId(), GetName().c_str()); return true; }
static bool HandleAccountSetGmLevelCommand(ChatHandler* handler, char const* args) { if (!*args) return false; std::string targetAccountName; uint32 targetAccountId = 0; uint32 targetSecurity = 0; uint32 gm = 0; char* arg1 = strtok((char*)args, " "); char* arg2 = strtok(NULL, " "); char* arg3 = strtok(NULL, " "); bool isAccountNameGiven = true; if (arg1 && !arg3) { if (!handler->getSelectedPlayer()) return false; isAccountNameGiven = false; } // Check for second parameter if (!isAccountNameGiven && !arg2) return false; // Check for account if (isAccountNameGiven) { targetAccountName = arg1; if (!AccountMgr::normalizeString(targetAccountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str()); handler->SetSentErrorMessage(true); return false; } } // Check for invalid specified GM level. gm = (isAccountNameGiven) ? atoi(arg2) : atoi(arg1); if (gm > SEC_CONSOLE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } // handler->getSession() == NULL only for console targetAccountId = (isAccountNameGiven) ? AccountMgr::GetId(targetAccountName) : handler->getSelectedPlayer()->GetSession()->GetAccountId(); int32 gmRealmID = (isAccountNameGiven) ? atoi(arg3) : atoi(arg2); uint32 playerSecurity; if (handler->GetSession()) playerSecurity = AccountMgr::GetSecurity(handler->GetSession()->GetAccountId(), gmRealmID); else playerSecurity = SEC_CONSOLE; // can set security level only for target with less security and to less security that we have // This is also reject self apply in fact targetSecurity = AccountMgr::GetSecurity(targetAccountId, gmRealmID); if (targetSecurity >= playerSecurity || gm >= playerSecurity) { handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); handler->SetSentErrorMessage(true); return false; } // Check and abort if the target gm has a higher rank on one of the realms and the new realm is -1 if (gmRealmID == -1 && !AccountMgr::IsConsoleAccount(playerSecurity)) { QueryResult result = LoginDatabase.PQuery("SELECT * FROM account_access WHERE id = '%u' AND gmlevel > '%d'", targetAccountId, gm); if (result) { handler->SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); handler->SetSentErrorMessage(true); return false; } } // Check if provided realmID has a negative value other than -1 if (gmRealmID < -1) { handler->SendSysMessage(LANG_INVALID_REALMID); handler->SetSentErrorMessage(true); return false; } // If gmRealmID is -1, delete all values for the account id, else, insert values for the specific realmID PreparedStatement* stmt; if (gmRealmID == -1) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); stmt->setUInt32(0, targetAccountId); } else { stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); stmt->setUInt32(0, targetAccountId); stmt->setUInt32(1, realmID); } LoginDatabase.Execute(stmt); if (gm != 0) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); stmt->setUInt32(0, targetAccountId); stmt->setUInt8(1, uint8(gm)); stmt->setInt32(2, gmRealmID); LoginDatabase.Execute(stmt); } handler->PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); return true; }
void BattlePetMgr::SaveToDB(SQLTransaction& trans) { PreparedStatement* stmt = nullptr; for (auto itr = _pets.begin(); itr != _pets.end();) { switch (itr->second.SaveInfo) { case BATTLE_PET_NEW: stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BATTLE_PETS); stmt->setUInt64(0, itr->first); stmt->setUInt32(1, _owner->GetBattlenetAccountId()); stmt->setUInt32(2, itr->second.PacketInfo.Species); stmt->setUInt16(3, itr->second.PacketInfo.Breed); stmt->setUInt16(4, itr->second.PacketInfo.Level); stmt->setUInt16(5, itr->second.PacketInfo.Exp); stmt->setUInt32(6, itr->second.PacketInfo.Health); stmt->setUInt8(7, itr->second.PacketInfo.Quality); stmt->setUInt16(8, itr->second.PacketInfo.Flags); stmt->setString(9, itr->second.PacketInfo.Name); trans->Append(stmt); itr->second.SaveInfo = BATTLE_PET_UNCHANGED; ++itr; break; case BATTLE_PET_CHANGED: stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BATTLE_PETS); stmt->setUInt16(0, itr->second.PacketInfo.Level); stmt->setUInt16(1, itr->second.PacketInfo.Exp); stmt->setUInt32(2, itr->second.PacketInfo.Health); stmt->setUInt8(3, itr->second.PacketInfo.Quality); stmt->setUInt16(4, itr->second.PacketInfo.Flags); stmt->setString(5, itr->second.PacketInfo.Name); stmt->setUInt32(6, _owner->GetBattlenetAccountId()); stmt->setUInt64(7, itr->first); trans->Append(stmt); itr->second.SaveInfo = BATTLE_PET_UNCHANGED; ++itr; break; case BATTLE_PET_REMOVED: stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BATTLE_PETS); stmt->setUInt32(0, _owner->GetBattlenetAccountId()); stmt->setUInt64(1, itr->first); trans->Append(stmt); itr = _pets.erase(itr); break; default: ++itr; break; } } stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_BATTLE_PET_SLOTS); stmt->setUInt32(0, _owner->GetBattlenetAccountId()); trans->Append(stmt); for (WorldPackets::BattlePet::BattlePetSlot const& slot : _slots) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BATTLE_PET_SLOTS); stmt->setUInt8(0, slot.Index); stmt->setUInt32(1, _owner->GetBattlenetAccountId()); stmt->setUInt64(2, slot.Pet.Guid.GetCounter()); stmt->setBool(3, slot.Locked); trans->Append(stmt); } }
// ACCOUNT_LOGOUT = 6 void AccountIPLogAction(uint32 accountId, IPLoggingTypes aType) { // Action IP Logger is only intialized if config is set up // Else, this script isn't loaded in the first place: We require no config check. // We declare all the required variables uint32 playerGuid = accountId; ObjectGuid::LowType characterGuid = 0; std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later. // With this switch, we change systemNote so that we have a more accurate phrasing of what type it is. // Avoids Magicnumbers in SQL table switch (aType) { case ACCOUNT_LOGIN: systemNote = "Logged on Successful AccountLogin"; break; case ACCOUNT_FAIL_LOGIN: systemNote = "Logged on Failed AccountLogin"; break; case ACCOUNT_CHANGE_PW: systemNote = "Logged on Successful Account Password Change"; break; case ACCOUNT_CHANGE_PW_FAIL: systemNote = "Logged on Failed Account Password Change"; break; case ACCOUNT_CHANGE_EMAIL: systemNote = "Logged on Successful Account Email Change"; break; case ACCOUNT_CHANGE_EMAIL_FAIL: systemNote = "Logged on Failed Account Email Change"; break; /*case ACCOUNT_LOGOUT: systemNote = "Logged on AccountLogout"; //Can not be logged break;*/ // Neither should happen. Ever. Period. If it does, call Ghostbusters and all your local software defences to investigate. case UNKNOWN_ACTION: default: systemNote = "ERROR! Unknown action!"; break; } // Once we have done everything, we can insert the new log. // Seeing as the time differences should be minimal, we do not get unixtime and the timestamp right now; // Rather, we let it be added with the SQL query. if (aType != ACCOUNT_FAIL_LOGIN) { // As we can assume most account actions are NOT failed login, so this is the more accurate check. // For those, we need last_ip... PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ALDL_IP_LOGGING); stmt->setUInt32(0, playerGuid); stmt->setUInt32(1, characterGuid); stmt->setUInt8(2, aType); stmt->setUInt32(3, playerGuid); stmt->setString(4, systemNote); LoginDatabase.Execute(stmt); } else // ... but for failed login, we query last_attempt_ip from account table. Which we do with an unique query { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FACL_IP_LOGGING); stmt->setUInt32(0, playerGuid); stmt->setUInt32(1, characterGuid); stmt->setUInt8(2, aType); stmt->setUInt32(3, playerGuid); stmt->setString(4, systemNote); LoginDatabase.Execute(stmt); } return; }