//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSellItem& packet) { if (packet.Items.size() > MAX_AUCTION_ITEMS) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } for (auto const& item : packet.Items) if (!item.Guid || !item.UseCount || item.UseCount > 1000) return; if (!packet.MinBid || !packet.RunTime) return; if (packet.MinBid > MAX_MONEY_AMOUNT || packet.BuyoutPrice > MAX_MONEY_AMOUNT) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player %s (%s) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUID().ToString().c_str()); SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(packet.Auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit (%s) not found or you can't interact with him.", packet.Auctioneer.ToString().c_str()); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); if (!auctionHouseEntry) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit (%s) has wrong faction.", packet.Auctioneer.ToString().c_str()); return; } packet.RunTime *= MINUTE; switch (packet.RunTime) { case 1 * MIN_AUCTION_TIME: case 2 * MIN_AUCTION_TIME: case 4 * MIN_AUCTION_TIME: break; default: return; } if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); uint32 finalCount = 0; for (auto const& packetItem : packet.Items) { Item* item = _player->GetItemByGuid(packetItem.Guid); if (!item) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND); return; } if (sAuctionMgr->GetAItem(item->GetGUID().GetCounter()) || !item->CanBeTraded() || item->IsNotEmptyBag() || item->GetTemplate()->GetFlags() & ITEM_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || item->GetCount() < packetItem.UseCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } finalCount += packetItem.UseCount; } if (packet.Items.empty()) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } if (!finalCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } // check if there are 2 identical guids, in this case user is most likely cheating for (uint32 i = 0; i < packet.Items.size() - 1; ++i) { for (uint32 j = i + 1; j < packet.Items.size(); ++j) { if (packet.Items[i].Guid == packet.Items[j].Guid) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } } } for (auto const& packetItem : packet.Items) { Item* item = _player->GetItemByGuid(packetItem.Guid); if (item->GetMaxStackCount() < finalCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } } Item* item = _player->GetItemByGuid(packet.Items[0].Guid); uint32 auctionTime = uint32(packet.RunTime * sWorld->getRate(RATE_AUCTION_TIME)); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, packet.RunTime, item, finalCount); if (!_player->HasEnoughMoney((uint64)deposit)) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY); return; } AuctionEntry* AH = new AuctionEntry(); if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = UI64LIT(23442); ///@TODO - HARDCODED DB GUID, BAD BAD BAD else AH->auctioneer = packet.Auctioneer.GetCounter(); // Required stack size of auction matches to current item stack size, just move item to auctionhouse if (packet.Items.size() == 1 && item->GetCount() == packet.Items[0].UseCount) { if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); AH->itemGUIDLow = item->GetGUID().GetCounter(); AH->itemEntry = item->GetEntry(); AH->itemCount = item->GetCount(); AH->owner = _player->GetGUID().GetCounter(); AH->startbid = packet.MinBid; AH->bidder = UI64LIT(0); AH->bid = 0; AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling item %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, item->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(item); auctionHouse->AddAuction(AH); _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(trans); item->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size { Item* newItem = item->CloneItem(finalCount, _player); if (!newItem) { TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); delete AH; return; } if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->GetDefaultLocaleName(), newItem->GetEntry(), newItem->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); AH->itemGUIDLow = newItem->GetGUID().GetCounter(); AH->itemEntry = newItem->GetEntry(); AH->itemCount = newItem->GetCount(); AH->owner = _player->GetGUID().GetCounter(); AH->startbid = packet.MinBid; AH->bidder = UI64LIT(0); AH->bid = 0; AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), newItem->GetGUID().ToString().c_str(), newItem->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, newItem->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(newItem); auctionHouse->AddAuction(AH); for (auto const& packetItem : packet.Items) { Item* item2 = _player->GetItemByGuid(packetItem.Guid); // Item stack count equals required count, ready to delete item - cloned item will be used for auction if (item2->GetCount() == packetItem.UseCount) { _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->DeleteFromInventoryDB(trans); item2->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); delete item2; } else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction { item2->SetCount(item2->GetCount() - packetItem.UseCount); item2->SetState(ITEM_CHANGED, _player); _player->ItemRemovedQuestCheck(item2->GetEntry(), packetItem.UseCount); item2->SendUpdateToPlayer(_player); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->SaveToDB(trans); CharacterDatabase.CommitTransaction(trans); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); newItem->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } _player->ModifyMoney(-int32(deposit)); }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); // Get petition guid from packet WorldPacket data; uint64 petitionGuid; recv_data >> petitionGuid; // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionGuid), _player->GetGUIDLow()); // Get petition data from db uint32 ownerguidlo; uint32 type; std::string name; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_PETITION); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { sLog->outError("Player %s (guid: %u) tried to turn in petition (guid: %u) that is not present in the database", _player->GetName(), _player->GetGUIDLow(), GUID_LOPART(petitionGuid)); return; } // Only the petition owner can turn in the petition if (_player->GetGUIDLow() != ownerguidlo) return; // Petition type (guild/arena) specific checks if (type == GUILD_CHARTER_TYPE) { // Check if player is already in a guild if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; _player->GetSession()->SendPacket(&data); return; } // Check if guild name is already taken if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); return; } } else { // Check for valid arena bracket (2v2, 3v3, 5v5) uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; // Check if player is already in an arena team if (_player->GetArenaTeamId(slot)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } // Check if arena team name is already taken if (sArenaTeamMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } } // Get petition signatures from db uint8 signatures; stmt = CharacterDatabase.GetPreparedStatement(CHAR_LOAD_PETITION_SIGNATURE); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); result = CharacterDatabase.Query(stmt); if (result) signatures = uint8(result->GetRowCount()); else signatures = 0; uint32 requiredSignatures; if (type == GUILD_CHARTER_TYPE) requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); else requiredSignatures = type-1; // Notify player if signatures are missing if (signatures < requiredSignatures) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; SendPacket(&data); return; } // Proceed with guild/arena team creation // Delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); if (type == GUILD_CHARTER_TYPE) { // Create guild Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // Register guild and add guild master sGuildMgr->AddGuild(guild); // Add members from signatures for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); guild->AddMember(MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); result->NextRow(); } } else { // Receive the rest of the packet in arena team creation case uint32 background, icon, iconcolor, border, bordercolor; recv_data >> background >> icon >> iconcolor >> border >> bordercolor; // Create arena team ArenaTeam* arenaTeam = new ArenaTeam(); if (!arenaTeam->Create(_player->GetGUID(), type, name, background, icon, iconcolor, border, bordercolor)) { delete arenaTeam; return; } // Register arena team sArenaTeamMgr->AddArenaTeam(arenaTeam); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); // Add members for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); uint32 memberGUID = fields[0].GetUInt32(); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitionsHandler: Adding arena team (guid: %u) member %u", arenaTeam->GetId(), memberGUID); arenaTeam->AddMember(MAKE_NEW_GUID(memberGUID, 0, HIGHGUID_PLAYER)); result->NextRow(); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); CharacterDatabase.CommitTransaction(trans); // created sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionGuid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_OK; SendPacket(&data); }
//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { uint64 auctioneer; uint32 itemsCount, etime, bid, buyout; recv_data >> auctioneer; recv_data >> itemsCount; uint64 itemGUIDs[MAX_AUCTION_ITEMS]; // 160 slot = 4x 36 slot bag + backpack 16 slot uint32 count[MAX_AUCTION_ITEMS]; if (itemsCount > MAX_AUCTION_ITEMS) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } for (uint32 i = 0; i < itemsCount; ++i) { recv_data >> itemGUIDs[i]; recv_data >> count[i]; if (!itemGUIDs[i] || !count[i] || count[i] > 1000 ) return; } recv_data >> bid; recv_data >> buyout; recv_data >> etime; if (!bid || !etime) return; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(auctioneer)); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); if (!auctionHouseEntry) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", GUID_LOPART(auctioneer)); return; } etime *= MINUTE; switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item* items[MAX_AUCTION_ITEMS]; uint32 finalCount = 0; for (uint32 i = 0; i < itemsCount; ++i) { Item* item = _player->GetItemByGuid(itemGUIDs[i]); if (!item) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); return; } if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() || item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_DURATION) || item->GetCount() < count[i]) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } items[i] = item; finalCount += count[i]; } if (!finalCount) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } for (uint32 i = 0; i < itemsCount; ++i) { Item* item = items[i]; if (item->GetMaxStackCount() < finalCount) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } } for (uint32 i = 0; i < itemsCount; ++i) { Item* item = items[i]; uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount); if (!_player->HasEnoughMoney(deposit)) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); return; } _player->ModifyMoney(-int32(deposit)); AuctionEntry* AH = new AuctionEntry; AH->Id = sObjectMgr->GenerateAuctionID(); if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = 23442; else AH->auctioneer = GUID_LOPART(auctioneer); // Required stack size of auction matches to current item stack size, just move item to auctionhouse if (itemsCount == 1 && item->GetCount() == count[i]) { if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); } AH->item_guidlow = item->GetGUIDLow(); AH->item_template = item->GetEntry(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(item); auctionHouse->AddAuction(AH); _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(trans); item->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); return; } else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size { Item* newItem = item->CloneItem(finalCount, _player); if (!newItem) { sLog->outError("CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } if (GetSecurity() > SEC_PLAYER && sWorld->getBoolConfig(CONFIG_GM_LOG_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); } AH->item_guidlow = newItem->GetGUIDLow(); AH->item_template = newItem->GetEntry(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; sLog->outDetail("CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to auctioneer %u with count %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", _player->GetName(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(newItem); auctionHouse->AddAuction(AH); for (uint32 j = 0; j < itemsCount; ++j) { Item* item2 = items[j]; // Item stack count equals required count, ready to delete item - cloned item will be used for auction if (item2->GetCount() == count[j]) { _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->DeleteFromInventoryDB(trans); item2->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); } else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction { item2->SetCount(item2->GetCount() - count[j]); item2->SetState(ITEM_CHANGED, _player); _player->ItemRemovedQuestCheck(item2->GetEntry(), count[j]); item2->SendUpdateToPlayer(_player); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->SaveToDB(trans); CharacterDatabase.CommitTransaction(trans); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); newItem->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); return; } } }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recv_data) { DEBUG_LOG("Received opcode CMSG_TURN_IN_PETITION"); // ok // recv_data.hexlike(); ObjectGuid petitionGuid; recv_data >> petitionGuid; DEBUG_LOG("Petition %s turned in by %s", petitionGuid.GetString().c_str(), _player->GetGuidStr().c_str()); /// Collect petition info data ObjectGuid ownerGuid; uint32 type; std::string name; // data QueryResult* result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", petitionGuid.GetCounter()); if (result) { Field* fields = result->Fetch(); ownerGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); name = fields[1].GetCppString(); type = fields[2].GetUInt32(); delete result; } else { sLog.outError("CMSG_TURN_IN_PETITION: petition table not have data for guid %u!", petitionGuid.GetCounter()); return; } if (type == 9) { if (_player->GetGuildId()) { WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_ALREADY_IN_GUILD); // already in guild _player->GetSession()->SendPacket(&data); return; } } else { if (!IsArenaTypeValid(ArenaType(type))) return; uint8 slot = ArenaTeam::GetSlotByType(ArenaType(type)); if (slot >= MAX_ARENA_SLOT) return; if (_player->GetArenaTeamId(slot)) { // data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); // data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild //_player->GetSession()->SendPacket(&data); SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } } if (_player->GetObjectGuid() != ownerGuid) return; // signs result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionGuid.GetCounter()); uint8 signs = result ? (uint8)result->GetRowCount() : 0; uint32 count = type == 9 ? sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS) : type - 1; if (signs < count) { WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_NEED_MORE_SIGNATURES); // need more signatures... SendPacket(&data); delete result; return; } if (type == 9) { if (sGuildMgr.GetGuildByName(name)) { SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); delete result; return; } } else { if (sObjectMgr.GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); delete result; return; } } // and at last charter item check Item* item = _player->GetItemByGuid(petitionGuid); if (!item) { delete result; return; } // OK! // delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); if (type == 9) // create guild { Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; delete result; return; } // register guild and add guildmaster sGuildMgr.AddGuild(guild); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); ObjectGuid signGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); if (!signGuid) continue; guild->AddMember(signGuid, guild->GetLowestRank()); result->NextRow(); } } else // or arena team { ArenaTeam* at = new ArenaTeam; if (!at->Create(_player->GetObjectGuid(), ArenaType(type), name)) { sLog.outError("PetitionsHandler: arena team create failed."); delete at; delete result; return; } uint32 icon, iconcolor, border, bordercolor, backgroud; recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor; at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor); // register team and add captain sObjectMgr.AddArenaTeam(at); DEBUG_LOG("PetitonsHandler: arena team added to objmrg"); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); ObjectGuid memberGUID = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); if (!memberGUID) continue; DEBUG_LOG("PetitionsHandler: adding arena member %s", memberGUID.GetString().c_str()); at->AddMember(memberGUID); result->NextRow(); } } delete result; CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", petitionGuid.GetCounter()); CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", petitionGuid.GetCounter()); CharacterDatabase.CommitTransaction(); // created DEBUG_LOG("TURN IN PETITION %s", petitionGuid.GetString().c_str()); WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_OK); SendPacket(&data); }
void WorldSession::HandleAutoEquipItemOpcode(WorldPacket & recv_data) { //sLog.outDebug("WORLD: CMSG_AUTOEQUIP_ITEM"); uint8 srcbag, srcslot; recv_data >> srcbag >> srcslot; //sLog.outDebug("STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); Item *pSrcItem = _player->GetItemByPos(srcbag, srcslot); if (!pSrcItem) return; // only at cheat uint16 dest; uint8 msg = _player->CanEquipItem(NULL_SLOT, dest, pSrcItem, !pSrcItem->IsBag()); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, pSrcItem, NULL); return; } uint16 src = pSrcItem->GetPos(); if (dest == src) // prevent equip in same slot, only at cheat return; Item *pDstItem = _player->GetItemByPos(dest); if (!pDstItem) // empty slot, simple case { _player->RemoveItem(srcbag, srcslot, true); _player->EquipItem(dest, pSrcItem, true); _player->AutoUnequipOffhandIfNeed(); } else // have currently equipped item, not simple case { uint8 dstbag = pDstItem->GetBagSlot(); uint8 dstslot = pDstItem->GetSlot(); msg = _player->CanUnequipItem(dest, !pSrcItem->IsBag()); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, pDstItem, NULL); return; } // check dest->src move possibility ItemPosCountVec sSrc; uint16 eSrc = 0; if (_player->IsInventoryPos(src)) { msg = _player->CanStoreItem(srcbag, srcslot, sSrc, pDstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanStoreItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); } else if (_player->IsBankPos(src)) { msg = _player->CanBankItem(srcbag, srcslot, sSrc, pDstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanBankItem(srcbag, NULL_SLOT, sSrc, pDstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, pDstItem, true); } else if (_player->IsEquipmentPos(src)) { msg = _player->CanEquipItem(srcslot, eSrc, pDstItem, true); if (msg == EQUIP_ERR_OK) msg = _player->CanUnequipItem(eSrc, true); } if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, pDstItem, pSrcItem); return; } // now do moves, remove... _player->RemoveItem(dstbag, dstslot, false); _player->RemoveItem(srcbag, srcslot, false); // add to dest _player->EquipItem(dest, pSrcItem, true); // add to src if (_player->IsInventoryPos(src)) _player->StoreItem(sSrc, pDstItem, true); else if (_player->IsBankPos(src)) _player->BankItem(sSrc, pDstItem, true); else if (_player->IsEquipmentPos(src)) _player->EquipItem(eSrc, pDstItem, true); _player->AutoUnequipOffhandIfNeed(); } }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recvData) { ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); // Get petition guid from packet WorldPacket data; uint64 petitionGuid; recvData >> petitionGuid; // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionGuid), _player->GetGUIDLow()); Petition const* petition = sPetitionMgr->GetPetition(GUID_LOPART(petitionGuid)); if (!petition) { sLog->outError("Player %s (guid: %u) tried to turn in petition (guid: %u) that is not present in the database", _player->GetName().c_str(), _player->GetGUIDLow(), GUID_LOPART(petitionGuid)); return; } uint32 ownerguidlo = petition->ownerGuid; uint8 type = petition->petitionType; std::string name = petition->petitionName; // Only the petition owner can turn in the petition if (_player->GetGUIDLow() != ownerguidlo) return; // Petition type (guild/arena) specific checks if (type == GUILD_CHARTER_TYPE) { // Check if player is already in a guild if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; SendPacket(&data); return; } // Check if guild name is already taken if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } } else { // Check for valid arena bracket (2v2, 3v3, 5v5) uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; // Check if player is already in an arena team if (_player->GetArenaTeamId(slot)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } // Check if arena team name is already taken if (sArenaTeamMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } } // Get petition signatures from db Signatures const* signatures = sPetitionMgr->GetSignature(GUID_LOPART(petitionGuid)); uint8 signs = signatures ? signatures->signatureMap.size() : 0; SignatureMap signatureCopy; if (signs) signatureCopy = signatures->signatureMap; uint32 requiredSignatures; if (type == GUILD_CHARTER_TYPE) requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); else requiredSignatures = type-1; // Notify player if signatures are missing if (signs < requiredSignatures) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; SendPacket(&data); return; } // Proceed with guild/arena team creation // Delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); if (type == GUILD_CHARTER_TYPE) { // Create guild Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // Register guild and add guild master sGuildMgr->AddGuild(guild); Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_COMMAND_SUCCESS, name); // Add members from signatures if (signs) for (SignatureMap::const_iterator itr = signatureCopy.begin(); itr != signatureCopy.end(); ++itr) guild->AddMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); } else { // Receive the rest of the packet in arena team creation case uint32 background, icon, iconcolor, border, bordercolor; recvData >> background >> icon >> iconcolor >> border >> bordercolor; // Create arena team ArenaTeam* arenaTeam = new ArenaTeam(); if (!arenaTeam->Create(_player->GetGUID(), type, name, background, icon, iconcolor, border, bordercolor)) { delete arenaTeam; return; } // Register arena team sArenaTeamMgr->AddArenaTeam(arenaTeam); ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); // Add members if (signs) for (SignatureMap::const_iterator itr = signatureCopy.begin(); itr != signatureCopy.end(); ++itr) { ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitionsHandler: Adding arena team (guid: %u) member %u", arenaTeam->GetId(), memberGUID); arenaTeam->AddMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER)); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); // xinef: clear petition store (petition and signatures) sPetitionMgr->RemovePetition(GUID_LOPART(petitionGuid)); // created ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionGuid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_OK; SendPacket(&data); }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= go->GetGOValue()->FishingHole.MaxOpens) go->SetLootState(GO_JUST_DEACTIVATED); else go->SetLootState(GO_READY); } else go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED, player); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* group = player->GetGroup()) { if (group->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; } } else loot->roundRobinPlayer = 0; } } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else { if (pItem->loot.isLooted()) // Only delete item if no loot or money (unlooted loot is saved to db) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &creature->loot; if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!creature->IsAlive()) creature->AllLootRemovedFromCorpse(); creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* group = player->GetGroup()) { if (group->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; group->SendLooter(creature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } else loot->roundRobinPlayer = 0; } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket) { recvPacket.read_skip<uint32>(); Item *myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; Item *hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; bool myCanCompleteTrade=true,hisCanCompleteTrade=true; if (!GetPlayer()->pTrader) return; // not accept case incorrect money amount if (_player->tradeGold > _player->GetMoney()) { SendNotification(LANG_NOT_ENOUGH_GOLD); _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); _player->acceptTrade = false; return; } // not accept case incorrect money amount if (_player->pTrader->tradeGold > _player->pTrader->GetMoney()) { _player->pTrader->GetSession()->SendNotification(LANG_NOT_ENOUGH_GOLD); SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); _player->pTrader->acceptTrade = false; return; } // not accept if some items now can't be trade (cheating) for (int i = 0; i < TRADE_SLOT_TRADED_COUNT; ++i) { if (_player->tradeItems[i] != 0) { if (Item* item =_player->GetItemByGuid(_player->tradeItems[i])) { if (!item->CanBeTraded()) { SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); return; } } } if (_player->pTrader->tradeItems[i] != 0) { if (Item* item =_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i])) { if (!item->CanBeTraded()) { SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); return; } } } } _player->acceptTrade = true; if (_player->pTrader->acceptTrade) { // inform partner client _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); // store items in local list and set 'in-trade' flag for (int i=0; i<TRADE_SLOT_TRADED_COUNT; i++) { if (_player->tradeItems[i] != 0 ) { //Can return NULL myItems[i]=_player->GetItemByGuid( _player->tradeItems[i] ); if (myItems[i]) { myItems[i]->SetInTrade(); sLog.outDebug("Player trade item bag: %u slot: %u", myItems[i]->GetBagSlot(), myItems[i]->GetSlot()); } } if (_player->pTrader->tradeItems[i] != 0) { //Can return NULL hisItems[i]=_player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); if (hisItems[i]) { hisItems[i]->SetInTrade(); sLog.outDebug("Player trade item bag: %u slot: %u", hisItems[i]->GetBagSlot(), hisItems[i]->GetSlot()); } } } // test if item will fit in each inventory hisCanCompleteTrade = (_player->pTrader->CanStoreItems(myItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); myCanCompleteTrade = (_player->CanStoreItems(hisItems,TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); // clear 'in-trade' flag for (int i=0; i<TRADE_SLOT_TRADED_COUNT; i++) { if (myItems[i]) myItems[i]->SetInTrade(false); if (hisItems[i]) hisItems[i]->SetInTrade(false); } // in case of missing space report error if (!myCanCompleteTrade) { SendNotification(LANG_NOT_FREE_TRADE_SLOTS); GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); return; } else if (!hisCanCompleteTrade) { SendNotification(LANG_NOT_PARTNER_FREE_TRADE_SLOTS); GetPlayer()->pTrader->GetSession()->SendNotification(LANG_NOT_FREE_TRADE_SLOTS); SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); return; } // execute trade: 1. remove for(int i = 0; i < TRADE_SLOT_TRADED_COUNT; i++) { Item* iPtr = NULL; if (myItems[i]) { myItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->GetGUID()); iPtr = _player->GetItemByGuid(_player->tradeItems[i]); _player->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); } if (hisItems[i]) { hisItems[i]->SetUInt64Value(ITEM_FIELD_GIFTCREATOR,_player->pTrader->GetGUID()); iPtr = _player->pTrader->GetItemByGuid(_player->pTrader->tradeItems[i]); _player->pTrader->MoveItemFromInventory(iPtr->GetBagSlot(), iPtr->GetSlot(), true); } } // execute trade: 2. store moveItems(myItems, hisItems); // logging money if (sWorld.getConfig(CONFIG_GM_LOG_TRADE)) { if (_player->GetSession()->GetSecurity() > SEC_PLAYER && _player->tradeGold > 0) { sLog.outCommand(_player->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", _player->GetName(),_player->GetSession()->GetAccountId(), _player->tradeGold, _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId()); } if (_player->pTrader->GetSession()->GetSecurity() > SEC_PLAYER && _player->pTrader->tradeGold > 0) { sLog.outCommand(_player->pTrader->GetSession()->GetAccountId(),"GM %s (Account: %u) give money (Amount: %u) to player: %s (Account: %u)", _player->pTrader->GetName(),_player->pTrader->GetSession()->GetAccountId(), _player->pTrader->tradeGold, _player->GetName(),_player->GetSession()->GetAccountId()); } } // update money _player->ModifyMoney(-int32(_player->tradeGold)); _player->ModifyMoney(_player->pTrader->tradeGold); _player->pTrader->ModifyMoney(-int32(_player->pTrader->tradeGold)); _player->pTrader->ModifyMoney(_player->tradeGold); _player->ClearTrade(); _player->pTrader->ClearTrade(); // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) CharacterDatabase.BeginTransaction(); _player->SaveInventoryAndGoldToDB(); _player->pTrader->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); _player->pTrader->pTrader = NULL; _player->pTrader = NULL; } else { _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); } }
void WorldSession::HandleSellItemOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_SELL_ITEM"); ObjectGuid vendorGuid; ObjectGuid itemGuid; uint32 count; recv_data >> vendorGuid; recv_data >> itemGuid; recv_data >> count; if (!itemGuid) return; Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR); if (!pCreature) { DEBUG_LOG("WORLD: HandleSellItemOpcode - %s not found or you can't interact with him.", vendorGuid.GetString().c_str()); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemGuid, 0); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); Item* pItem = _player->GetItemByGuid(itemGuid); if (pItem) { // prevent sell not owner item if (_player->GetObjectGuid() != pItem->GetOwnerGuid()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } // prevent sell non empty bag by drag-and-drop at vendor's item list if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } // prevent sell currently looted item if (_player->GetLootGuid() == pItem->GetObjectGuid()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } // special case at auto sell (sell all) if (count == 0) { count = pItem->GetCount(); } else { // prevent sell more items that exist in stack (possible only not from client) if (count > pItem->GetCount()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } } ItemPrototype const* pProto = pItem->GetProto(); if (pProto) { if (pProto->SellPrice > 0) { if (count < pItem->GetCount()) // need split items { Item* pNewItem = pItem->CloneItem(count, _player); if (!pNewItem) { sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } pItem->SetCount(pItem->GetCount() - count); _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); if (_player->IsInWorld()) pItem->SendCreateUpdateToPlayer(_player); pItem->SetState(ITEM_CHANGED, _player); _player->AddItemToBuyBackSlot(pNewItem); if (_player->IsInWorld()) pNewItem->SendCreateUpdateToPlayer(_player); } else { _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); pItem->RemoveFromUpdateQueueOf(_player); _player->AddItemToBuyBackSlot(pItem); } uint64 money = pProto->SellPrice * count; _player->ModifyMoney(money); _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); } else _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemGuid, 0); return; } } _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemGuid, 0); return; }
void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData) { Player* player = GetPlayer(); // Read everything ObjectGuid npcGuid; recvData.ReadByteMask(npcGuid[1]); uint32 countDeposit = recvData.ReadBits(26); if (countDeposit > 9) return; std::vector<ObjectGuid> itemGuids(countDeposit); for (uint32 i = 0; i < countDeposit; ++i) { recvData .ReadByteMask(itemGuids[i][4]) .ReadByteMask(itemGuids[i][6]) .ReadByteMask(itemGuids[i][7]) .ReadByteMask(itemGuids[i][0]) .ReadByteMask(itemGuids[i][1]) .ReadByteMask(itemGuids[i][5]) .ReadByteMask(itemGuids[i][3]) .ReadByteMask(itemGuids[i][2]); } recvData .ReadByteMask(npcGuid[2]) .ReadByteMask(npcGuid[0]) .ReadByteMask(npcGuid[3]) .ReadByteMask(npcGuid[5]) .ReadByteMask(npcGuid[6]) .ReadByteMask(npcGuid[4]); uint32 countWithdraw = recvData.ReadBits(26); if (countWithdraw > 9) return; std::vector<ObjectGuid> itemIds(countWithdraw); for (uint32 i = 0; i < countWithdraw; ++i) { recvData .ReadByteMask(itemIds[i][4]) .ReadByteMask(itemIds[i][7]) .ReadByteMask(itemIds[i][1]) .ReadByteMask(itemIds[i][0]) .ReadByteMask(itemIds[i][2]) .ReadByteMask(itemIds[i][3]) .ReadByteMask(itemIds[i][5]) .ReadByteMask(itemIds[i][6]); } recvData.ReadByteMask(npcGuid[7]); for (uint32 i = 0; i < countDeposit; ++i) { recvData .ReadByteSeq(itemGuids[i][6]) .ReadByteSeq(itemGuids[i][1]) .ReadByteSeq(itemGuids[i][0]) .ReadByteSeq(itemGuids[i][2]) .ReadByteSeq(itemGuids[i][4]) .ReadByteSeq(itemGuids[i][5]) .ReadByteSeq(itemGuids[i][3]) .ReadByteSeq(itemGuids[i][7]); } recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[6]); for (uint32 i = 0; i < countWithdraw; ++i) { recvData .ReadByteSeq(itemIds[i][3]) .ReadByteSeq(itemIds[i][0]) .ReadByteSeq(itemIds[i][1]) .ReadByteSeq(itemIds[i][6]) .ReadByteSeq(itemIds[i][2]) .ReadByteSeq(itemIds[i][7]) .ReadByteSeq(itemIds[i][5]) .ReadByteSeq(itemIds[i][4]); } recvData .ReadByteSeq(npcGuid[1]) .ReadByteSeq(npcGuid[4]) .ReadByteSeq(npcGuid[7]) .ReadByteSeq(npcGuid[3]) .ReadByteSeq(npcGuid[2]) .ReadByteSeq(npcGuid[0]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) return; if (!player->IsVoidStorageUnlocked()) 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) 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) 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); 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.WriteByteMask(creatorGuid[7]); data.WriteByteMask(itemId[7]); data.WriteByteMask(itemId[4]); data.WriteByteMask(creatorGuid[6]); data.WriteByteMask(creatorGuid[5]); data.WriteByteMask(itemId[3]); data.WriteByteMask(itemId[5]); data.WriteByteMask(creatorGuid[4]); data.WriteByteMask(creatorGuid[2]); data.WriteByteMask(creatorGuid[0]); data.WriteByteMask(creatorGuid[3]); data.WriteByteMask(creatorGuid[1]); data.WriteByteMask(itemId[2]); data.WriteByteMask(itemId[0]); data.WriteByteMask(itemId[1]); data.WriteByteMask(itemId[6]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteMask(itemId[1]); data.WriteByteMask(itemId[7]); data.WriteByteMask(itemId[3]); data.WriteByteMask(itemId[5]); data.WriteByteMask(itemId[6]); data.WriteByteMask(itemId[2]); data.WriteByteMask(itemId[4]); data.WriteByteMask(itemId[0]); } 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::HandleTurnInPetitionOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_TURN_IN_PETITION"); // Get petition guid from packet WorldPacket data; ObjectGuid petitionGuid; recvData.ReadGuidMask(petitionGuid, 1, 2, 3, 0, 5, 7, 4, 6); recvData.ReadGuidBytes(petitionGuid, 2, 1, 4, 6, 0, 7, 5, 3); // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; TC_LOG_DEBUG("network", "Petition %u turned in by %u", GUID_LOPART(petitionGuid), _player->GetGUIDLow()); // Get petition data from db uint32 ownerguidlo; uint32 type; std::string name; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { TC_LOG_ERROR("network", "Player %s (guid: %u) tried to turn in petition (guid: %u) that is not present in the database", _player->GetName().c_str(), _player->GetGUIDLow(), GUID_LOPART(petitionGuid)); return; } // Only the petition owner can turn in the petition if (_player->GetGUIDLow() != ownerguidlo) return; // Petition type (guild/arena) specific checks // Check if player is already in a guild if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 1); data.WriteBits(PETITION_TURN_ALREADY_IN_GUILD, 4); data.FlushBits(); _player->GetSession()->SendPacket(&data); return; } // Check if guild name is already taken if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } // Get petition signatures from db uint8 signatures; stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); result = CharacterDatabase.Query(stmt); if (result) signatures = uint8(result->GetRowCount()); else signatures = 0; uint32 requiredSignatures; if (type == GUILD_CHARTER_TYPE) requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); else requiredSignatures = type-1; // Notify player if signatures are missing if (signatures < requiredSignatures) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 1); data.WriteBits(PETITION_TURN_NEED_MORE_SIGNATURES, 4); data.FlushBits(); SendPacket(&data); return; } // Proceed with guild/arena team creation // Delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); // Create guild Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // Register guild and add guild master sGuildMgr->AddGuild(guild); Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_COMMAND_SUCCESS, name); // Add members from signatures for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); guild->AddMember(MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); result->NextRow(); } SQLTransaction trans = CharacterDatabase.BeginTransaction(); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); // created TC_LOG_DEBUG("network", "TURN IN PETITION GUID %u", GUID_LOPART(petitionGuid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 1); data.WriteBits(PETITION_TURN_OK, 4); data.FlushBits(); SendPacket(&data); }
// $req will be deleted by the caller. void WorldSession::HandleSendMailCallback(WorldSession::AsyncMailSendRequest* req) { MasterPlayer* pl = GetMasterPlayer(); Player* loadedPlayer = GetPlayer(); ASSERT(pl); uint32 reqmoney = req->money + 30; // Check for overflow if (reqmoney < req->money) { ProcessAnticheatAction("MailCheck", "Attempt to send free mails with money overflow", CHEAT_ACTION_LOG); pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } if (reqmoney && (!loadedPlayer || loadedPlayer->GetMoney() < reqmoney)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255.. if (req->mailsCount > 100) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED); return; } // check the receiver's Faction... if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != req->rcTeam && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } uint32 rc_account = sObjectMgr.GetPlayerAccountIdByGUID(req->receiver); Item* item = NULL; if (req->itemGuid) { item = loadedPlayer->GetItemByGuid(req->itemGuid); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item || !item->IsInWorld()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (!item->CanBeTraded()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if ((item->GetProto()->Flags & ITEM_FLAG_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (req->COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } } // Antispam checks if (loadedPlayer->getLevel() < sWorld.getConfig(CONFIG_UINT32_MAILSPAM_LEVEL) && req->money < sWorld.getConfig(CONFIG_UINT32_MAILSPAM_MONEY) && (sWorld.getConfig(CONFIG_BOOL_MAILSPAM_ITEM) && !req->itemGuid)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR); return; } AccountPersistentData& data = sAccountMgr.GetAccountPersistentData(GetAccountId()); if (!data.CanMail(rc_account)) { std::stringstream details; std::string from = ChatHandler(this).playerLink(GetMasterPlayer()->GetName()); std::string to = ChatHandler(this).playerLink(req->receiverName); details << from << " -> " << to << "\n"; details << req->subject << "\n"; details << req->body << "\n"; if (req->COD) details << "COD: " << req->COD << " coppers\n"; uint32 logId = sWorld.InsertLog(details.str(), SEC_GAMEMASTER); std::stringstream oss; oss << "Mail limit reached (\"" << req->body.substr(0, 30) << "...\") [log #" << logId << "]"; ProcessAnticheatAction("ChatSpam", oss.str().c_str(), CHEAT_ACTION_LOG | CHEAT_ACTION_REPORT_GMS); pl->SendMailResult(0, MAIL_SEND, MAIL_OK); return; } data.JustMailed(rc_account); pl->SendMailResult(0, MAIL_SEND, MAIL_OK); loadedPlayer->ModifyMoney(-int32(reqmoney)); bool needItemDelay = false; MailDraft draft(req->subject, req->body); if (!req->COD && (req->money || item)) { PlayerTransactionData data; data.type = "Mail"; data.parts[0].lowGuid = pl->GetGUIDLow(); if (item) { data.parts[0].itemsEntries[0] = item->GetEntry(); data.parts[0].itemsCount[0] = item->GetCount(); } data.parts[0].money = req->money; data.parts[1].lowGuid = req->receiver.GetCounter(); sWorld.LogTransaction(data); } if (req->itemGuid || req->money > 0) { if (item) { if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_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(), req->receiver.GetString().c_str(), rc_account); } loadedPlayer->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(); // deletes item from character's inventory item->SaveToDB(); // 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 CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", req->receiver.GetCounter(), item->GetGUIDLow()); CharacterDatabase.CommitTransaction(); draft.AddItem(item); // if item send to character at another account, then apply item delivery delay needItemDelay = pl->GetSession()->GetAccountId() != rc_account; } if (req->money > 0 && GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(), "GM %s (Account: %u) mail money: %u to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), req->money, req->receiver.GetString().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.getConfig(CONFIG_UINT32_MAIL_DELIVERY_DELAY) : 0; if (!item && req->COD) { req->COD = 0; ProcessAnticheatAction("MailCheck", "Attempt to send COD mail without any item", CHEAT_ACTION_LOG); } // will delete item or place to receiver mail list draft .SetMoney(req->money) .SetCOD(req->COD) .SendMailTo(MailReceiver(req->receiverPtr, req->receiver), loadedPlayer, req->body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); CharacterDatabase.BeginTransaction(); loadedPlayer->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { uint64 guid; uint32 questId; uint32 unk1; recvData >> guid >> questId >> unk1; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %u, quest = %u, unk1 = %u", uint32(GUID_LOPART(guid)), questId, unk1); Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT|TYPEMASK_ITEM|TYPEMASK_PLAYER); #define CLOSE_GOSSIP_CLEAR_DIVIDER() \ do { \ _player->PlayerTalkClass->SendCloseGossip(); \ _player->SetDivider(0); \ } while (0) // no or incorrect quest giver if (!object) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Player* playerQuestObject = object->ToPlayer()) { if ((_player->GetDivider() && _player->GetDivider() != guid) || ((object != _player && !playerQuestObject->CanShareQuest(questId)))) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } else { if (!object->hasQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) return; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { // prevent cheating if (!GetPlayer()->CanTakeQuest(quest, true)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (_player->GetDivider() != 0) { Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); if (player) { player->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); _player->SetDivider(0); } } if (_player->CanAddQuest(quest, true)) { _player->AddQuest(quest, object); if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) { if (Group* group = _player->GetGroup()) { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == _player) // not self continue; if (player->CanTakeQuest(quest, true)) { player->SetDivider(_player->GetGUID()); //need confirmation that any gossip window will close player->PlayerTalkClass->SendCloseGossip(); _player->SendQuestConfirmAccept(quest, player); } } } } if (_player->CanCompleteQuest(questId)) _player->CompleteQuest(questId); switch (object->GetTypeId()) { case TYPEID_UNIT: sScriptMgr->OnQuestAccept(_player, (object->ToCreature()), quest); object->ToCreature()->AI()->sQuestAccept(_player, quest); break; case TYPEID_ITEM: case TYPEID_CONTAINER: { Item* item = (Item*)object; sScriptMgr->OnQuestAccept(_player, item, quest); // destroy not required for quest finish quest starting item bool destroyItem = true; for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) { if (quest->RequiredItemId[i] == item->GetEntry() && item->GetTemplate()->MaxCount > 0) { destroyItem = false; break; } } if (destroyItem) _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); break; } case TYPEID_GAMEOBJECT: sScriptMgr->OnQuestAccept(_player, object->ToGameObject(), quest); object->ToGameObject()->AI()->QuestAccept(_player, quest); break; default: break; } _player->PlayerTalkClass->SendCloseGossip(); if (quest->GetSrcSpell() > 0) _player->CastSpell(_player, quest->GetSrcSpell(), true); return; } } _player->PlayerTalkClass->SendCloseGossip(); #undef CLOSE_GOSSIP_CLEAR_DIVIDER }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); // Get petition guid from packet WorldPacket data; uint64 petitionGuid; recv_data >> petitionGuid; // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionGuid), _player->GetGUIDLow()); // Get petition data from db uint32 ownerguidlo; std::string name; PreparedStatement* stmt = CharDB.GetPreparedStatement(CHAR_LOAD_PETITION); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); PreparedQueryResult result = CharDB.Query(stmt); if (result) { Field *fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); } else { sLog->outError("Player %s (guid: %u) tried to turn in petition (guid: %u) that is not present in the database", _player->GetName(), _player->GetGUIDLow(), GUID_LOPART(petitionGuid)); return; } // Only the petition owner can turn in the petition if (_player->GetGUIDLow() != ownerguidlo) return; // Petition type (guild/arena) specific checks if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild _player->GetSession()->SendPacket(&data); return; } // Get petition signatures from db uint8 signatures; stmt = CharDB.GetPreparedStatement(CHAR_LOAD_PETITION_SIGNATURE); stmt->setUInt32(0, GUID_LOPART(petitionGuid)); result = CharDB.Query(stmt); if (result) signatures = uint8(result->GetRowCount()); else signatures = 0; if (signatures < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; SendPacket(&data); return; } // Delete charter item _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true); if (sObjectMgr->GetGuildByName(name)) { Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // Register guild and add guild master sObjectMgr->AddGuild(guild); // Add members from signatures for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); guild->AddMember(MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER)); result->NextRow(); } } else { // ToDo: Fix Arena Team creation // Receive the rest of the packet in arena team creation case /*uint32 background, icon, iconcolor, border, bordercolor; recv_data >> background >> icon >> iconcolor >> border >> bordercolor; // Create arena team ArenaTeam* arenaTeam = new ArenaTeam(); if (!arenaTeam->Create(_player->GetGUID(), type, name, background, icon, iconcolor, border, bordercolor)) { delete arenaTeam; return; } // Register arena team sObjectMgr->AddArenaTeam(arenaTeam); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); // Add members for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); uint32 memberGUID = fields[0].GetUInt32(); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitionsHandler: Adding arena team (guid: %u) member %u", arenaTeam->GetId(), memberGUID); arenaTeam->AddMember(MAKE_NEW_GUID(memberGUID, 0, HIGHGUID_PLAYER)); result->NextRow(); }*/ } SQLTransaction trans = CharDB.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionGuid)); CharDB.CommitTransaction(trans); // created sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionGuid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_OK; SendPacket(&data); }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld->getRate(RATE_MINING_AMOUNT); float min_amount = go_min*amount_rate; float max_amount = go_max*amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld->getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate, 4*(1/double(max_amount))*double(uses)); if (roll_chance_f((float)(100*chance+skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED, player); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* group = player->GetGroup()) { if (group->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; } } else loot->roundRobinPlayer = 0; } } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else { if (pItem->loot.isLooted()) // Only delete item if no loot or money (unlooted loot is saved to db) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &creature->loot; if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!creature->isAlive()) creature->AllLootRemovedFromCorpse(); creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* group = player->GetGroup()) { if (group->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; group->SendLooter(creature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } else loot->roundRobinPlayer = 0; } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_SELL_ITEM"); uint64 vendorguid, itemguid; uint32 count; recv_data >> vendorguid >> itemguid >> count; if (!itemguid) return; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorguid))); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item* pItem = _player->GetItemByGuid(itemguid); if (pItem) { // prevent sell not owner item if (_player->GetGUID() != pItem->GetOwnerGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } // prevent sell non empty bag by drag-and-drop at vendor's item list if (pItem->IsNotEmptyBag()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } // prevent sell currently looted item if (_player->GetLootGUID() == pItem->GetGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } // prevent selling item for sellprice when the item is still refundable // this probably happens when right clicking a refundable item, the client sends both // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified) if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE)) return; // Therefore, no feedback to client // special case at auto sell (sell all) if (count == 0) { count = pItem->GetCount(); } else { // prevent sell more items that exist in stack (possible only not from client) if (count > pItem->GetCount()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } } ItemTemplate const* pProto = pItem->GetTemplate(); if (pProto) { if (pProto->SellPrice > 0) { if (count < pItem->GetCount()) // need split items { Item* pNewItem = pItem->CloneItem(count, _player); if (!pNewItem) { sLog->outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } pItem->SetCount(pItem->GetCount() - count); _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); if (_player->IsInWorld()) pItem->SendUpdateToPlayer(_player); pItem->SetState(ITEM_CHANGED, _player); _player->AddItemToBuyBackSlot(pNewItem); if (_player->IsInWorld()) pNewItem->SendUpdateToPlayer(_player); } else { _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); pItem->RemoveFromUpdateQueueOf(_player); _player->AddItemToBuyBackSlot(pItem); } uint32 money = pProto->SellPrice * count; _player->ModifyMoney(money); _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money); } else _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, itemguid, 0); return; } } _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, itemguid, 0); return; }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) { sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok //recv_data.hexlike(); WorldPacket data; uint64 petitionguid; uint32 ownerguidlo; std::string name; recv_data >> petitionguid; sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); // data QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if(result) { Field *fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetCppString(); delete result; } else { sLog.outError("petition table has broken data!"); return; } if(_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_ALREADY_IN_GUILD); // already in guild _player->GetSession()->SendPacket(&data); return; } if(_player->GetGUIDLow() != ownerguidlo) return; // signs uint8 signs; result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if(result) signs = (uint8)result->GetRowCount(); else signs = 0; uint32 count = sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS); if(signs < count) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_NEED_MORE_SIGNATURES); // need more signatures... SendPacket(&data); delete result; return; } if(sObjectMgr.GetGuildByName(name)) { SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); delete result; return; } // and at last charter item check Item *item = _player->GetItemByGuid(petitionguid); if(!item) { delete result; return; } // OK! // delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); Guild* guild = new Guild; if(!guild->Create(_player, name)) { delete guild; delete result; return; } // register guild and add guildmaster sObjectMgr.AddGuild(guild); // add members for(uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank()); result->NextRow(); } delete result; CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); CharacterDatabase.CommitTransaction(); // created sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_OK); SendPacket(&data); }
bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 uiAction) { WorldSession* session = player->GetSession(); player->PlayerTalkClass->ClearMenus(); switch(sender) { case EQUIPMENT_SLOT_END: // Show items you can use { if (Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)) { uint32 lowGUID = player->GetGUIDLow(); _items[lowGUID].clear(); uint32 limit = 0; uint32 price = 0; switch (sTransmogrification->GetRequireGold()) { case 1: { price = (unsigned int)(GetFakePrice(oldItem)*sTransmogrification->GetGoldModifier()); } break; case 2: { price = (unsigned int)sTransmogrification->GetGoldCost(); } break; } char tokenCost[250] = "\n"; if(sTransmogrification->GetRequireToken()) snprintf(tokenCost, 250, "\n\n%u x %s", sTransmogrification->GetTokenAmount(), GetItemName(sObjectMgr->GetItemTemplate(sTransmogrification->GetTokenEntry()), session).c_str()); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) { if (limit > 30) break; if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) { uint32 display = newItem->GetTemplate()->DisplayInfoID; if (player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) { if (_items[lowGUID].find(display) == _items[lowGUID].end()) { limit++; _items[lowGUID][display] = newItem; player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, GetItemName(newItem->GetTemplate(), session), uiAction, display, session->GetTrinityString(LANG_POPUP_TRANSMOGRIFY)+GetItemName(newItem->GetTemplate(), session)+tokenCost, price, false); } } } } for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { if (Bag* bag = player->GetBagByPos(i)) { for (uint32 j = 0; j < bag->GetBagSize(); j++) { if (limit > 30) break; if (Item* newItem = player->GetItemByPos(i, j)) { uint32 display = newItem->GetTemplate()->DisplayInfoID; if (player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) { if (_items[lowGUID].find(display) == _items[lowGUID].end()) { limit++; _items[lowGUID][display] = newItem; player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, GetItemName(newItem->GetTemplate(), session), uiAction, display, session->GetTrinityString(LANG_POPUP_TRANSMOGRIFY)+GetItemName(newItem->GetTemplate(), session)+tokenCost, price, false); } } } } } } char removeOnePopup[250]; snprintf(removeOnePopup, 250, session->GetTrinityString(LANG_POPUP_REMOVE_ONE), GetSlotName(uiAction, session)); player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_1, session->GetTrinityString(LANG_OPTION_REMOVE_ONE), EQUIPMENT_SLOT_END+3, uiAction, removeOnePopup, 0, false); player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TALK, session->GetTrinityString(LANG_OPTION_BACK), EQUIPMENT_SLOT_END+1, 0); player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); } else OnGossipHello(player, creature); } break; case EQUIPMENT_SLOT_END+1: // Back { OnGossipHello(player, creature); } break; case EQUIPMENT_SLOT_END+2: // Remove Transmogrifications { bool removed = false; for (uint8 Slot = EQUIPMENT_SLOT_START; Slot < EQUIPMENT_SLOT_END; Slot++) { if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, Slot)) { if (newItem->DeleteFakeEntry() && !removed) removed = true; } } if (removed) { session->SendAreaTriggerMessage(session->GetTrinityString(LANG_REM_TRANSMOGRIFICATIONS_ITEMS)); player->PlayDirectSound(3337); } else session->SendNotification(session->GetTrinityString(LANG_ERR_NO_TRANSMOGRIFICATIONS)); OnGossipHello(player, creature); } break; case EQUIPMENT_SLOT_END+3: // Remove Transmogrification from single item { if (Item* newItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, uiAction)) { if (newItem->DeleteFakeEntry()) { session->SendAreaTriggerMessage(session->GetTrinityString(LANG_REM_TRANSMOGRIFICATION_ITEM), GetSlotName(uiAction, session)); player->PlayDirectSound(3337); } else session->SendNotification(session->GetTrinityString(LANG_ERR_NO_TRANSMOGRIFICATION), GetSlotName(uiAction, session)); } OnGossipSelect(player, creature, EQUIPMENT_SLOT_END, uiAction); } break; default: // Transmogrify { uint32 lowGUID = player->GetGUIDLow(); if(!sTransmogrification->GetRequireToken() || player->GetItemCount(sTransmogrification->GetTokenEntry()) >= sTransmogrification->GetTokenAmount()) { if (Item* oldItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, sender)) { if (_items[lowGUID].find(uiAction) != _items[lowGUID].end() && _items[lowGUID][uiAction]->IsInWorld()) { Item* newItem = _items[lowGUID][uiAction]; if (newItem->GetOwnerGUID() == player->GetGUIDLow() && (newItem->IsInBag() || newItem->GetBagSlot() == INVENTORY_SLOT_BAG_0) && player->SuitableForTransmogrification(oldItem, newItem) == ERR_FAKE_OK) { switch(sTransmogrification->GetRequireGold()) { case 1: { player->ModifyMoney(-1*(uint32)(GetFakePrice(oldItem)*sTransmogrification->GetGoldModifier())); } break; case 2: { player->ModifyMoney(-1*(unsigned int)sTransmogrification->GetGoldCost()); } break; } if(sTransmogrification->GetRequireToken()) player->DestroyItemCount(sTransmogrification->GetTokenEntry(), sTransmogrification->GetTokenAmount(), true); oldItem->SetFakeEntry(newItem->GetEntry()); newItem->SetNotRefundable(player); newItem->SetBinding(true); player->PlayDirectSound(3337); session->SendAreaTriggerMessage(session->GetTrinityString(LANG_ITEM_TRANSMOGRIFIED), GetSlotName(sender, session)); } else session->SendNotification(session->GetTrinityString(LANG_ERR_NO_ITEM_SUITABLE)); } else session->SendNotification(session->GetTrinityString(LANG_ERR_NO_ITEM_EXISTS)); } else session->SendNotification(session->GetTrinityString(LANG_ERR_EQUIP_SLOT_EMPTY)); } else session->SendNotification(session->GetTrinityString(LANG_ERR_NO_TOKEN), GetItemName(sObjectMgr->GetItemTemplate(sTransmogrification->GetTokenEntry()), session).c_str()); _items[lowGUID].clear(); OnGossipSelect(player, creature, EQUIPMENT_SLOT_END, sender); } break; } return true; }
/** * Handles the Packet sent by the client when sending a mail. * * This methods takes the packet sent by the client and performs the following actions: * - Checks whether the mail is valid: i.e. can he send the selected items, * does he have enough money, etc. * - Creates a MailDraft and adds the needed items, money, cost data. * - Sends the mail. * * Depending on the outcome of the checks performed the player will recieve a different * MailResponseResult. * * @see MailResponseResult * @see SendMailResult() * * @param recv_data the WorldPacket containing the data sent by the client. */ void WorldSession::HandleSendMail(WorldPacket & recv_data ) { ObjectGuid mailboxGuid; ObjectGuid itemGuid; uint64 unk3; std::string receiver, subject, body; uint32 unk1, unk2, money, COD; uint8 unk4; recv_data >> mailboxGuid; recv_data >> receiver; recv_data >> subject; recv_data >> body; recv_data >> unk1; // stationery? recv_data >> unk2; // 0x00000000 recv_data >> itemGuid; recv_data >> money >> COD; // money and cod recv_data >> unk3; // const 0 recv_data >> unk4; // const 0 // packet read complete, now do check if (!CheckMailBox(mailboxGuid)) return; if (receiver.empty()) return; Player* pl = _player; ObjectGuid rc; if (normalizePlayerName(receiver)) rc = sObjectMgr.GetPlayerGuidByName(receiver); if (!rc) { DETAIL_LOG("%s is sending mail to %s (GUID: nonexistent!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGuidStr().c_str(), receiver.c_str(), subject.c_str(), body.c_str(), itemGuid ? 1 : 0, money, COD, unk1, unk2); pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND); return; } DETAIL_LOG("%s is sending mail to %s with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGuidStr().c_str(), rc.GetString().c_str(), subject.c_str(), body.c_str(), itemGuid ? 1 : 0, money, COD, unk1, unk2); if (pl->GetObjectGuid() == rc) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANNOT_SEND_TO_SELF); return; } uint32 reqmoney = money + 30; if (pl->GetMoney() < reqmoney) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Player *receive = sObjectMgr.GetPlayer(rc); Team rc_team; uint8 mails_count = 0; // do not allow to send to one player more than 100 mails if (receive) { rc_team = receive->GetTeam(); mails_count = receive->GetMailSize(); } else { rc_team = sObjectMgr.GetPlayerTeamByGUID(rc); if (QueryResult* result = CharacterDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", rc.GetCounter())) { Field *fields = result->Fetch(); mails_count = fields[0].GetUInt32(); delete result; } } // 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; } // check the receiver's Faction... if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && GetSecurity() == SEC_PLAYER) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); return; } // PvP.Chars? if (receive) { if ((receive->isPvPCharacter() && !pl->isPvPCharacter()) || (!receive->isPvPCharacter() && pl->isPvPCharacter())) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); ChatHandler(pl).PSendSysMessage( "PvP.Characters and PvE.Characters cannot interchange mail."); return; } } else { if (pl->isPvPCharacter()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM); ChatHandler(pl).PSendSysMessage( "The recipient is offline - cannot find out if it is also a PvP.Character."); return; } } uint32 rc_account = receive ? receive->GetSession()->GetAccountId() : sObjectMgr.GetPlayerAccountIdByGUID(rc); Item* item = NULL; if (itemGuid) { item = pl->GetItemByGuid(itemGuid); // 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()) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if ((item->GetProto()->Flags & ITEM_FLAG_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID); return; } if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_DYNFLAG_WRAPPED)) { pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD); return; } } pl->SendMailResult(0, MAIL_SEND, MAIL_OK); pl->ModifyMoney( -int32(reqmoney) ); bool needItemDelay = false; MailDraft draft(subject, body); if (itemGuid || money > 0) { uint32 rc_account = 0; if(receive) rc_account = receive->GetSession()->GetAccountId(); else rc_account = sObjectMgr.GetPlayerAccountIdByGUID(rc); if (item) { if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_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); } pl->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(); // deletes item from character's inventory item->SaveToDB(); // 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 CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", rc.GetCounter(), item->GetGUIDLow()); CharacterDatabase.CommitTransaction(); 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.getConfig(CONFIG_BOOL_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) mail money: %u 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.getConfig(CONFIG_UINT32_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list draft .SetMoney(money) .SetCOD(COD) .SendMailTo(MailReceiver(receive, rc), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Received opcode CMSG_TURN_IN_PETITION"); // ok //recv_data.hexlike(); WorldPacket data; uint64 petitionguid; uint32 ownerguidlo; uint32 type; std::string name; recv_data >> petitionguid; sLog->outDebug(LOG_FILTER_NETWORKIO, "Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow()); // data QueryResult result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if (result) { Field *fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { sLog->outError("petition table has broken data!"); return; } if (type == GUILD_CHARTER_TYPE) { if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild _player->GetSession()->SendPacket(&data); return; } } else { uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; if (_player->GetArenaTeamId(slot)) { //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild //_player->GetSession()->SendPacket(&data); SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } } if (_player->GetGUIDLow() != ownerguidlo) return; // signs uint8 signs; result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if (result) signs = uint8(result->GetRowCount()); else signs = 0; uint32 count; //if (signs < sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)) if (type == GUILD_CHARTER_TYPE) count = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); else count = type-1; if (signs < count) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures... SendPacket(&data); return; } if (type == GUILD_CHARTER_TYPE) { if (sObjectMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_CREATE_S, ERR_GUILD_NAME_EXISTS_S, name); return; } } else { if (sObjectMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } } // and at last charter item check Item *item = _player->GetItemByGuid(petitionguid); if (!item) return; // OK! // delete charter item _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true); if (type == GUILD_CHARTER_TYPE) // create guild { Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // register guild and add guildmaster sObjectMgr->AddGuild(guild); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); guild->AddMember(fields[0].GetUInt64()); result->NextRow(); } } else // or arena team { ArenaTeam* at = new ArenaTeam; if (!at->Create(_player->GetGUID(), type, name)) { sLog->outError("PetitionsHandler: arena team create failed."); delete at; return; } uint32 icon, iconcolor, border, bordercolor, backgroud; recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor; at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor); // register team and add captain sObjectMgr->AddArenaTeam(at); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitonsHandler: arena team added to objmrg"); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); uint64 memberGUID = fields[0].GetUInt64(); sLog->outDebug(LOG_FILTER_NETWORKIO, "PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID)); at->AddMember(memberGUID); result->NextRow(); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); CharacterDatabase.CommitTransaction(trans); // created sLog->outDebug(LOG_FILTER_NETWORKIO, "TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_OK; SendPacket(&data); }
// this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: HandleAuctionSellItem"); ObjectGuid auctioneerGuid; uint64 item; uint32 etime, bid, buyout; recv_data >> auctioneerGuid; recv_data.read_skip<uint32>(); // const 1? recv_data >> item; recv_data.read_skip<uint32>(); // stack size recv_data >> bid; recv_data >> buyout; recv_data >> etime; if (!item || !bid || !etime) return; // check for cheaters Player *pl = GetPlayer(); AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid); if (!auctionHouseEntry) return; // always return pointer AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); // client send time in minutes, convert to common used sec time etime *= MINUTE; // client understand only 3 auction time switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); Item *it = pl->GetItemByGuid( item ); // do not allow to sell already auctioned items if(sAuctionMgr.GetAItem(GUID_LOPART(item))) { sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to auction) if(!it) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); return; } if(!it->CanBeTraded()) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } if ((it->GetProto()->Flags & ITEM_FLAG_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } //we have to take deposit : uint32 deposit = AuctionHouseMgr::GetAuctionDeposit( auctionHouseEntry, etime, it ); if ( pl->GetMoney() < deposit ) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); return; } if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE) ) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(), GetAccountId(), it->GetProto()->Name1, it->GetEntry(), it->GetCount()); } pl->ModifyMoney( -int32(deposit) ); uint32 auction_time = uint32(etime * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME)); AuctionEntry *AH = new AuctionEntry; AH->Id = sObjectMgr.GenerateAuctionID(); AH->item_guidlow = GUID_LOPART(item); AH->item_template = it->GetEntry(); AH->owner = pl->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auction_time; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; DETAIL_LOG("selling item %u to auctioneer %s with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), auctioneerGuid.GetString().c_str(), bid, buyout, auction_time, AH->GetHouseId()); auctionHouse->AddAuction(AH); sAuctionMgr.AddAItem(it); pl->MoveItemFromInventory( it->GetBagSlot(), it->GetSlot(), true); CharacterDatabase.BeginTransaction(); it->DeleteFromInventoryDB(); it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone AH->SaveToDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); if((sIRC.BOTMASK & 1024) != 0) sIRC.AHFunc(it->GetEntry(), it->GetProto()->Name1, pl->GetName()); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); }
void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { DETAIL_LOG("WORLD: CMSG_OPEN_ITEM packet, data length = %i",(uint32)recvPacket.size()); uint8 bagIndex, slot; recvPacket >> bagIndex >> slot; DETAIL_LOG("bagIndex: %u, slot: %u",bagIndex,slot); Player* pUser = _player; // ignore for remote control state if (!pUser->IsSelfMover()) return; Item *pItem = pUser->GetItemByPos(bagIndex, slot); if(!pItem) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); return; } ItemPrototype const *proto = pItem->GetProto(); if(!proto) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); return; } // locked item uint32 lockId = proto->LockID; if(lockId) { LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); if (!lockInfo) { pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); sLog.outError( "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow() , lockId); return; } // required picklocking if(lockInfo->Skill[1] || lockInfo->Skill[0]) { pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); return; } } if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped? { QueryResult *result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); if (result) { Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); uint32 flags = fields[1].GetUInt32(); pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); pItem->SetEntry(entry); pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags); pItem->SetState(ITEM_CHANGED, pUser); delete result; } else { sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow()); pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); return; } CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); } else pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE); }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGuid(ObjectGuid()); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(float(100.0f * chance + skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else // not fully looted object go->SetLootState(GO_ACTIVATED); break; } case HIGHGUID_CORPSE: // ONLY remove insignia at BG { Corpse* corpse = _player->GetMap()->GetCorpse(lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; switch (pItem->loot.loot_type) { // temporary loot in stacking items, clear loot state, no auto loot move case LOOT_PROSPECTING: { uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; // reset loot for allow repeat looting if stack > 5 pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItemCount(pItem, count, true); break; } // temporary loot, auto loot move case LOOT_DISENCHANTING: { if (!pItem->loot.isLooted()) player->AutoStoreLoot(pItem->loot); // can be lost if no space pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); break; } // normal persistence loot default: { // must be destroyed only if no loot if (pItem->loot.isLooted()) { pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } break; } } return; // item can be looted only single player } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; // update next looter if (Group* group = pCreature->GetGroupLootRecipient()) if (group->GetLooterGuid() == player->GetObjectGuid()) group->UpdateLooterGuid(pCreature); if (loot->isLooted()) { // for example skinning after normal loot pCreature->PrepareBodyLootState(); if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); } break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } // Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetObjectGuid()); }
void WorldSession::HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem& autoEquipItem) { if (autoEquipItem.Inv.Items.size() != 1) { TC_LOG_ERROR("network", "HandleAutoEquipItemOpcode - Invalid itemCount (" SZFMTD ")", autoEquipItem.Inv.Items.size()); return; } TC_LOG_DEBUG("network", "HandleAutoEquipItemOpcode: receive PackSlot: %u, Slot: %u", autoEquipItem.PackSlot, autoEquipItem.Slot); Item* srcItem = _player->GetItemByPos(autoEquipItem.PackSlot, autoEquipItem.Slot); if (!srcItem) return; // only at cheat uint16 dest; InventoryResult msg = _player->CanEquipItem(NULL_SLOT, dest, srcItem, !srcItem->IsBag()); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, srcItem); return; } uint16 src = srcItem->GetPos(); if (dest == src) // prevent equip in same slot, only at cheat return; Item* dstItem = _player->GetItemByPos(dest); if (!dstItem) // empty slot, simple case { if (!srcItem->GetChildItem().IsEmpty()) { InventoryResult childEquipResult = _player->CanEquipChildItem(srcItem); if (childEquipResult != EQUIP_ERR_OK) { _player->SendEquipError(msg, srcItem); return; } } _player->RemoveItem(autoEquipItem.PackSlot, autoEquipItem.Slot, true); _player->EquipItem(dest, srcItem, true); if (!srcItem->GetChildItem().IsEmpty()) _player->EquipChildItem(autoEquipItem.PackSlot, autoEquipItem.Slot, srcItem); _player->AutoUnequipOffhandIfNeed(); } else // have currently equipped item, not simple case { uint8 dstbag = dstItem->GetBagSlot(); uint8 dstslot = dstItem->GetSlot(); msg = _player->CanUnequipItem(dest, !srcItem->IsBag()); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, dstItem); return; } if (!dstItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_CHILD)) { // check dest->src move possibility ItemPosCountVec sSrc; uint16 eSrc = 0; if (_player->IsInventoryPos(src)) { msg = _player->CanStoreItem(autoEquipItem.PackSlot, autoEquipItem.Slot, sSrc, dstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanStoreItem(autoEquipItem.PackSlot, NULL_SLOT, sSrc, dstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sSrc, dstItem, true); } else if (_player->IsBankPos(src)) { msg = _player->CanBankItem(autoEquipItem.PackSlot, autoEquipItem.Slot, sSrc, dstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanBankItem(autoEquipItem.PackSlot, NULL_SLOT, sSrc, dstItem, true); if (msg != EQUIP_ERR_OK) msg = _player->CanBankItem(NULL_BAG, NULL_SLOT, sSrc, dstItem, true); } else if (_player->IsEquipmentPos(src)) { msg = _player->CanEquipItem(autoEquipItem.Slot, eSrc, dstItem, true); if (msg == EQUIP_ERR_OK) msg = _player->CanUnequipItem(eSrc, true); } if (msg == EQUIP_ERR_OK && Player::IsEquipmentPos(dest) && !srcItem->GetChildItem().IsEmpty()) msg = _player->CanEquipChildItem(srcItem); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, dstItem, srcItem); return; } // now do moves, remove... _player->RemoveItem(dstbag, dstslot, false); _player->RemoveItem(autoEquipItem.PackSlot, autoEquipItem.Slot, false); // add to dest _player->EquipItem(dest, srcItem, true); // add to src if (_player->IsInventoryPos(src)) _player->StoreItem(sSrc, dstItem, true); else if (_player->IsBankPos(src)) _player->BankItem(sSrc, dstItem, true); else if (_player->IsEquipmentPos(src)) _player->EquipItem(eSrc, dstItem, true); if (Player::IsEquipmentPos(dest) && !srcItem->GetChildItem().IsEmpty()) _player->EquipChildItem(autoEquipItem.PackSlot, autoEquipItem.Slot, srcItem); } else { if (Item* parentItem = _player->GetItemByGuid(dstItem->GetGuidValue(ITEM_FIELD_CREATOR))) { if (Player::IsEquipmentPos(dest)) { _player->AutoUnequipChildItem(parentItem); // dest is now empty _player->SwapItem(src, dest); // src is now empty _player->SwapItem(parentItem->GetPos(), src); } } } _player->AutoUnequipOffhandIfNeed(); } }
void WorldSession::HandleSellItemOpcode(WorldPacket & recv_data) { sLog.outDebug("WORLD: Received CMSG_SELL_ITEM"); uint64 vendorguid, itemguid; uint8 _count; recv_data >> vendorguid >> itemguid >> _count; // prevent possible overflow, as Oregon uses uint32 for item count uint32 count = _count; if (!itemguid) return; Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) { sLog.outDebug("WORLD: HandleSellItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(vendorguid))); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, itemguid, 0); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); Item *pItem = _player->GetItemByGuid(itemguid); if (pItem) { // prevent sell not owner item if (_player->GetGUID() != pItem->GetOwnerGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } // prevent sell non empty bag by drag-and-drop at vendor's item list if (pItem->IsBag() && !((Bag*)pItem)->IsEmpty()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } // prevent sell currently looted item if (_player->GetLootGUID() == pItem->GetGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } // special case at auto sell (sell all) if (count == 0) { count = pItem->GetCount(); } else { // prevent sell more items that exist in stack (possible only not from client) if (count > pItem->GetCount()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } } ItemPrototype const *pProto = pItem->GetProto(); if (pProto) { if (pProto->SellPrice > 0) { if (count < pItem->GetCount()) // need split items { Item *pNewItem = pItem->CloneItem(count, _player); if (!pNewItem) { sLog.outError("WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), count); _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } pItem->SetCount(pItem->GetCount() - count); _player->ItemRemovedQuestCheck(pItem->GetEntry(), count); if (_player->IsInWorld()) pItem->SendUpdateToPlayer(_player); pItem->SetState(ITEM_CHANGED, _player); _player->AddItemToBuyBackSlot(pNewItem); if (_player->IsInWorld()) pNewItem->SendUpdateToPlayer(_player); } else { _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); pItem->RemoveFromUpdateQueueOf(_player); _player->AddItemToBuyBackSlot(pItem); } _player->ModifyMoney(pProto->SellPrice * count); } else _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, pCreature, itemguid, 0); return; } } _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, pCreature, itemguid, 0); return; }
void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_SELL_ITEM: Vendor %s, Item %s, Amount: %u", packet.VendorGUID.ToString().c_str(), packet.ItemGUID.ToString().c_str(), packet.Amount); if (packet.ItemGUID.IsEmpty()) return; Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(packet.VendorGUID, UNIT_NPC_FLAG_VENDOR); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleSellItemOpcode - %s not found or you can not interact with him.", packet.VendorGUID.ToString().c_str()); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, nullptr, packet.ItemGUID); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item* pItem = _player->GetItemByGuid(packet.ItemGUID); if (pItem) { // prevent sell not owner item if (_player->GetGUID() != pItem->GetOwnerGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } // prevent sell non empty bag by drag-and-drop at vendor's item list if (pItem->IsNotEmptyBag()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } // prevent sell currently looted item if (_player->GetLootGUID() == pItem->GetGUID()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } // prevent selling item for sellprice when the item is still refundable // this probably happens when right clicking a refundable item, the client sends both // CMSG_SELL_ITEM and CMSG_REFUND_ITEM (unverified) if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FIELD_FLAG_REFUNDABLE)) return; // Therefore, no feedback to client // special case at auto sell (sell all) if (packet.Amount == 0) packet.Amount = pItem->GetCount(); else { // prevent sell more items that exist in stack (possible only not from client) if (packet.Amount > pItem->GetCount()) { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } } ItemTemplate const* pProto = pItem->GetTemplate(); if (pProto) { if (pProto->GetSellPrice() > 0) { uint64 money = uint64(pProto->GetSellPrice()) * packet.Amount; if (!_player->ModifyMoney(money)) // ensure player doesn't exceed gold limit { _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } _player->UpdateCriteria(CRITERIA_TYPE_MONEY_FROM_VENDORS, money); if (packet.Amount < pItem->GetCount()) // need split items { Item* pNewItem = pItem->CloneItem(packet.Amount, _player); if (!pNewItem) { TC_LOG_ERROR("network", "WORLD: HandleSellItemOpcode - could not create clone of item %u; count = %u", pItem->GetEntry(), packet.Amount); _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } pItem->SetCount(pItem->GetCount() - packet.Amount); _player->ItemRemovedQuestCheck(pItem->GetEntry(), packet.Amount); if (_player->IsInWorld()) pItem->SendUpdateToPlayer(_player); pItem->SetState(ITEM_CHANGED, _player); _player->AddItemToBuyBackSlot(pNewItem); if (_player->IsInWorld()) pNewItem->SendUpdateToPlayer(_player); } else { _player->ItemRemovedQuestCheck(pItem->GetEntry(), pItem->GetCount()); _player->RemoveItem(pItem->GetBagSlot(), pItem->GetSlot(), true); RemoveItemFromUpdateQueueOf(pItem, _player); _player->AddItemToBuyBackSlot(pItem); } } else _player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID); return; } } _player->SendSellError(SELL_ERR_CANT_FIND_ITEM, creature, packet.ItemGUID); return; }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recv_data) { DEBUG_LOG("Received opcode CMSG_TURN_IN_PETITION"); // ok // recv_data.hexlike(); ObjectGuid petitionGuid; recv_data >> petitionGuid; DEBUG_LOG("Petition %s turned in by %s", petitionGuid.GetString().c_str(), _player->GetGuidStr().c_str()); /// Collect petition info data ObjectGuid ownerGuid; std::string name; // data QueryResult* result = CharacterDatabase.PQuery("SELECT ownerguid, name FROM petition WHERE petitionguid = '%u'", petitionGuid.GetCounter()); if (result) { Field* fields = result->Fetch(); ownerGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); name = fields[1].GetCppString(); delete result; } else { sLog.outError("CMSG_TURN_IN_PETITION: petition table not have data for guid %u!", petitionGuid.GetCounter()); return; } if (_player->GetGuildId()) { WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_ALREADY_IN_GUILD); // already in guild _player->GetSession()->SendPacket(data); return; } if (_player->GetObjectGuid() != ownerGuid) return; // signs result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionGuid.GetCounter()); uint8 signs = result ? (uint8)result->GetRowCount() : 0; uint32 count = sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS); if (signs < count) { WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_NEED_MORE_SIGNATURES); // need more signatures... SendPacket(data); delete result; return; } if (sGuildMgr.GetGuildByName(name)) { SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S); delete result; return; } // and at last charter item check Item* item = _player->GetItemByGuid(petitionGuid); if (!item) { delete result; return; } // OK! // delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; delete result; return; } // register guild and add guildmaster sGuildMgr.AddGuild(guild); // Send result to GM if (WorldSession* session = _player->GetSession()) session->SendGuildCommandResult(GUILD_CREATE_S, name, 0); // add members for (uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch(); ObjectGuid signGuid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); if (signGuid.IsEmpty()) continue; guild->AddMember(signGuid, guild->GetLowestRank()); // Put record into guild log guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, signGuid); // Send result to online signees if (Player* signee = sObjectMgr.GetPlayer(signGuid)) { if (WorldSession* session = signee->GetSession()) session->SendGuildCommandResult(GUILD_FOUNDER_S, name, 0); } result->NextRow(); } delete result; CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", petitionGuid.GetCounter()); CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", petitionGuid.GetCounter()); CharacterDatabase.CommitTransaction(); // created DEBUG_LOG("TURN IN PETITION %s", petitionGuid.GetString().c_str()); WorldPacket data(SMSG_TURN_IN_PETITION_RESULTS, 4); data << uint32(PETITION_TURN_OK); SendPacket(data); }
void WorldSession::DoLootRelease(uint64 lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getRate(RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->requiredminingskill; float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(100 * chance + skill)) go->SetLootState(GO_READY); else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (int32(go->GetUseCount()) >= irand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) go->SetLootState(GO_JUST_DEACTIVATED); else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED, player); if (player->GetGUID() == loot->roundRobinPlayer) loot->roundRobinPlayer = 0; } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; if ((pItem->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) && pItem->GetProto()->Class == ITEM_CLASS_TRADE_GOODS && pItem->GetCount() >= 5) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = 5; player->DestroyItemCount(pItem, count, true); } else // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); return; // item can be looted only single player } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->IsAlive() == (player->getClass() == CLASS_ROGUE && pCreature->loot.loot_type == LOOT_SKINNING); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; if (loot->isLooted()) { pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!pCreature->IsAlive()) pCreature->AllLootRemovedFromCorpse(); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { loot->roundRobinPlayer = 0; if (Group* group = player->GetGroup()) { group->SendLooter(pCreature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data ) { uint64 auctioneer, item; uint32 etime, bid, buyout; recv_data >> auctioneer >> item; recv_data >> bid >> buyout >> etime; Player *pl = GetPlayer(); if (!item || !bid || !etime) return; //check for cheaters Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(pCreature->getFaction()); if(!auctionHouseEntry) { sLog.outDebug( "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer)) ); return; } // client send time in minutes, convert to common used sec time etime *= MINUTE; // client understand only 3 auction time switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item *it = pl->GetItemByGuid( item ); //do not allow to sell already auctioned items if(auctionmgr.GetAItem(GUID_LOPART(item))) { sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) if(!it) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); return; } if(!it->CanBeTraded()) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap( pCreature->getFaction() ); //we have to take deposit : uint32 deposit = auctionmgr.GetAuctionDeposit( auctionHouseEntry, etime, it ); if ( pl->GetMoney() < deposit ) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); return; } if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); } pl->ModifyMoney( -int32(deposit) ); uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); AuctionEntry *AH = new AuctionEntry; AH->Id = objmgr.GenerateAuctionID(); if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = 23442; else AH->auctioneer = GUID_LOPART(auctioneer); AH->item_guidlow = GUID_LOPART(item); AH->item_template = it->GetEntry(); AH->owner = pl->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auction_time; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); auctionHouse->AddAuction(AH); auctionmgr.AddAItem(it); pl->MoveItemFromInventory( it->GetBagSlot(), it->GetSlot(), true); CharacterDatabase.BeginTransaction(); it->DeleteFromInventoryDB(); it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone AH->SaveToDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); }
//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket& recvData) { ObjectGuid auctioneer; uint64 bid, buyout; uint32 etime; uint8 itemCount; // 32 slots, value sent as 5 bits ObjectGuid itemGuids[MAX_AUCTION_ITEMS]; uint32 count[MAX_AUCTION_ITEMS]; recvData >> buyout >> bid; recvData >> etime; if (!bid || !etime) { recvData.rfinish(); return; } if (bid > MAX_MONEY_AMOUNT || buyout > MAX_MONEY_AMOUNT) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Player %s (GUID %u) attempted to sell item with higher price than max gold amount.", _player->GetName().c_str(), _player->GetGUIDLow()); SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); recvData.rfinish(); return; } auctioneer[3] = recvData.ReadBit(); itemCount = recvData.ReadBits(5); if (itemCount > MAX_AUCTION_ITEMS) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); recvData.rfinish(); return; } auctioneer[0] = recvData.ReadBit(); for (uint8 i = 0; i < itemCount; i++) { itemGuids[i][4] = recvData.ReadBit(); itemGuids[i][6] = recvData.ReadBit(); itemGuids[i][2] = recvData.ReadBit(); itemGuids[i][3] = recvData.ReadBit(); itemGuids[i][5] = recvData.ReadBit(); itemGuids[i][7] = recvData.ReadBit(); itemGuids[i][1] = recvData.ReadBit(); itemGuids[i][0] = recvData.ReadBit(); } auctioneer[6] = recvData.ReadBit(); auctioneer[2] = recvData.ReadBit(); auctioneer[1] = recvData.ReadBit(); auctioneer[4] = recvData.ReadBit(); auctioneer[5] = recvData.ReadBit(); auctioneer[7] = recvData.ReadBit(); for (uint8 i = 0; i < itemCount; i++) { recvData.ReadByteSeq(itemGuids[i][3]); recvData.ReadByteSeq(itemGuids[i][1]); recvData >> count[i]; recvData.ReadByteSeq(itemGuids[i][6]); recvData.ReadByteSeq(itemGuids[i][4]); recvData.ReadByteSeq(itemGuids[i][5]); recvData.ReadByteSeq(itemGuids[i][0]); recvData.ReadByteSeq(itemGuids[i][2]); recvData.ReadByteSeq(itemGuids[i][7]); if (!itemGuids[i] || !count[i] || count[i] > 1000) { recvData.rfinish(); return; } } recvData.ReadByteSeq(auctioneer[3]); recvData.ReadByteSeq(auctioneer[7]); recvData.ReadByteSeq(auctioneer[2]); recvData.ReadByteSeq(auctioneer[5]); recvData.ReadByteSeq(auctioneer[6]); recvData.ReadByteSeq(auctioneer[1]); recvData.ReadByteSeq(auctioneer[0]); recvData.ReadByteSeq(auctioneer[4]); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(auctioneer)); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(creature->getFaction()); if (!auctionHouseEntry) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", GUID_LOPART(auctioneer)); return; } etime *= MINUTE; switch (etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item* items[MAX_AUCTION_ITEMS]; uint32 finalCount = 0; for (uint32 i = 0; i < itemCount; ++i) { Item* item = _player->GetItemByGuid(itemGuids[i]); if (!item) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_ITEM_NOT_FOUND); return; } if (sAuctionMgr->GetAItem(item->GetGUIDLow()) || !item->CanBeTraded() || item->IsNotEmptyBag() || item->GetTemplate()->Flags & ITEM_PROTO_FLAG_CONJURED || item->GetUInt32Value(ITEM_FIELD_EXPIRATION) || item->GetCount() < count[i]) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } items[i] = item; finalCount += count[i]; } if (!finalCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } for (uint32 i = 0; i < itemCount; ++i) { Item* item = items[i]; if (item->GetMaxStackCount() < finalCount) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); return; } } Item* item = items[0]; uint32 auctionTime = uint32(etime * sWorld->getRate(RATE_AUCTION_TIME)); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); uint32 deposit = sAuctionMgr->GetAuctionDeposit(auctionHouseEntry, etime, item, finalCount); if (!_player->HasEnoughMoney((uint64)deposit)) { SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_NOT_ENOUGHT_MONEY); return; } AuctionEntry* AH = new AuctionEntry(); if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = 23442; ///@TODO - HARDCODED DB GUID, BAD BAD BAD else AH->auctioneer = GUID_LOPART(auctioneer); // Required stack size of auction matches to current item stack size, just move item to auctionhouse if (itemCount == 1 && item->GetCount() == count[0]) { if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName().c_str(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); AH->itemGUIDLow = item->GetGUIDLow(); AH->itemEntry = item->GetEntry(); AH->itemCount = item->GetCount(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) " "to auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetGUIDLow(), AH->auctioneer, item->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(item); auctionHouse->AddAuction(AH); _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(trans); item->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size { Item* newItem = item->CloneItem(finalCount, _player); if (!newItem) { TC_LOG_ERROR("network", "CMSG_AUCTION_SELL_ITEM: Could not create clone of item %u", item->GetEntry()); SendAuctionCommandResult(NULL, AUCTION_SELL_ITEM, ERR_AUCTION_DATABASE_ERROR); delete AH; return; } if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { sLog->outCommand(GetAccountId(), "GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName().c_str(), GetAccountId(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetCount()); } AH->Id = sObjectMgr->GenerateAuctionID(); AH->itemGUIDLow = newItem->GetGUIDLow(); AH->itemEntry = newItem->GetEntry(); AH->itemCount = newItem->GetCount(); AH->owner = _player->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: Player %s (guid %d) is selling item %s entry %u (guid %d) to " "auctioneer %u with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetName().c_str(), _player->GetGUIDLow(), newItem->GetTemplate()->Name1.c_str(), newItem->GetEntry(), newItem->GetGUIDLow(), AH->auctioneer, newItem->GetCount(), bid, buyout, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(newItem); auctionHouse->AddAuction(AH); for (uint32 j = 0; j < itemCount; ++j) { Item* item2 = items[j]; // Item stack count equals required count, ready to delete item - cloned item will be used for auction if (item2->GetCount() == count[j]) { _player->MoveItemFromInventory(item2->GetBagSlot(), item2->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->DeleteFromInventoryDB(trans); item2->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); } else // Item stack count is bigger than required count, update item stack count and save to database - cloned item will be used for auction { item2->SetCount(item2->GetCount() - count[j]); item2->SetState(ITEM_CHANGED, _player); _player->ItemRemovedQuestCheck(item2->GetEntry(), count[j]); item2->SendUpdateToPlayer(_player); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item2->SaveToDB(trans); CharacterDatabase.CommitTransaction(trans); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); newItem->SaveToDB(trans); AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK); GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } _player->ModifyMoney(-int32(deposit)); }