Skip to content

fix(Core/Player): Loot Chest eligibility and re-send loot rolls#26469

Merged
Nyeriah merged 5 commits into
azerothcore:masterfrom
sogladev:fix-chest-loot-eligibility
Jul 18, 2026
Merged

fix(Core/Player): Loot Chest eligibility and re-send loot rolls#26469
Nyeriah merged 5 commits into
azerothcore:masterfrom
sogladev:fix-chest-loot-eligibility

Conversation

@sogladev

@sogladev sogladev commented Jul 4, 2026

Copy link
Copy Markdown
Member

Changes Proposed:

This PR proposes changes to:

  • Core (units, players, creatures, game systems).
  • Scripts (bosses, spell scripts, creature scripts).
  • Database (SAI, creatures, etc).

This contains 3 commits:

  • Fix issue where a player is not eligible for Loot from a GameObject chest when present for the kill, but outside of the map when the chest is opened.
  • Fix issue where a player does not show up on the master loot popup when outside of the map when the chest is opened
  • Re-send group loot roll window on map entry when the player hasn't selected an option yet.

AI-assisted Pull Requests

Important

While the use of AI tools when preparing pull requests is not prohibited, contributors must clearly disclose when such tools have been used and specify the model involved.

Contributors are also expected to fully understand the changes they are submitting and must be able to explain and justify those changes when requested by maintainers.

  • AI tools (e.g. ChatGPT, Claude, or similar) were used entirely or partially in preparing this pull request. Please specify which tools were used, if any.

Deepseek V4 Pro

Issues Addressed:

  • Closes

SOURCE:

The changes have been validated through:

  • Live research (checked on live servers, e.g Classic WotLK, Retail, etc.)
  • Sniffs (remember to share them with the open source community!)
  • Video evidence, knowledge databases or other public sources (e.g forums, Wowhead, etc.)
  • The changes promoted by this pull request come partially or entirely from another project (cherry-pick). Cherry-picks must be committed using the proper --author tag in order to be accepted, thus crediting the original authors, unless otherwise unable to be found

Tests Performed:

This PR has been:

  • Tested in-game by the author.
  • Tested in-game by other community members/someone else other than the author/has been live on production servers.
  • This pull request requires further testing and may have edge cases to be tested.

2 characters are required

  1. Raid Leader with Group Loot or Master Loot
  2. Any

GameObject testing:
.tele horsemen

Creature testing:
.tele patchw

Both characters must be present when killing the bosses. But, before looting, teleport the second character outside the map. Then try to award loot, roll, or trade items to the second character.

How to Test the Changes:

  • This pull request can be tested by following the reproduction steps provided in the linked issue
  • This pull request requires further testing. Provide steps to test your changes. If it requires any specific setup e.g multiple players please specify it as well.

Known Issues and TODO List:

  • [ ]
  • [ ]

How to Test AzerothCore PRs

When a PR is ready to be tested, it will be marked as [WAITING TO BE TESTED].

You can help by testing PRs and writing your feedback here on the PR's page on GitHub. Follow the instructions here:

http://www.azerothcore.org/wiki/How-to-test-a-PR

REMEMBER: when testing a PR that changes something generic (i.e. a part of code that handles more than one specific thing), the tester should not only check that the PR does its job (e.g. fixing spell XXX) but especially check that the PR does not cause any regression (i.e. introducing new bugs).

For example: if a PR fixes spell X by changing a part of code that handles spells X, Y, and Z, we should not only test X, but we should test Y and Z as well.

sogladev added 3 commits July 4, 2026 20:12
for GameObject Loot chests only: If a player is outside of the instance,
when a raid loot chest is opened, that player remains eligible for the
loot.

The player outside will receive an emblem, and items can be traded.

Tested with master loot and group loot
Players not inside the instance will now show up in the list, but result
in a "Player not found" UI error message
fix issue where rolls are "lost" if a player disconnects, logs out,
leaves the map; or is corpserunning at the moment when a loot chest is
opened
Copilot AI review requested due to automatic review settings July 4, 2026 18:21
@github-actions github-actions Bot added CORE Related to the core file-cpp Used to trigger the matrix build labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Group loot eligibility in GroupLoot, NeedBeforeGreed, and MasterLoot now accepts players in a gameobject's allowed-looter list in addition to distance-based checks. A new Group::SendPendingRollsToPlayer method resends pending roll-start packets on map entry, and Player::SendLoot pre-fills non-normal loot for allowed looters.

Changes

Allowed-looter eligibility and pending roll resend

Layer / File(s) Summary
Loot eligibility checks in group roll flows
src/server/game/Groups/Group.cpp
GroupLoot (normal and quest items), NeedBeforeGreed, and MasterLoot replace distance-only checks with a combined canLoot condition allowing players on the allowed-looter list even outside reward distance.
Pending roll resend and non-normal loot pre-fill
src/server/game/Groups/Group.h, src/server/game/Groups/Group.cpp, src/server/game/Entities/Player/Player.cpp
Adds Group::SendPendingRollsToPlayer to resend active roll-start packets based on vote state, countdown, and NEED_BEFORE_GREED eligibility; wires it into Player::SendInitialPacketsAfterAddToMap for dungeon/raid entry, and pre-fills non-normal loot for allowed looters in Player::SendLoot.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: Kitzunu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately reflects the main changes to loot eligibility and loot-roll resends.
Description check ✅ Passed The description covers the main changes, AI disclosure, tests, and repro steps, with only minor template fields left partial.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/game/Groups/Group.cpp`:
- Around line 1242-1246: The NeedBeforeGreed quest-item roll path in
Group::RollForGroup should use the same allowed-looter fallback as the other
loot roll paths, since it currently only checks IsAtGroupRewardDistance() and
blocks eligible out-of-range players. Update the quest-item loop to mirror the
canLoot logic used elsewhere in Group.cpp by checking
lootedObject->GetAllowedLooters().empty() and then
HasAllowedLooter(playerToRoll->GetGUID()) before deciding whether the player can
roll.
- Around line 901-905: The loot handling in Group::SendLootStart (the branch
using loot->sourceGameObject) should not rely on the raw GameObject* because it
can dangle before pending rolls are sent. Change this path to resolve the object
from sourceWorldObjectGUID, mirroring the creature branch, then use the resolved
GameObject to read m_groupLootTimer and set lootedObject only if the lookup
succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: b0204b25-e2c8-4a79-92c8-fa10c3c23981

📥 Commits

Reviewing files that changed from the base of the PR and between b4f2e6f and 54e6d34.

📒 Files selected for processing (3)
  • src/server/game/Entities/Player/Player.cpp
  • src/server/game/Groups/Group.cpp
  • src/server/game/Groups/Group.h

Comment on lines +901 to +905
if (GameObject* go = loot->sourceGameObject)
{
remainingTime = go->m_groupLootTimer;
lootedObject = go;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm Loot members used here exist and their types
rg -nP '\b(sourceGameObject|sourceWorldObjectGUID)\b' --type=cpp --type=h -C2 src/server/game/Loot/
ast-grep run --pattern 'class Loot { $$$ }' --lang cpp $(fd -a LootMgr.h) 2>/dev/null | rg -n 'sourceGameObject|sourceWorldObjectGUID' -C1

Repository: azerothcore/azerothcore-wotlk

Length of output: 4844


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant loot member definitions and nearby usage.
grep -RIn --line-number --context=3 -E '\bsourceGameObject\b|\bsourceWorldObjectGUID\b' src/server/game/Loot src/server/game/Groups/Group.cpp

# Show the Loot definition around the member declarations.
file=$(git ls-files 'src/server/game/Loot/LootMgr.h' | head -n1)
sed -n '300,380p' "$file"

# Show the Group.cpp loot branch in context.
sed -n '880,930p' src/server/game/Groups/Group.cpp

# Find where sourceGameObject is assigned or cleared.
grep -RIn --line-number -E 'sourceGameObject\s*=|sourceGameObject\b.*nullptr|sourceGameObject\b.*=' src/server/game/Loot src/server/game | head -n 50

Repository: azerothcore/azerothcore-wotlk

Length of output: 13760


Use sourceWorldObjectGUID instead of loot->sourceGameObject. Loot::sourceGameObject is a raw GameObject*, so this can dangle if the object despawns before pending rolls are sent. Resolve the gameobject by GUID, as in the creature branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/game/Groups/Group.cpp` around lines 901 - 905, The loot handling
in Group::SendLootStart (the branch using loot->sourceGameObject) should not
rely on the raw GameObject* because it can dangle before pending rolls are sent.
Change this path to resolve the object from sourceWorldObjectGUID, mirroring the
creature branch, then use the resolved GameObject to read m_groupLootTimer and
set lootedObject only if the lookup succeeds.

Comment on lines +1242 to +1246
bool canLoot = playerToRoll->IsAtGroupRewardDistance(lootedObject);
if (!canLoot && !lootedObject->GetAllowedLooters().empty())
canLoot = lootedObject->HasAllowedLooter(playerToRoll->GetGUID());

if (canLoot)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/server/game/Groups/Group.cpp"

# Show the relevant regions around the referenced lines and nearby loot-roll logic.
sed -n '1060,1355p' "$file" | cat -n

Repository: azerothcore/azerothcore-wotlk

Length of output: 13227


NeedBeforeGreed quest items should honor allowed looters src/server/game/Groups/Group.cpp:247-274
The quest-item loop still gates rolls on IsAtGroupRewardDistance() only. Add the same allowed-looter fallback used in the other roll paths so eligible out-of-range players can roll on NBG quest items.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/game/Groups/Group.cpp` around lines 1242 - 1246, The
NeedBeforeGreed quest-item roll path in Group::RollForGroup should use the same
allowed-looter fallback as the other loot roll paths, since it currently only
checks IsAtGroupRewardDistance() and blocks eligible out-of-range players.
Update the quest-item loop to mirror the canLoot logic used elsewhere in
Group.cpp by checking lootedObject->GetAllowedLooters().empty() and then
HasAllowedLooter(playerToRoll->GetGUID()) before deciding whether the player can
roll.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts group loot eligibility and client loot-roll messaging so that players who were present for a kill but are temporarily outside the map/instance can still be treated as eligible (e.g., for chest loot/master loot lists), and adds logic to re-send pending loot roll windows when a player re-enters an instance.

Changes:

  • Expands roll/master-loot candidate selection to include players listed in the loot source’s AllowedLooters, even if they fail distance/map checks.
  • Adds Group::SendPendingRollsToPlayer() and calls it on map entry to re-send unresolved roll windows.
  • For chest group-loot rules, fills non-normal loot visibility for all allowed looters (not only those currently near the chest).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/server/game/Groups/Group.h Adds SendPendingRollsToPlayer() declaration to support re-sending unresolved roll windows.
src/server/game/Groups/Group.cpp Implements pending-roll re-send; adjusts eligibility checks to consider AllowedLooters for group/master loot.
src/server/game/Entities/Player/Player.cpp Fills loot visibility for allowed looters on chest loot generation; triggers pending-roll re-send on instance entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

canNeed = (player->CanRollForItemInLFG(proto, lootedObject) == EQUIP_ERR_OK);
}

SendLootStartRollToPlayer(remainingTime, map->GetId(), player, canNeed, *roll);
Comment on lines +915 to +921
bool canNeed = true;
if (GetLootMethod() == NEED_BEFORE_GREED)
{
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(roll->itemid);
if (proto && lootedObject)
canNeed = (player->CanRollForItemInLFG(proto, lootedObject) == EQUIP_ERR_OK);
}
Comment on lines +1242 to +1246
bool canLoot = playerToRoll->IsAtGroupRewardDistance(lootedObject);
if (!canLoot && !lootedObject->GetAllowedLooters().empty())
canLoot = lootedObject->HasAllowedLooter(playerToRoll->GetGUID());

if (canLoot)
@sogladev sogladev changed the title fix(Core/Player): Loot Chest eligibility and re-send loot rules fix(Core/Player): Loot Chest eligibility and re-send loot rolls Jul 5, 2026
@PkllonG

PkllonG commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Creature drops passed the test, but gameobject drops are wrong. .go c id 32906 (No quest looting window appeared) AND .go c id 32930 (There's a loot window you can ROLL, but no loot message).

I also found another mistake. After A kills the boss(B wasn’t in the instance when killing the boss), when B enters the instance, the team has finished rolling and passed on some items, B can still loot them! Is this correct? I remember that someone who didn't participate in the kill shouldn't be able to loot.

@sogladev
sogladev marked this pull request as draft July 11, 2026 15:53
@sogladev

Copy link
Copy Markdown
Member Author

Creature drops passed the test, but gameobject drops are wrong. .go c id 32906 (No quest looting window appeared) AND .go c id 32930 (There's a loot window you can ROLL, but no loot message).

.go c id 32906 ignores Freya's chest, as it's bugged due to a regression.

.go c id 32930 for Kologarn, what is the issue @PkllonG ? Is it master loot or group loot?

I also found another mistake. After A kills the boss(B wasn’t in the instance when killing the boss), when B enters the instance, the team has finished rolling and passed on some items, B can still loot them! Is this correct? I remember that someone who didn't participate in the kill shouldn't be able to loot.

This is a bug specific to Freya where loot isn't tied to Freya. Freya's Chest is summoned by SPELL_EFFECT_SUMMON_OBJECT_WILD, which doesn't set any loot recipients.

also reported by copilot:

@sogladev
sogladev marked this pull request as ready for review July 13, 2026 23:17
@PkllonG

PkllonG commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Creature drops passed the test, but gameobject drops are wrong. .go c id 32906 (No quest looting window appeared) AND .go c id 32930 (There's a loot window you can ROLL, but no loot message).

.go c id 32906 ignores Freya's chest, as it's bugged due to a regression.

.go c id 32930 for Kologarn, what is the issue @PkllonG ? Is it master loot or group loot?

I also found another mistake. After A kills the boss(B wasn’t in the instance when killing the boss), when B enters the instance, the team has finished rolling and passed on some items, B can still loot them! Is this correct? I remember that someone who didn't participate in the kill shouldn't be able to loot.

This is a bug specific to Freya where loot isn't tied to Freya. Freya's Chest is summoned by , which doesn't set any loot recipients.SPELL_EFFECT_SUMMON_OBJECT_WILD

also reported by copilot:

Works fine after using #26592.

@PkllonG

PkllonG commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

-- Creature ID 33515
Both A and B are in the instance -> Kill the BOSS -> A loots it 《Works fine》
B is not in the instance -> Kill the BOSS -> B enters the instance -> A loots it (Error: After rolling, remaining items can be looted by B, which is wrong)
B is not in the instance -> Kill the BOSS -> A loots it -> B enters the instance (Error: After rolling, remaining items can be looted by B, which is wrong)
B is in the instance -> Kill the BOSS -> B leaves -> B re-enters -> A loots it 《Works fine》
B is in the instance -> Kill the BOSS -> B leaves -> A loots it -> B re-enters 《Works fine》

-- Creature ID 32906
Both A and B are in the instance -> Kill the BOSS -> A loots it 《Works fine》
B is not in the instance -> Kill the BOSS -> B enters the instance -> A loots it 《Works fine》
B is not in the instance -> Kill the BOSS -> A loots it -> B enters the instance 《Works fine》
B is in the instance -> Kill the BOSS -> B leaves -> B re-enters -> A loots it 《Works fine》
B is in the instance -> Kill the BOSS -> B leaves -> A loots it -> B re-enters 《Works fine》

-- Creature ID 32930
Both A and B are in the instance -> Kill the BOSS -> A loots it 《Works fine》
B is not in the instance -> Kill the BOSS -> B enters the instance -> A loots it 《Works fine》
B is not in the instance -> Kill the BOSS -> A loots it -> B enters the instance 《Works fine》
B is in the instance -> Kill the BOSS -> B leaves -> B re-enters -> A loots it 《Works fine》
B is in the instance -> Kill the BOSS -> B leaves -> A loots it -> B re-enters 《Works fine》

@PkllonG

PkllonG commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

During testing, we found that there’s a bug in the biological looting. It should be an error that existed before the PR and has nothing to do with the PR. The PR has been tested.

@Nyeriah
Nyeriah merged commit 37c7238 into azerothcore:master Jul 18, 2026
18 checks passed
@pureland251025

Copy link
Copy Markdown

Items from Thorim's chest, after the rolling process, still fail to appear in players' inventories. Is this the same issue?

@sogladev

Copy link
Copy Markdown
Member Author

Items from Thorim's chest, after the rolling process, still fail to appear in players' inventories. Is this the same issue?

Did this bug happen before this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE Related to the core file-cpp Used to trigger the matrix build Ready to be Reviewed Waiting to be Tested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants