From 6b6da2861b0b0d445cccbd5488fab8edff2b46d1 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 26 Sep 2026 21:08:45 -0300 Subject: [PATCH] feat(Core/Commands): Show guid and remaining count on .additem removal (#27817) --- .../rev_1790462170445466200.sql | 12 ++++++ .../Implementation/CharacterDatabase.cpp | 4 +- src/server/game/Miscellaneous/Language.h | 6 ++- src/server/scripts/Commands/cs_misc.cpp | 38 +++++++++++++++---- 4 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1790462170445466200.sql diff --git a/data/sql/updates/pending_db_world/rev_1790462170445466200.sql b/data/sql/updates/pending_db_world/rev_1790462170445466200.sql new file mode 100644 index 0000000000..d249dba083 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1790462170445466200.sql @@ -0,0 +1,12 @@ +-- +UPDATE `acore_string` SET +`content_default` = 'Removed itemID = {}, amount = {} from {} (GUID: {}, {}). Remaining: {}', +`locale_deDE` = 'Entferne itemID {}, Anzahl {} von {} (GUID: {}, {}). Verbleibend: {}', +`locale_zhCN` = '移除物品ID = {}, amount = {} from {} (GUID: {}, {}). 剩余: {}' +WHERE `entry` = 496; + +DELETE FROM `acore_string` WHERE `entry` IN (35480, 35481, 35482); +INSERT INTO `acore_string` (`entry`, `content_default`, `locale_deDE`, `locale_zhCN`) VALUES +(35480, 'Removed itemID = {}, amount = {} from {} (GUID: {}, {}). No items remaining.', 'Entferne itemID {}, Anzahl {} von {} (GUID: {}, {}). Keine Gegenstände verbleibend.', '移除物品ID = {}, amount = {} from {} (GUID: {}, {}). 没有剩余物品.'), +(35481, 'online', 'online', '在线'), +(35482, 'offline', 'offline', '离线'); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index a3def12d13..e4dffef486 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -439,8 +439,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() "INNER JOIN item_instance ii ON ii.guid = ci.item " "LEFT JOIN character_inventory cb ON cb.item = ci.bag WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY_AND_OWNER, "SELECT ci.item FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE ii.itemEntry = ? AND ii.owner_guid = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHAR_INVENTORY_STACKS_BY_ENTRY_AND_OWNER, "SELECT ci.item, ii.count FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item " - "LEFT JOIN character_inventory cb ON cb.bag = ci.item WHERE ii.itemEntry = ? AND ii.owner_guid = ? AND cb.item IS NULL", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHAR_INVENTORY_STACKS_BY_ENTRY_AND_OWNER, "SELECT ci.item, ii.count, EXISTS (SELECT 1 FROM character_inventory cb WHERE cb.guid = ci.guid AND cb.bag = ci.item) " + "FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE ii.itemEntry = ? AND ii.owner_guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_MAIL_ITEMS_BY_ENTRY, "SELECT mi.item_guid, m.sender, m.receiver, cs.account, cs.name, cr.account, cr.name " "FROM mail m INNER JOIN mail_items mi ON mi.mail_id = m.id INNER JOIN item_instance ii ON ii.guid = mi.item_guid " "INNER JOIN characters cs ON cs.guid = m.sender INNER JOIN characters cr ON cr.guid = m.receiver WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 6c44df656e..22e1f59956 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1556,6 +1556,10 @@ enum AcoreStrings LANG_ACCOUNT_INFO_CHAR_ENTRY = 35476, LANG_ACCOUNT_INFO_NO_CHARS = 35477, LANG_ACCOUNT_INFO_CURRENT_IP = 35478, - LANG_ACCOUNT_INFO_CHAR_OFFLINE = 35479 + LANG_ACCOUNT_INFO_CHAR_OFFLINE = 35479, + + LANG_REMOVEITEM_NONE_LEFT = 35480, + LANG_CHARACTER_ONLINE = 35481, + LANG_CHARACTER_OFFLINE = 35482 }; #endif diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 5cfc67f586..647a380699 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1721,6 +1721,16 @@ public: return true; } + static void SendRemoveItemResult(ChatHandler* handler, uint32 itemId, uint32 removed, std::string const& nameLink, ObjectGuid::LowType guidLow, bool online, uint32 countLeft) + { + std::string status = handler->GetAcoreString(online ? LANG_CHARACTER_ONLINE : LANG_CHARACTER_OFFLINE); + + if (countLeft) + handler->PSendSysMessage(LANG_REMOVEITEM, itemId, removed, nameLink, guidLow, status, countLeft); + else + handler->PSendSysMessage(LANG_REMOVEITEM_NONE_LEFT, itemId, removed, nameLink, guidLow, status); + } + static bool HandleAddItemCommand(ChatHandler* handler, Optional player, ItemTemplate const* itemTemplate, Optional _count) { if (!sObjectMgr->GetItemTemplate(itemTemplate->ItemId)) @@ -1771,9 +1781,12 @@ public: } } - // output successful amount of destroyed items + uint32 countBefore = playerTarget->GetItemCount(itemId, true); playerTarget->DestroyItemCount(itemId, removeCount, true, false); - handler->PSendSysMessage(LANG_REMOVEITEM, itemId, removeCount, handler->GetNameLink(playerTarget)); + uint32 countAfter = playerTarget->GetItemCount(itemId, true); + + SendRemoveItemResult(handler, itemId, countBefore - countAfter, handler->GetNameLink(playerTarget), + playerTarget->GetGUID().GetCounter(), true, countAfter); return true; } @@ -1789,18 +1802,26 @@ public: PreparedQueryResult result = CharacterDatabase.Query(stmt); std::vector> stacks; - uint32 totalCount = 0; + uint32 removableCount = 0; + uint32 ownedCount = 0; if (result) { do { Field* fields = result->Fetch(); - stacks.emplace_back(fields[0].Get(), fields[1].Get()); - totalCount += fields[1].Get(); + uint32 stackCount = fields[1].Get(); + ownedCount += stackCount; + + // Bags that still hold items are never removed + if (fields[2].Get()) + continue; + + stacks.emplace_back(fields[0].Get(), stackCount); + removableCount += stackCount; } while (result->NextRow()); } - if (!totalCount) + if (!removableCount) { handler->SendErrorMessage(LANG_REMOVEITEM_FAILURE, nameLink, itemId); return false; @@ -1808,7 +1829,7 @@ public: // Only have scam check on player accounts uint32 accountId = sCharacterCache->GetCharacterAccountIdByGuid(player->GetGUID()); - if (AccountMgr::GetSecurity(accountId, realm.Id.Realm) == SEC_PLAYER && totalCount < removeCount) + if (AccountMgr::GetSecurity(accountId, realm.Id.Realm) == SEC_PLAYER && removableCount < removeCount) { handler->SendErrorMessage(LANG_REMOVEITEM_ERROR, nameLink, itemId); return false; @@ -1854,7 +1875,8 @@ public: } CharacterDatabase.CommitTransaction(trans); - handler->PSendSysMessage(LANG_REMOVEITEM, itemId, removeCount - remaining, nameLink); + uint32 removed = removeCount - remaining; + SendRemoveItemResult(handler, itemId, removed, nameLink, player->GetGUID().GetCounter(), false, ownedCount - removed); return true; }