void WorldSession::SendNotification(uint32 string_id, ...) { char const* format = GetStarGateString(string_id); if (format) { va_list ap; char szStr[1024]; szStr[0] = '\0'; va_start(ap, string_id); vsnprintf(szStr, 1024, format, ap); va_end(ap); WorldPacket data(SMSG_NOTIFICATION, (strlen(szStr) + 1)); data << szStr; SendPacket(&data); } }
//this void causes that auction window is opened void WorldSession::SendAuctionHello(uint64 guid, Creature* unit) { if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_AUCTION_REQ), sWorld->getIntConfig(CONFIG_AUCTION_LEVEL_REQ)); return; } AuctionHouseEntry const* ahEntry = AuctionHouseMgr::GetAuctionHouseEntry(unit->getFaction()); if (!ahEntry) return; WorldPacket data(MSG_AUCTION_HELLO, 12); data << uint64(guid); data << uint32(ahEntry->houseId); data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled SendPacket(&data); }
void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult result) { if (!result) return; Field *fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); std::string name = fields[1].GetString(); uint8 pRace = 0, pGender = 0, pClass = 0; if (name == "") name = GetStarGateString(LANG_NON_EXIST_CHARACTER); else { pRace = fields[2].GetUInt8(); pGender = fields[3].GetUInt8(); pClass = fields[4].GetUInt8(); } // guess size WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+1+10)); data.appendPackGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); data << uint8(0); // added in 3.1 data << name; data << uint8(0); // realm name for cross realm BG usage data << uint8(pRace); // race data << uint8(pGender); // gender data << uint8(pClass); // class // if the first declined name field (5) is empty, the rest must be too if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && fields[5].GetString() != "") { data << uint8(1); // is declined for (int i = 5; i < MAX_DECLINED_NAME_CASES+5; ++i) data << fields[i].GetString(); } else data << uint8(0); // is not declined SendPacket(&data); }
void WorldSession::HandleSendMail(WorldPacket & recv_data) { uint64 mailbox, unk3, money, COD; std::string receiver, subject, body; uint32 unk1, unk2; uint8 unk4; recv_data >> mailbox; recv_data >> receiver; recv_data >> subject; recv_data >> body; recv_data >> unk1; // stationery? recv_data >> unk2; // 0x00000000 uint8 items_count; recv_data >> items_count; // attached items count if (items_count > MAX_MAIL_ITEMS) // client limit { GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS); recv_data.rpos(recv_data.wpos()); // set to end to avoid warnings spam return; } uint64 itemGUIDs[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { recv_data.read_skip<uint8>(); // item slot in mail, not used recv_data >> itemGUIDs[i]; } recv_data >> money >> COD; // money and cod recv_data >> unk3; // const 0 recv_data >> unk4; // const 0 // packet read complete, now do check if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; if (receiver.empty()) return; Player* pl = _player; if (pl->getLevel() < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_MAIL_SENDER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint64 rc = 0; if (normalizePlayerName(receiver)) rc = sObjectMgr->GetPlayerGUIDByName(receiver); if (!rc) { sLog->outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, "UI64FMTD" copper and "UI64FMTD" COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } sLog->outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, "UI64FMTD" copper and "UI64FMTD" COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2); if (pl->GetGUID() == rc) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint64 reqmoney = cost + money; if (!pl->HasEnoughMoney(uint32(reqmoney))) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player *receive = sObjectMgr->GetPlayer(rc); uint32 rc_team = 0; uint8 mails_count = 0; //do not allow to send to one player more than 100 mails uint8 receiveLevel = 0; if (receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); receiveLevel = receive->getLevel(); } else { rc_team = sObjectMgr->GetPlayerTeamByGUID(rc); if (QueryResult result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc))) { Field *fields = result->Fetch(); mails_count = fields[0].GetUInt32(); } if (QueryResult result = CharacterDatabase.PQuery("SELECT level FROM characters WHERE guid = '%u'", GUID_LOPART(rc))) { Field *fields = result->Fetch(); receiveLevel = fields[0].GetUInt8(); } } //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (mails_count > 100) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // test the receiver's Faction... or all items are account bound bool accountBound = items_count ? true : false; for (uint8 i = 0; i < items_count; ++i) { Item* item = pl->GetItemByGuid(itemGUIDs[i]); if (item) { ItemPrototype const* itemProto = item->GetProto(); if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT)) { accountBound = false; break; } } } if (!accountBound && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } if (receiveLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ)); return; } uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(rc); Item* items[MAX_MAIL_ITEMS]; for (uint8 i = 0; i < items_count; ++i) { if (!itemGUIDs[i]) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } Item* item = pl->GetItemByGuid(itemGUIDs[i]); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded(true)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (item->IsBoundAccountWide() && item->IsSoulBound() && pl->GetSession()->GetAccountId() != rc_account) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); return; } if (item->GetProto()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } if (item->IsBag() && !((Bag*)item)->IsEmpty()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_CAN_ONLY_DO_WITH_EMPTY_BAGS); return; } items[i] = item; } pl->SendMailResult(0, MAIL_SEND, MAIL_OK); pl->ModifyMoney(-int32(reqmoney)); pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; MailDraft draft(subject, body); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (items_count > 0 || money > 0) { if (items_count > 0) { for (uint8 i = 0; i < items_count; ++i) { Item* item = items[i]; if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), item->GetProto()->Name1, item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable pl->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); item->DeleteFromInventoryDB(trans); // deletes item from character's inventory item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SET_ITEM_OWNER); stmt->setUInt32(0, GUID_LOPART(rc)); stmt->setUInt32(1, item->GetGUIDLow()); trans->Append(stmt); draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = pl->GetSession()->GetAccountId() != rc_account; } if (money > 0 && GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: "UI64FMTD" to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list draft .AddMoney(money) .AddCOD(COD) .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), MailSender(pl), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); pl->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
void WorldSession::HandleMessagechatOpcode(WorldPacket & recv_data) { uint32 type = 0; uint32 lang; // Les types sont maintenant ger�s par opcode, un opcode par type // Changement en place depuis la 4.0.1 13164 switch(recv_data.GetOpcode()) { case CMSG_MESSAGECHAT_SAY: type = CHAT_MSG_SAY; break; case CMSG_MESSAGECHAT_YELL: type = CHAT_MSG_YELL; break; case CMSG_MESSAGECHAT_CHANNEL: type = CHAT_MSG_CHANNEL; break; case CMSG_MESSAGECHAT_WHISPER: type = CHAT_MSG_WHISPER; break; case CMSG_MESSAGECHAT_GUILD: type = CHAT_MSG_GUILD; break; case CMSG_MESSAGECHAT_OFFICER: type = CHAT_MSG_OFFICER; break; case CMSG_MESSAGECHAT_AFK: type = CHAT_MSG_AFK; break; case CMSG_MESSAGECHAT_DND: type = CHAT_MSG_DND; break; case CMSG_MESSAGECHAT_EMOTE: type = CHAT_MSG_EMOTE; break; case CMSG_MESSAGECHAT_PARTY: type = CHAT_MSG_PARTY; break; case CMSG_MESSAGECHAT_PARTY_LEADER: type = CHAT_MSG_PARTY_LEADER; break; case CMSG_MESSAGECHAT_RAID: type = CHAT_MSG_RAID; break; case CMSG_MESSAGECHAT_RAID_LEADER: type = CHAT_MSG_RAID_LEADER; break; case CMSG_MESSAGECHAT_BATTLEGROUND: type = CHAT_MSG_BATTLEGROUND; break; case CMSG_MESSAGECHAT_BATTLEGROUND_LEADER: type = CHAT_MSG_BATTLEGROUND_LEADER; break; case CMSG_MESSAGECHAT_RAID_WARNING: type = CHAT_MSG_RAID_WARNING; break; default: sLog->outDetail("HandleMessagechatOpcode : Unknown chat opcode (%u)", recv_data.GetOpcode()); recv_data.hexlike(); return; } // no language for AFK and DND messages if (type == CHAT_MSG_AFK) { std::string msg; recv_data >> msg; if ((msg.empty() || !_player->isAFK()) && !_player->isInCombat()) { if (!_player->isAFK()) { if (msg.empty()) msg = GetStarGateString(LANG_PLAYER_AFK_DEFAULT); _player->afkMsg = msg; } sScriptMgr->OnPlayerChat(_player, type, LANG_UNIVERSAL, msg); _player->ToggleAFK(); if (_player->isAFK() && _player->isDND()) _player->ToggleDND(); } return; }
void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recv_data) { // Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable) if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED) return; if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_TICKET_REQ), sWorld->getIntConfig(CONFIG_TICKET_LEVEL_REQ)); return; } if (sTicketMgr->GetGMTicketByPlayer(GetPlayer()->GetGUID())) { WorldPacket data(SMSG_GMTICKET_CREATE, 4); data << uint32(GMTICKET_RESPONSE_FAILURE); // You already have GM ticket SendPacket(&data); return; } uint32 map, unk, unk1, unk2; uint8 needResponse; // ignored float x, y, z; std::string ticketText, ticketText2; SendQueryTimeResponse(); recv_data >> map; recv_data >> x; recv_data >> y; recv_data >> z; recv_data >> ticketText; recv_data >> unk; // not sure what this is... replyTo? recv_data >> needResponse; // always 1/0 -- not sure what retail does with this recv_data >> unk1; recv_data >> unk2; GM_Ticket *ticket = new GM_Ticket; ticket->name = GetPlayer()->GetName(); ticket->guid = sTicketMgr->GenerateGMTicketId(); ticket->playerGuid = GetPlayer()->GetGUID(); ticket->message = ticketText; ticket->createtime = time(NULL); ticket->map = map; ticket->pos_x = x; ticket->pos_y = y; ticket->pos_z = z; ticket->timestamp = time(NULL); ticket->closed = 0; ticket->assignedToGM = 0; ticket->comment = ""; ticket->completed = false; ticket->escalated = TICKET_UNASSIGNED; ticket->response = ""; sTicketMgr->AddOrUpdateGMTicket(*ticket, true); WorldPacket data(SMSG_GMTICKET_CREATE, 4); data << uint32(GMTICKET_RESPONSE_SUCCESS); SendPacket(&data); sWorld->SendGMText(LANG_COMMAND_TICKETNEW, GetPlayer()->GetName(), ticket->guid); }
void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) { if (GetPlayer()->m_trade) return; uint64 ID; if (!GetPlayer()->isAlive()) { SendTradeStatus(TRADE_STATUS_YOU_DEAD); return; } if (GetPlayer()->HasUnitState(UNIT_STAT_STUNNED)) { SendTradeStatus(TRADE_STATUS_YOU_STUNNED); return; } if (isLogingOut()) { SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); return; } if (GetPlayer()->isInFlight()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; } if (GetPlayer()->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_TRADE_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); return; } recvPacket >> ID; Player* pOther = ObjectAccessor::FindPlayer(ID); if (!pOther) { SendTradeStatus(TRADE_STATUS_NO_TARGET); return; } if (pOther == GetPlayer() || pOther->m_trade) { SendTradeStatus(TRADE_STATUS_BUSY); return; } if (!pOther->isAlive()) { SendTradeStatus(TRADE_STATUS_TARGET_DEAD); return; } if (pOther->isInFlight()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; } if (pOther->HasUnitState(UNIT_STAT_STUNNED)) { SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); return; } if (pOther->GetSession()->isLogingOut()) { SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); return; } if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendTradeStatus(TRADE_STATUS_IGNORE_YOU); return; } if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam()) { SendTradeStatus(TRADE_STATUS_WRONG_FACTION); return; } if (!pOther->IsWithinDistInMap(_player, 10.0f, false)) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; } if (pOther->getLevel() < sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)) { SendNotification(GetStarGateString(LANG_TRADE_OTHER_REQ), sWorld->getIntConfig(CONFIG_TRADE_LEVEL_REQ)); return; } // OK start trade _player->m_trade = new TradeData(_player, pOther); pOther->m_trade = new TradeData(pOther, _player); WorldPacket data(SMSG_TRADE_STATUS, 1+8+4+4+4+1+4+4+4); data << uint8(0); data << uint64(_player->GetGUID()); data << uint32(0); data << uint32(TRADE_STATUS_BEGIN_TRADE); data << uint32(0); data << uint8(0); data << uint32(0); data << uint32(0); data << uint32(0); pOther->GetSession()->SendPacket(&data); }