From 169e31f2c63b1572c7d1dfb54766f2254288df7c Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Tue, 19 May 2026 21:41:11 -0300 Subject: [PATCH] feat(Core/Groups): mail roll-won items when inventory is full (#25909) Co-authored-by: Claude Sonnet 4.6 --- .../apps/worldserver/worldserver.conf.dist | 10 +++++ src/server/game/Entities/Player/Player.h | 1 + .../game/Entities/Player/PlayerMisc.cpp | 13 +++++++ src/server/game/Groups/Group.cpp | 38 ++++++++++++++++--- src/server/game/Groups/Group.h | 7 ++++ src/server/game/World/WorldConfig.cpp | 2 + src/server/game/World/WorldConfig.h | 1 + 7 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist index 982d73c27..5ee8464a0 100644 --- a/src/server/apps/worldserver/worldserver.conf.dist +++ b/src/server/apps/worldserver/worldserver.conf.dist @@ -3386,6 +3386,16 @@ DungeonAccessRequirements.OptionalStringID = 0 JoinBGAndLFG.Enable = 0 +# +# LFG.MailItemOnFullInventory +# Description: When a player wins a group roll but their inventory is full, mail +# the item to them instead of leaving it on the corpse. +# Default: 0 - Disabled +# 1 - Only in LFG/RDF groups +# 2 - In all group types + +LFG.MailItemOnFullInventory = 0 + # # DungeonFinder.OptionsMask # Description: Dungeon and raid finder system. diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1b1ca057f..71831c18b 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1668,6 +1668,7 @@ public: [[nodiscard]] PlayerMails const& GetMails() const { return m_mail; } void SendItemRetrievalMail(uint32 itemEntry, uint32 count); // Item retrieval mails sent by The Postmaster (34337) void SendItemRetrievalMail(std::vector> mailItems); // Item retrieval mails sent by The Postmaster (34337) + void SendItemRetrievalMail(Item* item); // As above, but for a pre-created item (preserves randomPropertyId) /*********************************************************/ /*** MAILED ITEMS SYSTEM ***/ diff --git a/src/server/game/Entities/Player/PlayerMisc.cpp b/src/server/game/Entities/Player/PlayerMisc.cpp index 91a3fa93c..4b5f063d0 100644 --- a/src/server/game/Entities/Player/PlayerMisc.cpp +++ b/src/server/game/Entities/Player/PlayerMisc.cpp @@ -508,3 +508,16 @@ void Player::SendItemRetrievalMail(std::vector> mailIt CharacterDatabase.CommitTransaction(trans); } + +void Player::SendItemRetrievalMail(Item* item) +{ + if (!item) + return; + + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + item->SaveToDB(trans); + MailDraft("Recovered Item", "We recovered a lost item in the twisting nether and noted that it was yours.$B$BPlease find said object enclosed.") + .AddItem(item) + .SendMailTo(trans, MailReceiver(this, GetGUID().GetCounter()), MailSender(MAIL_CREATURE, 34337 /* The Postmaster */)); + CharacterDatabase.CommitTransaction(trans); +} diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 25ecb1cd2..3a4e5a2fb 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1490,9 +1490,22 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) } else { - item->is_blocked = false; - item->rollWinnerGUID = player->GetGUID(); - player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + uint32 mailOnFull = sWorld->getIntConfig(CONFIG_LFG_MAIL_ITEM_ON_FULL_INVENTORY); + if (mailOnFull == MAIL_ITEM_ON_FULL_INVENTORY_EVERYWHERE || (mailOnFull == MAIL_ITEM_ON_FULL_INVENTORY_LFG_ONLY && isLFGGroup())) + { + item->is_looted = true; + roll->getLoot()->NotifyItemRemoved(roll->itemSlot); + roll->getLoot()->unlootedCount--; + player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + if (Item* mailItem = Item::CreateItem(roll->itemid, item->count, player, false, item->randomPropertyId)) + player->SendItemRetrievalMail(mailItem); + } + else + { + item->is_blocked = false; + item->rollWinnerGUID = player->GetGUID(); + player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + } } } } @@ -1560,9 +1573,22 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) } else { - item->is_blocked = false; - item->rollWinnerGUID = player->GetGUID(); - player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + uint32 mailOnFull = sWorld->getIntConfig(CONFIG_LFG_MAIL_ITEM_ON_FULL_INVENTORY); + if (mailOnFull == MAIL_ITEM_ON_FULL_INVENTORY_EVERYWHERE || (mailOnFull == MAIL_ITEM_ON_FULL_INVENTORY_LFG_ONLY && isLFGGroup())) + { + item->is_looted = true; + roll->getLoot()->NotifyItemRemoved(roll->itemSlot); + roll->getLoot()->unlootedCount--; + player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + if (Item* mailItem = Item::CreateItem(roll->itemid, item->count, player, false, item->randomPropertyId)) + player->SendItemRetrievalMail(mailItem); + } + else + { + item->is_blocked = false; + item->rollWinnerGUID = player->GetGUID(); + player->SendEquipError(msg, nullptr, nullptr, roll->itemid); + } } } else if (rollvote == DISENCHANT) diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 5d2ca9e75..3b1bec04b 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -128,6 +128,13 @@ enum lfgGroupFlags GROUP_LFG_FLAG_IS_HEROIC = 0x004 }; +enum MailItemOnFullInventory +{ + MAIL_ITEM_ON_FULL_INVENTORY_DISABLED = 0, + MAIL_ITEM_ON_FULL_INVENTORY_LFG_ONLY = 1, + MAIL_ITEM_ON_FULL_INVENTORY_EVERYWHERE = 2, +}; + enum DifficultyPreventionChangeType { DIFFICULTY_PREVENTION_CHANGE_NONE = 0, diff --git a/src/server/game/World/WorldConfig.cpp b/src/server/game/World/WorldConfig.cpp index d96915e15..f1d872c0a 100644 --- a/src/server/game/World/WorldConfig.cpp +++ b/src/server/game/World/WorldConfig.cpp @@ -494,6 +494,8 @@ void WorldConfig::BuildConfigCache() SetConfigValue(CONFIG_ALLOW_JOIN_BG_AND_LFG, "JoinBGAndLFG.Enable", false); + SetConfigValue(CONFIG_LFG_MAIL_ITEM_ON_FULL_INVENTORY, "LFG.MailItemOnFullInventory", 0); + SetConfigValue(CONFIG_LEAVE_GROUP_ON_LOGOUT, "LeaveGroupOnLogout.Enabled", false); SetConfigValue(CONFIG_RANDOM_ROLL_MAXIMUM, "Group.RandomRollMaximum", 1000000); diff --git a/src/server/game/World/WorldConfig.h b/src/server/game/World/WorldConfig.h index c573fc287..a4b70c61b 100644 --- a/src/server/game/World/WorldConfig.h +++ b/src/server/game/World/WorldConfig.h @@ -375,6 +375,7 @@ enum ServerConfigs CONFIG_LOOT_NEED_BEFORE_GREED_ILVL_RESTRICTION, CONFIG_LFG_MAX_KICK_COUNT, CONFIG_LFG_KICK_PREVENTION_TIMER, + CONFIG_LFG_MAIL_ITEM_ON_FULL_INVENTORY, CONFIG_CHANGE_FACTION_MAX_MONEY, CONFIG_WATER_BREATH_TIMER, CONFIG_DAILY_RBG_MIN_LEVEL_AP_REWARD,