void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+4); uint64 guid; uint32 spellId = 0; recv_data >> guid >> spellId; sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId ); Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if(!unit->isCanTrainingOf(_player,true)) return; // check present spell in trainer spell list TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if(!trainer_spells) return; // not found, cheat? TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); if(!trainer_spell) return; // can't be learn, cheat? Or double learn with lags... if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) return; // apply reputation discount uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit))); // check money requirement if(_player->GetMoney() < nSpellCost ) return; WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer data << uint64(guid) << uint32(0xB3); SendPacket(&data); data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player data << uint64(_player->GetGUID()) << uint32(0x016A); SendPacket(&data); _player->ModifyMoney( -int32(nSpellCost) ); // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation _player->learnSpell(trainer_spell->spell); data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); data << uint64(guid) << uint32(spellId); SendPacket(&data); }
void WorldSession::HandleVoidSwapItem(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_SWAP_ITEM"); Player* player = GetPlayer(); uint32 newSlot; ObjectGuid npcGuid; ObjectGuid itemId; recvData >> newSlot; npcGuid[2] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); itemId[2] = recvData.ReadBit(); itemId[6] = recvData.ReadBit(); itemId[5] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[7] = recvData.ReadBit(); itemId[3] = recvData.ReadBit(); itemId[7] = recvData.ReadBit(); itemId[0] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); itemId[1] = recvData.ReadBit(); itemId[4] = recvData.ReadBit(); recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(itemId[3]); recvData.ReadByteSeq(itemId[2]); recvData.ReadByteSeq(itemId[4]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(itemId[6]); recvData.ReadByteSeq(itemId[1]); recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(itemId[5]); recvData.ReadByteSeq(npcGuid[6]); recvData.ReadByteSeq(itemId[0]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(itemId[7]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } uint8 oldSlot; if (!player->GetVoidStorageItem(itemId, oldSlot)) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) requested swapping an invalid item (slot: %u, itemid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), newSlot, uint64(itemId)); return; } bool usedSrcSlot = player->GetVoidStorageItem(oldSlot) != NULL; // should be always true bool usedDestSlot = player->GetVoidStorageItem(newSlot) != NULL; ObjectGuid itemIdDest; if (usedDestSlot) itemIdDest = player->GetVoidStorageItem(newSlot)->ItemId; if (!player->SwapVoidStorageItem(oldSlot, newSlot)) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1); return; } WorldPacket data(SMSG_VOID_ITEM_SWAP_RESPONSE, 1 + (usedSrcSlot + usedDestSlot) * (1 + 7 + 4)); data.WriteBit(!usedDestSlot); data.WriteBit(!usedSrcSlot); if (usedSrcSlot) { data.WriteBit(itemId[5]); data.WriteBit(itemId[2]); data.WriteBit(itemId[1]); data.WriteBit(itemId[4]); data.WriteBit(itemId[0]); data.WriteBit(itemId[6]); data.WriteBit(itemId[7]); data.WriteBit(itemId[3]); } data.WriteBit(!usedDestSlot); // unk if (usedDestSlot) { data.WriteBit(itemIdDest[7]); data.WriteBit(itemIdDest[3]); data.WriteBit(itemIdDest[4]); data.WriteBit(itemIdDest[0]); data.WriteBit(itemIdDest[5]); data.WriteBit(itemIdDest[1]); data.WriteBit(itemIdDest[2]); data.WriteBit(itemIdDest[6]); } data.WriteBit(!usedSrcSlot); // unk data.FlushBits(); if (usedDestSlot) { data.WriteByteSeq(itemIdDest[4]); data.WriteByteSeq(itemIdDest[6]); data.WriteByteSeq(itemIdDest[5]); data.WriteByteSeq(itemIdDest[2]); data.WriteByteSeq(itemIdDest[3]); data.WriteByteSeq(itemIdDest[1]); data.WriteByteSeq(itemIdDest[7]); data.WriteByteSeq(itemIdDest[0]); } if (usedSrcSlot) { data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(itemId[7]); } if (usedDestSlot) data << uint32(oldSlot); if (usedSrcSlot) data << uint32(newSlot); SendPacket(&data); }
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; typedef std::pair<ResetTimeMapDiffInstances::const_iterator, ResetTimeMapDiffInstances::const_iterator> ResetTimeMapDiffInstancesBounds; 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 result2 = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAX_CREATURE_RESPAWNS))) { do { Field* fields = result2->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].GetUInt8()); uint64 oldresettime = fields[2].GetUInt32(); 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); 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); 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; 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); } 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)); } }
void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID, bool activateAccept) const { std::string questTitle = quest->GetTitle(); std::string questDetails = quest->GetDetails(); std::string questObjectives = quest->GetObjectives(); std::string questEndText = quest->GetEndText(); int32 locale = _session->GetSessionDbLocaleIndex(); if (locale >= 0) { if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(quest->GetQuestId())) { ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle); ObjectMgr::GetLocaleString(localeData->Details, locale, questDetails); ObjectMgr::GetLocaleString(localeData->Objectives, locale, questObjectives); ObjectMgr::GetLocaleString(localeData->EndText, locale, questEndText); } } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); WorldPacket data(SMSG_QUESTGIVER_QUEST_DETAILS, 100); // guess size data << uint64(npcGUID); data << uint64(_session->GetPlayer()->GetDivider()); data << uint32(quest->GetQuestId()); data << questTitle; data << questDetails; data << questObjectives; data << uint8(activateAccept ? 1 : 0); // auto finish data << uint32(quest->GetFlags()); // 3.3.3 questFlags data << uint32(quest->GetSuggestedPlayers()); data << uint8(0); // IsFinished? value is sent back to server in quest accept packet if (quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { data << uint32(0); // Rewarded chosen items hidden data << uint32(0); // Rewarded items hidden data << uint32(0); // Rewarded money hidden data << uint32(0); // Rewarded XP hidden } else { data << uint32(quest->GetRewChoiceItemsCount()); for (uint32 i=0; i < QUEST_REWARD_CHOICES_COUNT; ++i) { if (!quest->RewardChoiceItemId[i]) continue; data << uint32(quest->RewardChoiceItemId[i]); data << uint32(quest->RewardChoiceItemCount[i]); if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i])) data << uint32(itemTemplate->DisplayInfoID); else data << uint32(0x00); } data << uint32(quest->GetRewItemsCount()); for (uint32 i=0; i < QUEST_REWARDS_COUNT; ++i) { if (!quest->RewardItemId[i]) continue; data << uint32(quest->RewardItemId[i]); data << uint32(quest->RewardItemIdCount[i]); if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i])) data << uint32(itemTemplate->DisplayInfoID); else data << uint32(0); } data << uint32(quest->GetRewOrReqMoney()); data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST)); } // rewarded honor points. Multiply with 10 to satisfy client data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest))); data << float(0.0f); // unk, honor multiplier? data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0) data << int32(quest->GetRewSpellCast()); // cast spell data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) data << uint32(quest->GetBonusTalents()); // bonus talents data << uint32(quest->GetRewArenaPoints()); // reward arena points data << uint32(0); // unk for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) data << uint32(quest->RewardFactionId[i]); for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) data << int32(quest->RewardFactionValueId[i]); for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) data << int32(quest->RewardFactionValueIdOverride[i]); data << uint32(QUEST_EMOTE_COUNT); for (uint32 i = 0; i < QUEST_EMOTE_COUNT; ++i) { data << uint32(quest->DetailsEmote[i]); data << uint32(quest->DetailsEmoteDelay[i]); // DetailsEmoteDelay (in ms) } _session->SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); }
void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, uint64 npcGUID, bool canComplete, bool closeOnCancel) const { // We can always call to RequestItems, but this packet only goes out if there are actually // items. Otherwise, we'll skip straight to the OfferReward std::string questTitle = quest->GetTitle(); std::string requestItemsText = quest->GetRequestItemsText(); int32 locale = _session->GetSessionDbLocaleIndex(); if (locale >= 0) { if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(quest->GetQuestId())) { ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle); ObjectMgr::GetLocaleString(localeData->RequestItemsText, locale, requestItemsText); } } if (!quest->GetReqItemsCount() && canComplete) { SendQuestGiverOfferReward(quest, npcGUID, true); return; } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); WorldPacket data(SMSG_QUESTGIVER_REQUEST_ITEMS, 50); // guess size data << uint64(npcGUID); data << uint32(quest->GetQuestId()); data << questTitle; data << requestItemsText; data << uint32(0); // unknown if (canComplete) data << quest->GetCompleteEmote(); else data << quest->GetIncompleteEmote(); // Close Window after cancel data << uint32(closeOnCancel); data << uint32(quest->GetFlags()); // 3.3.3 questFlags data << uint32(quest->GetSuggestedPlayers()); // SuggestedGroupNum // Required Money data << uint32(quest->GetRewOrReqMoney() < 0 ? -quest->GetRewOrReqMoney() : 0); data << uint32(quest->GetReqItemsCount()); for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { if (!quest->RequiredItemId[i]) continue; data << uint32(quest->RequiredItemId[i]); data << uint32(quest->RequiredItemCount[i]); if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i])) data << uint32(itemTemplate->DisplayInfoID); else data << uint32(0); } if (!canComplete) data << uint32(0x00); else data << uint32(0x03); data << uint32(0x04); data << uint32(0x08); data << uint32(0x10); _session->SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); }
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket & recv_data) { uint64 guid; uint32 trainerId; uint32 spellId, result = ERR_TRAINER_OK; recv_data >> guid >> trainerId >> spellId; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u", uint32(GUID_LOPART(guid)), spellId); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if (!unit->isCanTrainingOf(_player, true)) return; // check present spell in trainer spell list TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) return; // not found, cheat? TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); if (!trainer_spell) return; // can't be learn, cheat? Or double learn with lags... if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) return; // apply reputation discount uint64 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if (!_player->HasEnoughMoney(nSpellCost)) result = ERR_TRAINER_NOT_ENOUGH_MONEY; if (result == ERR_TRAINER_OK) { _player->ModifyMoney(-int32(nSpellCost)); unit->SendPlaySpellVisual(179); // 53 SpellCastDirected unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute // learn explicitly or cast explicitly if (trainer_spell->IsCastable()) _player->CastSpell(_player, trainer_spell->spell, true); else _player->learnSpell(spellId, false); } WorldPacket data(SMSG_TRAINER_BUY_RESULT, 16); data << uint64(guid); data << uint32(spellId); // should be same as in packet from client data << uint32(result); SendPacket(&data); }
void InstanceScript::LoadDoorData(const DoorData* data) { while (data->entry) { if (data->bossId < bosses.size()) doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary)))); ++data; } sLog->outDebug(LOG_FILTER_TSCR, "InstanceScript::LoadDoorData: " UI64FMTD " doors loaded.", uint64(doors.size())); }
void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) { uint64 ownerguid = 0; uint32 type; std::string name = "NO_NAME_FOR_GUID"; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); stmt->setUInt32(0, GUID_LOPART(petitionguid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); return; } WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) data << uint64(ownerguid); // charter owner guid data << name; // name (guild/arena team) data << uint8(0); // some string if (type == GUILD_CHARTER_TYPE) { uint32 needed = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); data << uint32(needed); data << uint32(needed); data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition } else { data << uint32(type-1); data << uint32(type-1); data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition } data << uint32(0); // 5 data << uint32(0); // 6 data << uint32(0); // 7 data << uint32(0); // 8 data << uint16(0); // 9 2 bytes field data << uint32(0); // 10 data << uint32(0); // 11 data << uint32(0); // 13 count of next strings? for (int i = 0; i < 10; ++i) data << uint8(0); // some string data << uint32(0); // 14 data << uint32(type != GUILD_CHARTER_TYPE); // 15 0 - guild, 1 - arena team SendPacket(&data); }
void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode MSG_PETITION_RENAME"); // ok uint64 petitionGuid; uint32 type; std::string newName; recvData >> petitionGuid; // guid recvData >> newName; // new name Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); type = fields[0].GetUInt8(); } else { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionGuid)); return; } if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(newName)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, newName); return; } if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, newName); return; } } else { if (sArenaTeamMgr->GetArenaTeamByName(newName)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_INVALID); return; } } stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); stmt->setString(0, newName); stmt->setUInt32(1, GUID_LOPART(petitionGuid)); CharacterDatabase.Execute(stmt); TC_LOG_DEBUG("network", "Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionGuid), newName.c_str()); WorldPacket data(MSG_PETITION_RENAME, (8+newName.size()+1)); data << uint64(petitionGuid); data << newName; SendPacket(&data); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) { if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; } data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); *data << player->GetPackGUID(); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { uint16 playerStatus = MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->isAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; *data << uint16(playerStatus); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()); if (mask & GROUP_UPDATE_FLAG_AURAS) { const uint64& auraMask = player->GetAuraUpdateMask(); *data << uint64(auraMask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auraMask & (uint64(1) << i)) { SpellAuraHolderPtr holder = player->GetVisibleAura(i); *data << uint32(holder ? holder->GetId() : 0); *data << uint8(holder ? holder->GetAuraFlags() : 0); } } } Pet* pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) *data << (pet ? pet->GetObjectGuid() : ObjectGuid()); if (mask & GROUP_UPDATE_FLAG_PET_NAME) *data << (pet ? pet->GetName() : uint8(0)); if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) *data << uint16(pet ? pet->GetDisplayId() : 0); if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) *data << uint32(pet ? pet->GetHealth() : 0); if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) *data << uint32(pet ? pet->GetMaxHealth() : 0); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) *data << uint8(pet ? pet->getPowerType() : 0); if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) *data << uint16(pet ? pet->GetPower(pet->getPowerType()) : 0); if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) *data << uint16(pet ? pet->GetMaxPower(pet->getPowerType()) : 0); if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { MAPLOCK_READ(pet, MAP_LOCK_TYPE_AURAS); const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { SpellAuraHolderPtr holder = pet->GetVisibleAura(i); *data << uint32(holder ? holder->GetId() : 0); *data << uint8(holder ? holder->GetAuraFlags() : 0); } } } else *data << uint64(0); } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) *data << uint32(player->m_movementInfo.GetTransportDBCSeat()); }
// this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 1 + 8 + 4 + 2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Powers powerType = player->getPowerType(); uint32 updateFlags = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_MODEL_ID | GROUP_UPDATE_FLAG_PET_AURAS; if (powerType != POWER_MANA) updateFlags |= GROUP_UPDATE_FLAG_POWER_TYPE; Pet* pet = player->GetPet(); if (pet) updateFlags |= GROUP_UPDATE_FLAG_PET_GUID | GROUP_UPDATE_FLAG_PET_CUR_HP | GROUP_UPDATE_FLAG_PET_MAX_HP | GROUP_UPDATE_FLAG_PET_POWER_TYPE | GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER; if (player->GetVehicle()) updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; uint16 playerStatus = player->IsReferAFriendLinked(player) ? (MEMBER_STATUS_ONLINE | MEMBER_STATUS_RAF) : MEMBER_STATUS_ONLINE; if (player->IsPvP()) playerStatus |= MEMBER_STATUS_PVP; if (!player->isAlive()) { if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) playerStatus |= MEMBER_STATUS_GHOST; else playerStatus |= MEMBER_STATUS_DEAD; } if (player->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) playerStatus |= MEMBER_STATUS_PVP_FFA; if (player->isAFK()) playerStatus |= MEMBER_STATUS_AFK; if (player->isDND()) playerStatus |= MEMBER_STATUS_DND; WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 255); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); data << uint32(updateFlags); data << uint16(playerStatus); // GROUP_UPDATE_FLAG_STATUS data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP if (updateFlags & GROUP_UPDATE_FLAG_POWER_TYPE) data << uint8(powerType); data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.GetMapId(), loc.x, loc.y, loc.z); iCoordX = loc.x; iCoordY = loc.y; } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolderPtr holder = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint8(holder->GetAuraFlags()); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if(pet) { Powers petPowerType = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petPowerType); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petPowerType)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petPowerType)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petAuraMask = 0; size_t petMaskPos = data.wpos(); data << uint64(petAuraMask); // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolderPtr holder = pet->GetVisibleAura(i)) { petAuraMask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint8(holder->GetAuraFlags()); } } data.put<uint64>(petMaskPos, petAuraMask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(0); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS } if (updateFlags & GROUP_UPDATE_FLAG_VEHICLE_SEAT) data << uint32(player->m_movementInfo.GetTransportDBCSeat()); SendPacket(&data); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) { DEBUG_LOG("WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player * player = HashMapHolder<Player>::Find(guid); if(!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet *pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if(pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets Powers powerType = player->getPowerType(); data << uint32(mask1); // group update mask data << uint16(MEMBER_STATUS_ONLINE); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL //verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; } else { //unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 aura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(aura); data << uint8(1); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if(pet) { Powers petpowertype = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { if(uint32 petaura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(petaura); data << uint8(1); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacket *data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); *data << player->GetPackGUID(); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player) { if (player->IsPvP()) *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << uint16(MEMBER_STATUS_ONLINE); } else *data << uint16(MEMBER_STATUS_OFFLINE); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()); if (mask & GROUP_UPDATE_FLAG_AURAS) { const uint64& auramask = player->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { *data << uint32(player->GetVisibleAura(i)); *data << uint8(1); } } } Pet *pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) *data << (pet ? pet->GetObjectGuid() : ObjectGuid()); if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if(pet) *data << pet->GetName(); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if(pet) *data << uint16(pet->GetDisplayId()); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if(pet) *data << uint32(pet->GetHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if(pet) *data << uint32(pet->GetMaxHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if(pet) *data << uint8(pet->getPowerType()); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if(pet) *data << uint16(pet->GetPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if(pet) *data << uint16(pet->GetMaxPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if(pet) { const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { *data << uint32(pet->GetVisibleAura(i)); *data << uint8(1); } } } else *data << uint64(0); } }
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_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; } } 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(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 WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask == GROUP_UPDATE_FLAG_NONE) return; if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); data->append(player->GetPackGUID()); *data << (uint32) mask; if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player) { if (player->IsPvP()) *data << (uint16) (MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << (uint16) MEMBER_STATUS_ONLINE; } else *data << (uint16) MEMBER_STATUS_OFFLINE; } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << (uint32) player->GetHealth(); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << (uint32) player->GetMaxHealth(); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << (uint8) powerType; if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << (uint16) player->GetPower(powerType); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << (uint16) player->GetMaxPower(powerType); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << (uint16) player->getLevel(); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << (uint16) player->GetZoneId(); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << (uint16) player->GetPositionX() << (uint16) player->GetPositionY(); if (mask & GROUP_UPDATE_FLAG_AURAS) { uint64 auramask = player->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } Pet* pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) { if (pet) *data << (uint64) pet->GetGUID(); else *data << (uint64) 0; } if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << (uint16) pet->GetDisplayId(); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << (uint32) pet->GetHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << (uint32) pet->GetMaxHealth(); else *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << (uint8) pet->getPowerType(); else *data << (uint8) 0; } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << (uint16) pet->GetPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << (uint16) pet->GetMaxPower(pet->getPowerType()); else *data << (uint16) 0; } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) { if (Vehicle* veh = player->GetVehicle()) *data << (uint32) veh->GetVehicleInfo()->m_seatID[player->m_movementInfo.t_seat]; } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { uint64 auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { AuraApplication const* aurApp = player->GetVisibleAura(i); *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } } else *data << (uint64) 0; } }
void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SIGN"); // ok Field* fields; uint64 petitionGuid; uint8 unk; recvData >> petitionGuid; // petition guid recvData >> unk; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); stmt->setUInt32(1, GUID_LOPART(petitionGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { TC_LOG_ERROR("network", "Petition %u is not found for player %u %s", GUID_LOPART(petitionGuid), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); return; } fields = result->Fetch(); uint64 ownerGuid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); uint64 signs = fields[1].GetUInt64(); uint8 type = fields[2].GetUInt8(); uint32 playerGuid = _player->GetGUIDLow(); if (GUID_LOPART(ownerGuid) == playerGuid) return; // not let enemies sign guild charter if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(ownerGuid)) { if (type != GUILD_CHARTER_TYPE) SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); else Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED); return; } if (type != GUILD_CHARTER_TYPE) { if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName().c_str(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); return; } uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; if (_player->GetArenaTeamId(slot)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if (_player->GetArenaTeamIdInvited()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } } else { if (_player->GetGuildId()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, _player->GetName()); return; } if (_player->GetGuildIdInvited()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName()); return; } } if (++signs > type) // client signs maximum return; // Client doesn't allow to sign petition two times by one character, but not check sign by another character from same account // not allow sign another player from already sign player account stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_ACCOUNT); stmt->setUInt32(0, GetAccountId()); stmt->setUInt32(1, GUID_LOPART(petitionGuid)); result = CharacterDatabase.Query(stmt); if (result) { WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); data << uint64(_player->GetGUID()); data << (uint32)PETITION_SIGN_ALREADY_SIGNED; // close at signer side SendPacket(&data); // update for owner if online if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); return; } stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); stmt->setUInt32(0, GUID_LOPART(ownerGuid)); stmt->setUInt32(1, GUID_LOPART(petitionGuid)); stmt->setUInt32(2, playerGuid); stmt->setUInt32(3, GetAccountId()); CharacterDatabase.Execute(stmt); TC_LOG_DEBUG("network", "PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionGuid), _player->GetName().c_str(), playerGuid, GetAccountId()); WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); data << uint64(_player->GetGUID()); data << uint32(PETITION_SIGN_OK); // close at signer side SendPacket(&data); // update signs count on charter, required testing... //Item* item = _player->GetItemByGuid(petitionguid)); //if (item) // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); // update for owner if online if (Player* owner = ObjectAccessor::FindPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket &recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_PARTY_MEMBER_STATS"); uint64 Guid; recv_data >> Guid; Player* player = HashMapHolder<Player>::Find(Guid); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << (uint32) GROUP_UPDATE_FLAG_STATUS; data << (uint16) MEMBER_STATUS_OFFLINE; SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF if (pet) mask1 = 0x7FFFFFFF; // for hunters and other classes with pets Powers powerType = player->getPowerType(); data << (uint32) mask1; // group update mask data << (uint16) MEMBER_STATUS_ONLINE; // member's online status data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER data << (uint16) player->getLevel(); // GROUP_UPDATE_FLAG_LEVEL data << (uint16) player->GetZoneId(); // GROUP_UPDATE_FLAG_ZONE data << (uint16) player->GetPositionX(); // GROUP_UPDATE_FLAG_POSITION data << (uint16) player->GetPositionY(); // GROUP_UPDATE_FLAG_POSITION uint64 auramask = 0; size_t maskPos = data.wpos(); data << (uint64) auramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication * aurApp = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << (uint32) aurApp->GetBase()->GetId(); data << (uint8) 1; } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->getPowerType(); data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << (uint64) petauramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { if (AuraApplication * auraApp = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << (uint32) auraApp->GetBase()->GetId(); data << (uint8) 1; } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << (uint8) 0; // GROUP_UPDATE_FLAG_PET_NAME data << (uint64) 0; // GROUP_UPDATE_FLAG_PET_AURAS } SendPacket(&data); }
void WorldSession::HandleOfferPetitionOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_OFFER_PETITION"); // ok uint8 signs = 0; uint64 petitionguid, plguid; uint32 type, junk; Player* player; recvData >> junk; // this is not petition type! recvData >> petitionguid; // petition guid recvData >> plguid; // player guid player = ObjectAccessor::FindPlayer(plguid); if (!player) return; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); stmt->setUInt32(0, GUID_LOPART(petitionguid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return; Field* fields = result->Fetch(); type = fields[0].GetUInt8(); TC_LOG_DEBUG("network", "OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam()) { if (type != GUILD_CHARTER_TYPE) SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); else Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED); return; } if (type != GUILD_CHARTER_TYPE) { if (player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { // player is too low level to join an arena team SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName().c_str(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S); return; } uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; if (player->GetArenaTeamId(slot)) { // player is already in an arena team SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName().c_str(), "", ERR_ALREADY_IN_ARENA_TEAM_S); return; } if (player->GetArenaTeamIdInvited()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } } else { if (player->GetGuildId()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, _player->GetName()); return; } if (player->GetGuildIdInvited()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName()); return; } } stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); stmt->setUInt32(0, GUID_LOPART(petitionguid)); result = CharacterDatabase.Query(stmt); // result == NULL also correct charter without signs if (result) signs = uint8(result->GetRowCount()); WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12)); data << uint64(petitionguid); // petition guid data << uint64(_player->GetGUID()); // owner guid data << uint32(GUID_LOPART(petitionguid)); // guild guid data << uint8(signs); // sign's count for (uint8 i = 1; i <= signs; ++i) { Field* fields2 = result->Fetch(); data << uint64(MAKE_NEW_GUID(fields2[0].GetUInt32(), 0, HIGHGUID_PLAYER)); // Player GUID data << uint32(0); // there 0 ... result->NextRow(); } player->GetSession()->SendPacket(&data); }
void InstanceScript::LoadMinionData(const MinionData* data) { while (data->entry) { if (data->bossId < bosses.size()) minions.insert(std::make_pair(data->entry, MinionInfo(&bosses[data->bossId]))); ++data; } sLog->outDebug(LOG_FILTER_TSCR, "InstanceScript::LoadMinionData: " UI64FMTD " minions loaded.", uint64(minions.size())); }
void WorldSession::CharacterEnumProc(QueryResult* result) { struct player_item { uint32 displayid; uint8 invtype; uint32 enchantment; // added in 2.4 }; uint32 start_time = getMSTime(); player_item items[23]; int8 slot; uint32 i; ItemPrototype* proto; QueryResult* res; CreatureInfo* info = NULL; uint8 race; has_dk = false; _side = -1; // side should be set on every enumeration for safety uint32 numchar; if(result) numchar = result->GetRowCount(); else numchar = 0; // should be more than enough.. 200 bytes per char.. WorldPacket data(SMSG_CHAR_ENUM, 1 + numchar * 200); // parse m_characters and build a mighty packet of // characters to send to the client. data << uint8(numchar); if(result) { uint64 guid; uint8 Class; uint32 bytes2; uint32 flags; uint32 banned; Field* fields; uint32 petLevel = 0; do { fields = result->Fetch(); guid = fields[0].GetUInt64(); bytes2 = fields[6].GetUInt32(); Class = fields[3].GetUInt8(); flags = fields[17].GetUInt32(); race = fields[2].GetUInt8(); if(_side < 0) { // work out the side static uint8 sides[RACE_DRAENEI + 1] = {0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0}; _side = sides[race]; } // Death Knight starting information // Note: To change what level is required to make a dk change the >= 55 to something. // For example >=80 would require a level 80 to create a DK has_level_55_char = has_level_55_char || (fields[1].GetUInt8() >= 55); has_dk = has_dk || (Class == 6); /* build character enum, w0000t :p */ data << uint64(guid); //guid data << fields[7].GetString(); //name data << uint8(race); //race data << uint8(Class); //class data << uint8(fields[4].GetUInt8()); //gender data << uint32(fields[5].GetUInt32()); //PLAYER_BYTES data << uint8(bytes2 & 0xFF); //facial hair data << uint8(fields[1].GetUInt8()); //Level data << uint32(fields[12].GetUInt32()); //zoneid data << uint32(fields[11].GetUInt32()); //Mapid data << float(fields[8].GetFloat()); //X data << float(fields[9].GetFloat()); //Y data << float(fields[10].GetFloat()); //Z data << uint32(fields[18].GetUInt32()); //GuildID banned = fields[13].GetUInt32(); uint32 char_flags = 0; if(banned && (banned < 10 || banned > (uint32)UNIXTIME)) char_flags |= 0x01000000; //Character is banned if(fields[15].GetUInt32() != 0) char_flags |= 0x00002000; //Character is dead if(flags & PLAYER_FLAG_NOHELM) char_flags |= 0x00000400; //Helm not displayed if(flags & PLAYER_FLAG_NOCLOAK) char_flags |= 0x00000800; //Cloak not displayed if(fields[16].GetUInt32() != 0) char_flags |= 0x00004000; //Character has to be renamed before logging in data << uint32(char_flags); data << uint32(0); //Character recustomization flags data << uint8(0); //Unknown 3.2.0 if(Class == WARLOCK || Class == HUNTER) { res = CharacterDatabase.Query("SELECT entry, level FROM playerpets WHERE ownerguid = %u AND MOD( active, 10 ) = 1 AND alive = TRUE;", Arcemu::Util::GUID_LOPART(guid)); if(res) { petLevel = res->Fetch()[1].GetUInt32(); info = CreatureNameStorage.LookupEntry(res->Fetch()[0].GetUInt32()); delete res; } else info = NULL; } else info = NULL; if(info) { data << uint32(info->Male_DisplayID); data << uint32(petLevel); data << uint32(info->Family); } else { data << uint32(0); data << uint32(0); data << uint32(0); } res = CharacterDatabase.Query("SELECT slot, entry, enchantments FROM playeritems WHERE ownerguid=%u AND containerslot = '-1' AND slot BETWEEN '0' AND '22'", Arcemu::Util::GUID_LOPART(guid)); memset(items, 0, sizeof(player_item) * 23); uint32 enchantid; EnchantEntry* enc; if(res) { do { slot = res->Fetch()[0].GetInt8(); proto = ItemPrototypeStorage.LookupEntry(res->Fetch()[1].GetUInt32()); if(proto) { items[slot].displayid = proto->DisplayInfoID; items[slot].invtype = static_cast<uint8>(proto->InventoryType); // weapon glows if(slot == EQUIPMENT_SLOT_MAINHAND || slot == EQUIPMENT_SLOT_OFFHAND) { // get enchant visual ID const char* enchant_field = res->Fetch()[2].GetString(); if(sscanf(enchant_field , "%u,0,0;" , (unsigned int*)&enchantid) == 1 && enchantid > 0) { enc = dbcEnchant.LookupEntryForced(enchantid); if(enc != NULL) items[slot].enchantment = enc->visual; } } } } while(res->NextRow()); delete res; } for(i = 0; i < INVENTORY_SLOT_BAG_END; ++i) { data << uint32(items[i].displayid); data << uint8(items[i].invtype); data << uint32(items[i].enchantment); } } while(result->NextRow()); } Log.Debug("Character Enum", "Built in %u ms.", getMSTime() - start_time); SendPacket(&data); }
//Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored) void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit* speaker) { uint32 messageLength = (message ? strlen(message) : 0) + 1; data->Initialize(SMSG_MESSAGECHAT, 100); // guess size *data << uint8(type); if ((type != CHAT_MSG_CHANNEL && type != CHAT_MSG_WHISPER) || language == LANG_ADDON) *data << uint32(language); else *data << uint32(LANG_UNIVERSAL); switch (type) { case CHAT_MSG_SAY: case CHAT_MSG_PARTY: case CHAT_MSG_PARTY_LEADER: case CHAT_MSG_RAID: case CHAT_MSG_GUILD: case CHAT_MSG_OFFICER: case CHAT_MSG_YELL: case CHAT_MSG_WHISPER: case CHAT_MSG_CHANNEL: case CHAT_MSG_RAID_LEADER: case CHAT_MSG_RAID_WARNING: case CHAT_MSG_BG_SYSTEM_NEUTRAL: case CHAT_MSG_BG_SYSTEM_ALLIANCE: case CHAT_MSG_BG_SYSTEM_HORDE: case CHAT_MSG_BATTLEGROUND: case CHAT_MSG_BATTLEGROUND_LEADER: target_guid = session ? session->GetPlayer()->GetGUID() : 0; break; case CHAT_MSG_MONSTER_SAY: case CHAT_MSG_MONSTER_PARTY: case CHAT_MSG_MONSTER_YELL: case CHAT_MSG_MONSTER_WHISPER: case CHAT_MSG_MONSTER_EMOTE: case CHAT_MSG_RAID_BOSS_WHISPER: case CHAT_MSG_RAID_BOSS_EMOTE: case CHAT_MSG_BATTLENET: { *data << uint64(speaker->GetGUID()); *data << uint32(0); // 2.1.0 *data << uint32(strlen(speaker->GetName()) + 1); *data << speaker->GetName(); uint64 listener_guid = 0; *data << uint64(listener_guid); if (listener_guid && !IS_PLAYER_GUID(listener_guid)) { *data << uint32(1); // string listener_name_length *data << uint8(0); // string listener_name } *data << uint32(messageLength); *data << message; *data << uint8(0); return; } default: if (type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_IGNORED && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) target_guid = 0; // only for CHAT_MSG_WHISPER_INFORM used original value target_guid break; } *data << uint64(target_guid); // there 0 for BG messages *data << uint32(0); // can be chat msg group or something if (type == CHAT_MSG_CHANNEL) { ASSERT(channelName); *data << channelName; } *data << uint64(target_guid); *data << uint32(messageLength); *data << message; if (session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK) *data << uint8(session->GetPlayer()->GetChatTag()); else *data << uint8(0); }
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(); if (receiver.GetPlayerGUIDLow() == auctionbot.GetAHBplayerGUID()) { if (sender.GetMailMessageType() == MAIL_AUCTION) // auction mail with items deleteIncludedItems(trans, true); return; } 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 PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, uint64 npcGUID, bool enableNext) const { std::string questTitle = quest->GetTitle(); std::string questOfferRewardText = quest->GetOfferRewardText(); int32 locale = _session->GetSessionDbLocaleIndex(); if (locale >= 0) { if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(quest->GetQuestId())) { ObjectMgr::GetLocaleString(localeData->Title, locale, questTitle); ObjectMgr::GetLocaleString(localeData->OfferRewardText, locale, questOfferRewardText); } } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) AddQuestLevelToTitle(questTitle, quest->GetQuestLevel()); WorldPacket data(SMSG_QUESTGIVER_OFFER_REWARD, 50); // guess size data << uint64(npcGUID); data << uint32(quest->GetQuestId()); data << questTitle; data << questOfferRewardText; data << uint8(enableNext ? 1 : 0); // Auto Finish data << uint32(quest->GetFlags()); // 3.3.3 questFlags data << uint32(quest->GetSuggestedPlayers()); // SuggestedGroupNum uint32 emoteCount = 0; for (uint8 i = 0; i < QUEST_EMOTE_COUNT; ++i) { if (quest->OfferRewardEmote[i] <= 0) break; ++emoteCount; } data << emoteCount; // Emote Count for (uint8 i = 0; i < emoteCount; ++i) { data << uint32(quest->OfferRewardEmoteDelay[i]); // Delay Emote data << uint32(quest->OfferRewardEmote[i]); } data << uint32(quest->GetRewChoiceItemsCount()); for (uint32 i=0; i < quest->GetRewChoiceItemsCount(); ++i) { data << uint32(quest->RewardChoiceItemId[i]); data << uint32(quest->RewardChoiceItemCount[i]); if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[i])) data << uint32(itemTemplate->DisplayInfoID); else data << uint32(0); } data << uint32(quest->GetRewItemsCount()); for (uint32 i = 0; i < quest->GetRewItemsCount(); ++i) { data << uint32(quest->RewardItemId[i]); data << uint32(quest->RewardItemIdCount[i]); if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RewardItemId[i])) data << uint32(itemTemplate->DisplayInfoID); else data << uint32(0); } data << uint32(quest->GetRewOrReqMoney()); data << uint32(quest->XPValue(_session->GetPlayer()) * sWorld->getRate(RATE_XP_QUEST)); // rewarded honor points. Multiply with 10 to satisfy client data << uint32(10 * quest->CalculateHonorGain(_session->GetPlayer()->GetQuestLevel(quest))); data << float(0.0f); // unk, honor multiplier? data << uint32(0x08); // unused by client? data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0) data << int32(quest->GetRewSpellCast()); // cast spell data << uint32(0); // unknown data << uint32(quest->GetBonusTalents()); // bonus talents data << uint32(quest->GetRewArenaPoints()); // arena points data << uint32(0); for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids data << uint32(quest->RewardFactionId[i]); for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid in QuestFactionReward.dbc (zero based)? data << int32(quest->RewardFactionValueId[i]); for (uint32 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward reputation override? data << uint32(quest->RewardFactionValueIdOverride[i]); _session->SendPacket(&data); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), quest->GetQuestId()); }
/** * @fn void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData) * * @brief Send by client on clicking in accept or refuse of invitation windows for join game. */ void WorldSession::HandleBfEntryInviteResponse(WorldPacket& recvData) { uint8 accepted; ObjectGuid guid; guid[6] = recvData.ReadBit(); guid[1] = recvData.ReadBit(); accepted = recvData.ReadBit(); guid[5] = recvData.ReadBit(); guid[3] = recvData.ReadBit(); guid[2] = recvData.ReadBit(); guid[0] = recvData.ReadBit(); guid[7] = recvData.ReadBit(); guid[4] = recvData.ReadBit(); recvData.ReadByteSeq(guid[0]); recvData.ReadByteSeq(guid[3]); recvData.ReadByteSeq(guid[4]); recvData.ReadByteSeq(guid[2]); recvData.ReadByteSeq(guid[1]); recvData.ReadByteSeq(guid[6]); recvData.ReadByteSeq(guid[7]); recvData.ReadByteSeq(guid[5]); TC_LOG_ERROR("misc", "HandleBattlefieldInviteResponse: GUID: " UI64FMTD ", accepted: %u", uint64(guid), accepted); Battlefield* bf = sBattlefieldMgr->GetBattlefieldByGUID(guid); if (!bf) return; // If player accept invitation if (accepted) { bf->PlayerAcceptInviteToWar(_player); } else { if (_player->GetZoneId() == bf->GetZoneId()) bf->KickPlayerFromBattlefield(_player->GetGUID()); } }
void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_TRANSFER"); Player* player = GetPlayer(); // Read everything ObjectGuid npcGuid; npcGuid[1] = recvData.ReadBit(); uint32 countDeposit = recvData.ReadBits(26); if (countDeposit > 9) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countDeposit); return; } std::vector<ObjectGuid> itemGuids(countDeposit); for (uint32 i = 0; i < countDeposit; ++i) { itemGuids[i][4] = recvData.ReadBit(); itemGuids[i][6] = recvData.ReadBit(); itemGuids[i][7] = recvData.ReadBit(); itemGuids[i][0] = recvData.ReadBit(); itemGuids[i][1] = recvData.ReadBit(); itemGuids[i][5] = recvData.ReadBit(); itemGuids[i][3] = recvData.ReadBit(); itemGuids[i][2] = recvData.ReadBit(); } npcGuid[2] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); uint32 countWithdraw = recvData.ReadBits(26); if (countWithdraw > 9) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countWithdraw); return; } std::vector<ObjectGuid> itemIds(countWithdraw); for (uint32 i = 0; i < countWithdraw; ++i) { itemIds[i][4] = recvData.ReadBit(); itemIds[i][7] = recvData.ReadBit(); itemIds[i][1] = recvData.ReadBit(); itemIds[i][0] = recvData.ReadBit(); itemIds[i][2] = recvData.ReadBit(); itemIds[i][3] = recvData.ReadBit(); itemIds[i][5] = recvData.ReadBit(); itemIds[i][6] = recvData.ReadBit(); } npcGuid[7] = recvData.ReadBit(); recvData.FlushBits(); for (uint32 i = 0; i < countDeposit; ++i) { recvData.ReadByteSeq(itemGuids[i][6]); recvData.ReadByteSeq(itemGuids[i][1]); recvData.ReadByteSeq(itemGuids[i][0]); recvData.ReadByteSeq(itemGuids[i][2]); recvData.ReadByteSeq(itemGuids[i][4]); recvData.ReadByteSeq(itemGuids[i][5]); recvData.ReadByteSeq(itemGuids[i][3]); recvData.ReadByteSeq(itemGuids[i][7]); } recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[6]); for (uint32 i = 0; i < countWithdraw; ++i) { recvData.ReadByteSeq(itemIds[i][3]); recvData.ReadByteSeq(itemIds[i][1]); recvData.ReadByteSeq(itemIds[i][0]); recvData.ReadByteSeq(itemIds[i][6]); recvData.ReadByteSeq(itemIds[i][2]); recvData.ReadByteSeq(itemIds[i][7]); recvData.ReadByteSeq(itemIds[i][5]); recvData.ReadByteSeq(itemIds[i][4]); } recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[0]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (itemIds.size() != 0) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (itemIds.size() > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT]; uint8 depositCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr) { Item* item = player->GetItemByGuid(*itr); if (!item) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor()); uint8 slot = player->AddVoidStorageItem(itemVS); depositItems[depositCount++] = std::make_pair(itemVS, slot); player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM; player->ModifyMoney(-cost); VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW]; uint8 withdrawCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr) { uint8 slot; VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot); if (!itemVS) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); return; } Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId); item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid)); item->SetBinding(true); player->SendNewItem(item, 1, false, false, false); withdrawItems[withdrawCount++] = *itemVS; player->DeleteVoidStorageItem(slot); } WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount + 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount); data.WriteBits(depositCount, 5); data.WriteBits(withdrawCount, 5); for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data.WriteBit(creatorGuid[7]); data.WriteBit(itemId[7]); data.WriteBit(itemId[4]); data.WriteBit(creatorGuid[6]); data.WriteBit(creatorGuid[5]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(creatorGuid[4]); data.WriteBit(creatorGuid[2]); data.WriteBit(creatorGuid[0]); data.WriteBit(creatorGuid[3]); data.WriteBit(creatorGuid[1]); data.WriteBit(itemId[2]); data.WriteBit(itemId[0]); data.WriteBit(itemId[1]); data.WriteBit(itemId[6]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteBit(itemId[1]); data.WriteBit(itemId[7]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(itemId[6]); data.WriteBit(itemId[2]); data.WriteBit(itemId[4]); data.WriteBit(itemId[0]); } data.FlushBits(); for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[7]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); } for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data << uint32(depositItems[i].first.ItemSuffixFactor); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(creatorGuid[4]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(creatorGuid[1]); data.WriteByteSeq(creatorGuid[3]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(creatorGuid[0]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(creatorGuid[6]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(creatorGuid[5]); data.WriteByteSeq(creatorGuid[7]); data << uint32(depositItems[i].first.ItemEntry); data.WriteByteSeq(itemId[1]); data << uint32(depositItems[i].second); // slot data.WriteByteSeq(creatorGuid[2]); data.WriteByteSeq(itemId[7]); data << uint32(depositItems[i].first.ItemRandomPropertyId); } SendPacket(&data); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }
void WorldSession::HandleCharCustomize(WorldPacket& recv_data) { uint64 guid; std::string newname; recv_data >> guid; recv_data >> newname; uint8 gender, skin, face, hairStyle, hairColor, facialHair; recv_data >> gender >> skin >> hairColor >> hairStyle >> facialHair >> face; QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); if (!result) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } Field *fields = result->Fetch(); uint32 at_loginFlags = fields[0].GetUInt32(); delete result; if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } // prevent character rename to invalid name if (!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_NO_NAME); SendPacket( &data ); return; } uint8 res = ObjectMgr::CheckPlayerName(newname,true); if (res != CHAR_NAME_SUCCESS) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(res); SendPacket( &data ); return; } // check name limitations if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_NAME_RESERVED); SendPacket( &data ); return; } // character with this name already exist if (uint64 newguid = objmgr.GetPlayerGUIDByName(newname)) { if (newguid != guid) { WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket( &data ); return; } } CharacterDatabase.escape_string(newname); Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str()); WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); data << uint8(RESPONSE_SUCCESS); data << uint64(guid); data << newname; data << uint8(gender); data << uint8(skin); data << uint8(face); data << uint8(hairStyle); data << uint8(hairColor); data << uint8(facialHair); SendPacket(&data); }
/** * Handles the packet sent by the client when requesting the current mail list. * It will send a list of all available mails in the players mailbox to the client. */ void WorldSession::HandleGetMailList(WorldPacket & recv_data ) { uint64 mailbox; recv_data >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mailsCount = 0; // send to client mails amount uint32 realCount = 0; // real mails amount WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size data << uint32(0); // real mail's count data << uint8(0); // mail's count time_t cur_time = time(NULL); for(PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr) { // packet send mail count as uint8, prevent overflow if(mailsCount >= 254) { realCount += 1; continue; } // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+((*itr)->body.size()+1)+1+item_count*(1+4+4+7*3*4+4+4+4+4+4+4+1); if(data.wpos()+next_mail_size > maxPacketSize) { realCount += 1; continue; } data << uint16(next_mail_size); // Message size data << uint32((*itr)->messageID); // Message ID data << uint8((*itr)->messageType); // Message Type switch((*itr)->messageType) { case MAIL_NORMAL: // sender guid data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << uint32((*itr)->sender); // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI data << uint32(0); // item entry break; } data << uint32((*itr)->COD); // COD data << uint32(0); // unknown, probably changed in 3.3.3 data << uint32((*itr)->stationery); // stationery (Stationery.dbc) data << uint32((*itr)->money); // copper data << uint32((*itr)->checked); // flags data << float(((*itr)->expire_time-time(NULL))/DAY);// Time data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3, max 256 data << (*itr)->body; // message? max 8000 data << uint8(item_count); // client limit is 0x10 for(uint8 i = 0; i < item_count; ++i) { Item *item = _player->GetMItem((*itr)->items[i].item_guid); // item index (0-6?) data << uint8(i); // item guid low? data << uint32(item ? item->GetGUIDLow() : 0); // entry data << uint32(item ? item->GetEntry() : 0); for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { // unsure data << uint32(item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); // unsure data << uint32(item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0); // unsure data << uint32(item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0); } // can be negative data << uint32(item ? item->GetItemRandomPropertyId() : 0); // unk data << uint32(item ? item->GetItemSuffixFactor() : 0); // stack count data << uint32(item ? item->GetCount() : 0); // charges data << uint32(item ? item->GetSpellCharges() : 0); // durability data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); // durability data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); // unknown wotlk data << uint8(0); } mailsCount += 1; realCount += 1; } data.put<uint32>(0, realCount); // this will display warning about undelivered mail to player if realCount > mailsCount data.put<uint8>(4, mailsCount); // set real send mails to client SendPacket(&data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; // not accept declined names for unsupported languages std::string name; if(!objmgr.GetPlayerNameByGUID(guid, name)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::wstring wname; if(!Utf8toWStr(name, wname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } if(!isCyrillicCharacter(wname[0])) // name already stored as only single alphabet using { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } std::string name2; DeclinedName declinedname; recv_data >> name2; if(name2 != name) // character have different name { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; if(!normalizePlayerName(declinedname.name[i])) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } } if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname, 0), declinedname)) { WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(1); data << uint64(guid); SendPacket(&data); return; } for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); CharacterDatabase.CommitTransaction(); WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(0); // OK data << uint64(guid); SendPacket(&data); }
//called when player lists his received mails void WorldSession::HandleGetMail(WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); uint64 mailbox; recv_data >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* pl = _player; //load players mails, and mailed items if(!pl->m_mailsLoaded) pl ->_LoadMail(); // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mails_count = 0; // real send to client mails amount WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size data << uint8(0); // mail's count time_t cur_time = time(NULL); for(PlayerMails::iterator itr = pl->GetmailBegin(); itr != pl->GetmailEnd(); ++itr) { // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) size_t next_mail_size = 2+4+1+8+4*8+((*itr)->subject.size()+1)+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4); if(data.wpos()+next_mail_size > maxPacketSize) break; data << (uint16) 0x0040; // unknown 2.3.0, different values data << (uint32) (*itr)->messageID; // Message ID data << (uint8) (*itr)->messageType; // Message Type switch((*itr)->messageType) { case MAIL_NORMAL: // sender guid data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << (uint32) (*itr)->sender; // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI break; } data << (uint32) (*itr)->COD; // COD data << (uint32) (*itr)->itemTextId; // sure about this data << (uint32) 0; // unknown data << (uint32) (*itr)->stationery; // stationery (Stationery.dbc) data << (uint32) (*itr)->money; // Gold data << (uint32) 0x04; // unknown, 0x4 - auction, 0x10 - normal // Time data << (float) ((*itr)->expire_time-time(NULL))/DAY; data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3 data << (uint8) item_count; // client limit is 0x10 for(uint8 i = 0; i < item_count; ++i) { Item *item = pl->GetMItem((*itr)->items[i].item_guid); // item index (0-6?) data << (uint8) i; // item guid low? data << (uint32) (item ? item->GetGUIDLow() : 0); // entry data << (uint32) (item ? item->GetEntry() : 0); for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { // unsure data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); // unsure data << (uint32) (item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0); // unsure data << (uint32) (item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0); } // can be negative data << (uint32) (item ? item->GetItemRandomPropertyId() : 0); // unk data << (uint32) (item ? item->GetItemSuffixFactor() : 0); // stack count data << (uint32) (item ? item->GetCount() : 0); // charges data << (uint32) (item ? item->GetSpellCharges() : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); // unknown wotlk data << (uint8) 0; } mails_count += 1; } data.put<uint8>(0, mails_count); // set real send mails to client SendPacket(&data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
/// Logon Challenge command handler bool AuthSocket::_HandleLogonChallenge() { DEBUG_LOG("Entering _HandleLogonChallenge"); if (recv_len() < sizeof(sAuthLogonChallenge_C)) return false; ///- Read the first 4 bytes (header) to get the length of the remaining of the packet std::vector<uint8> buf; buf.resize(4); recv((char*)&buf[0], 4); EndianConvert(*((uint16*)(buf[0]))); uint16 remaining = ((sAuthLogonChallenge_C*)&buf[0])->size; DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining); if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining)) return false; //No big fear of memory outage (size is int16, i.e. < 65536) buf.resize(remaining + buf.size() + 1); buf[buf.size() - 1] = 0; sAuthLogonChallenge_C* ch = (sAuthLogonChallenge_C*)&buf[0]; ///- Read the remaining of the packet recv((char*)&buf[4], remaining); DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size); DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I); // BigEndian code, nop in little endian case // size already converted EndianConvert(*((uint32*)(&ch->gamename[0]))); EndianConvert(ch->build); EndianConvert(*((uint32*)(&ch->platform[0]))); EndianConvert(*((uint32*)(&ch->os[0]))); EndianConvert(*((uint32*)(&ch->country[0]))); EndianConvert(ch->timezone_bias); EndianConvert(ch->ip); ByteBuffer pkt; _login = (const char*)ch->I; _build = ch->build; ///- Normalize account name //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form //Escape the user login to avoid further SQL injection //Memory will be freed on AuthSocket object destruction _safelogin = _login; LoginDatabase.escape_string(_safelogin); pkt << (uint8) CMD_AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) std::string address = get_remote_address(); LoginDatabase.escape_string(address); QueryResult* result = LoginDatabase.PQuery("SELECT unbandate FROM ip_banned WHERE " // permanent still banned "(unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", address.c_str()); if (result) { pkt << (uint8)WOW_FAIL_BANNED; BASIC_LOG("[AuthChallenge] Banned ip %s tries to login!", get_remote_address().c_str()); delete result; } else { ///- Get the account details from the account table // No SQL injection (escaped user name) result = LoginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '******'",_safelogin.c_str()); if (result) { ///- If the IP is 'locked', check that the player comes indeed from the correct IP address bool locked = false; if ((*result)[2].GetUInt8() == 1) // if ip is locked { DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); DEBUG_LOG("[AuthChallenge] Player address is '%s'", get_remote_address().c_str()); if (strcmp((*result)[3].GetString(),get_remote_address().c_str())) { DEBUG_LOG("[AuthChallenge] Account IP differs"); pkt << (uint8) WOW_FAIL_SUSPENDED; locked=true; } else { DEBUG_LOG("[AuthChallenge] Account IP matches"); } } else { DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); } if (!locked) { ///- If the account is banned, reject the logon attempt QueryResult* banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE " "id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)", (*result)[1].GetUInt32()); if (banresult) { if ((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) { pkt << (uint8) WOW_FAIL_BANNED; BASIC_LOG("[AuthChallenge] Banned account %s tries to login!",_login.c_str()); } else { pkt << (uint8) WOW_FAIL_SUSPENDED; BASIC_LOG("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str()); } delete banresult; } else { ///- Get the password from the account table, upper it, and make the SRP6 calculation std::string rI = (*result)[0].GetCppString(); ///- Don't calculate (v, s) if there are already some in the database std::string databaseV = (*result)[5].GetCppString(); std::string databaseS = (*result)[6].GetCppString(); DEBUG_LOG("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str()); // multiply with 2, bytes are stored as hexstring if (databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2) _SetVSFields(rI); else { s.SetHexStr(databaseS.c_str()); v.SetHexStr(databaseV.c_str()); } b.SetRand(19 * 8); BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; MANGOS_ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; unk3.SetRand(16 * 8); ///- Fill the response packet with the result pkt << uint8(WOW_SUCCESS); // B may be calculated < 32B so we force minimal length to 32B pkt.append(B.AsByteArray(32), 32); // 32 bytes pkt << uint8(1); pkt.append(g.AsByteArray(), 1); pkt << uint8(32); pkt.append(N.AsByteArray(32), 32); pkt.append(s.AsByteArray(), s.GetNumBytes());// 32 bytes pkt.append(unk3.AsByteArray(16), 16); uint8 securityFlags = 0; pkt << uint8(securityFlags); // security flags (0x0...0x04) if (securityFlags & 0x01) // PIN input { pkt << uint32(0); pkt << uint64(0) << uint64(0); // 16 bytes hash? } if (securityFlags & 0x02) // Matrix input { pkt << uint8(0); pkt << uint8(0); pkt << uint8(0); pkt << uint8(0); pkt << uint64(0); } if (securityFlags & 0x04) // Security token input { pkt << uint8(1); } uint8 secLevel = (*result)[4].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _localizationName.resize(4); for (int i = 0; i < 4; ++i) _localizationName[i] = ch->country[4-i-1]; BASIC_LOG("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str(), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName)); } } delete result; } else // no account { pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT; } } send((char const*)pkt.contents(), pkt.size()); return true; }