TrinityCore / TrinityCore

TrinityCore Open Source MMO Framework (master = 11.0.5.57388, 3.3.5 = 3.3.5a.12340, cata classic = 4.4.1.57294)
http://www.trinitycore.org
GNU General Public License v2.0
9.61k stars 6.06k forks source link

[3.3.5] Round Robin/Group Loot does not apply to quest items #22829

Closed kartoffelsup closed 1 year ago

kartoffelsup commented 5 years ago

Description:

As far as I remember, quest items were a part of group loot/round robin rules in WOTLK. However, on 352c4a4 with _2018_11_21_00world.sql one is able to 'steal' another group members quest item (even though he is the 'round_robin_player')

Current behaviour:

If in a group with another player with both having the same quest where specific items need to be looted from creatures (i.e. Lynx Collar for Quest Unfortunate Measures), if a quest item drops and the Loot Mode is set to 'Group Loot', the _non-round_robinplayer can 'steal' the quest item from the _round_robinplayer.

Expected behaviour:

AFAIR, only the round_robin_player should be able to receive the quest item as long as they still need it.

Steps to reproduce the problem:

  1. Start 2 Clients
  2. Create BloodElf on Client1
  3. Create another BloodElf on Client2
  4. Group them up
  5. Make sure Loot Type is set to Group Loot
  6. Accept Quest Unfortunate Measures on both
  7. Kill a Springpaw Cub
  8. Notice how the _non-round_robinplayer can steal the Lynx Collar from the _round_robinplayer.

Branch(es):

3.3.5

TC rev. hash/commit: 352c4a4

Operating system: Manjaro Linux x64

ghost commented 5 years ago

Aren't they separate loot categories? Or did I miss something important? In my game client, I see the following loot methods:

(only the group leader can see more than the active method)

kartoffelsup commented 5 years ago

I saw in the code that the field 'round_robin_player' is being used for both Group Loot and Round Robin. Though to be frank, I have never used Round Robin ever, so I guess I can only provide info on Group Loot in this case.

FYI, I'm using this as a workaround at the moment. It does come with downsides though:

Index: src/server/game/Loot/Loot.cpp
<+>UTF-8
===================================================================
--- src/server/game/Loot/Loot.cpp   (revision 352c4a4c680c94fc9fbc725c51135667662f1c77)
+++ src/server/game/Loot/Loot.cpp   (date 1543131566000)
@@ -184,6 +184,29 @@
                 if (player->IsInMap(lootOwner))
                     FillNotNormalLootFor(player, player->IsAtGroupRewardDistance(lootOwner));

+        if (group->GetLootMethod() == GROUP_LOOT || group->GetLootMethod() == ROUND_ROBIN) {
+            NotNormalLootItemMap::const_iterator iter = PlayerQuestItems.find(roundRobinPlayer);
+            if (iter != PlayerQuestItems.end() && iter->second) {
+                NotNormalLootItemList &pql = *iter->second;
+                for (int j = 0; j < pql.size(); ++j) {
+                    auto &qItem = quest_items[pql[j].index];
+                    if (!qItem.freeforall) {
+                        for (NotNormalLootItemMap::const_iterator itr = PlayerQuestItems.begin();
+                             itr != PlayerQuestItems.end(); ++itr) {
+                            if (itr->first != roundRobinPlayer && itr->second) {
+                                auto list = itr->second;
+                                list->erase(std::remove_if(list->begin(), list->end(),
+                                                           [&](NotNormalLootItem i) {
+                                                               return i.index == pql[j].index;
+                                                           }),
+                                            list->end());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
         for (uint8 i = 0; i < items.size(); ++i)
         {
             if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(items[i].itemid))
ghost commented 5 years ago

Would be nice if any of the seasoned coders could take look at it and provide a constructive comment.

Shauren commented 5 years ago

I don't know about this. I thought quest items were supposed to be FFA with unlimited copies for entire group (with the exception of raid quests like shadowmourne) - and that is how it works for as long as I played on retail (that is cata)

Killyana commented 5 years ago

It depends if the item has the Flags=2048 "Item is party loot and can be looted by all" I'm not sure about only "round_robin_player" could loot the item. If it's the case imagine the player number one completed the quest (have required Lynx Collar in the inventory) and he will help player number 2 to finish the quest, in this case killed npc tagued for player number 1 will not show the item for player 2.

kartoffelsup commented 5 years ago

I don't know about this. I thought quest items were supposed to be FFA with unlimited copies for entire group (with the exception of raid quests like shadowmourne) - and that is how it works for as long as I played on retail (that is cata)

I think this is especially the case in Legion/BFA. But if my memory doesn't fail me, this was not true for WOTLK. Most of the quest items were actually bound to the 'round_robin_player', unless they had finished the quest/are not on the quest.

kartoffelsup commented 5 years ago

In the history of WoWWiki, in an entry shortly before Cataklysm (Revision as of 18:17, September 21, 2010), it says:

Quest loot is on a separate loot distribution and there are two common modes for this to occur. 1) In quests where the party is to collect one of a specific item from a specific mob (Collect the head of (mob name here)) then regardless of loot setting, the mob will indicate lootable by every party member with the quest (and without the object). Each member may loot the quest item off the corpse. The other loot on the corpse is subject to the party loot setting. 2) In other quests which require collecting several items of a type (harpy feathers for example), the quest items will drop on some mobs and be looted in the normal way, except that if the current looter can't collect the items (not on quest, already has full set) then the quest loot is FFA for those members who can still pick up the quest items. Other items on the corpse are governed by the party loot setting. On some quests the quest loot is always free-for-all and this may be the above mechanic gone haywire. Some quests where the party is collecting one item will use the named mob mechanism (1) (the Shaman Voodoo Charm from The Sleeping Druid quest, for example, where all party members can get the charm off the same shaman.)

The first scenario is when the qItem.freeforall flag is true The second scenario is what my bug report is about:

In other quests which require collecting several items of a type (harpy feathers for example), the quest items will drop on some mobs and be looted in the normal way, except that if the current looter can't collect the items (not on quest, already has full set) then the quest loot is FFA for those members who can still pick up the quest items

Shauren commented 5 years ago

The thing you need to always keep in mind is that wiki writers do not know anything about how most of the stuff works under the hood and especially they do not know about various item flags such as the one mentioned earlier ITEM_FLAG_MULTI_DROP. So do not go by "quest item or not" but rather just check the flag

Killyana commented 5 years ago

Confirm, if there's a quest item dropped by the npc, the corpse could be loot by any member that need this item (but only the quest item will be visible for this players).

According to many sources the corpse must turn lootable and show the quest item only if the player that own the loot doesn't require the quest item.