mirror of
https://github.com/TemujinCalidius/SurvivorCore.git
synced 2026-08-14 00:58:01 +00:00
fix: loot-bag owner beacon race + looting while dead
- Beacon: LootBagDropped fired the same frame the bag was created, so the Instance reference arrived as nil on the client (not yet replicated) and the owner beacon silently never appeared. The fire is now delayed 0.5s. - Dead looting: collect() never verified the collector was alive, so a corpse lying next to its own bag could scoop everything back before respawning. The server now rejects dead collectors (isAlive gate, Harvesting pattern). Live verification note: the running Studio session executed stale bytecode (old collect granted loot to a dead player even though the new source was synced) — verified source-in-place; behavior verification needs a Studio restart, which CI/release artifacts are unaffected by. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
015dc60a8e
commit
78f99a0667
@@ -5,6 +5,15 @@ All notable changes to SurvivorCore are recorded here. The format follows
|
||||
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). At release time, `## Unreleased`
|
||||
is promoted to the new version and `main` is tagged `vX.Y.Z`.
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Fixed
|
||||
- **Loot-bag beacon never appeared** — the owner's beacon remote fired the same frame the bag was
|
||||
created, so the Instance reference arrived as `nil` on the client (not yet replicated) and the
|
||||
beacon silently skipped. The fire is now delayed a beat past replication.
|
||||
- **Looting while dead** — a dead player could scoop their own bag from the corpse before
|
||||
respawning, defeating the corpse-run. The server now rejects collectors who aren't alive.
|
||||
|
||||
## 0.7.1 — 2026-07-06
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -113,6 +113,12 @@ local function collect(bag: Instance, player: Player)
|
||||
if looting[player] then
|
||||
return
|
||||
end
|
||||
-- Dead players can't loot — the corpse falls right next to the bag, and a quick E while dead
|
||||
-- would scoop everything back before the respawn corpse-run even begins.
|
||||
local hum = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
|
||||
if not hum or hum.Health <= 0 then
|
||||
return
|
||||
end
|
||||
looting[player] = true
|
||||
|
||||
local entries = {}
|
||||
@@ -262,9 +268,15 @@ local function dropBag(player: Player, position: Vector3)
|
||||
Hooks.run("lootbag:dropped", ctx)
|
||||
EventBridge.fire("lootbag:dropped", player, { position = position, items = total })
|
||||
|
||||
-- Owner-only client juice: beacon + "your things dropped" toast.
|
||||
-- Owner-only client juice: beacon + "your things dropped" toast. The beacon fire is DELAYED a
|
||||
-- beat — the bag was created this frame, and an Instance sent before it replicates arrives as
|
||||
-- nil on the client (the beacon would silently never appear).
|
||||
if cfg.OwnerBeacon ~= false then
|
||||
Remotes.event("LootBagDropped"):FireClient(player, bag, lifetime)
|
||||
task.delay(0.5, function()
|
||||
if bag.Parent and player.Parent then
|
||||
Remotes.event("LootBagDropped"):FireClient(player, bag, lifetime)
|
||||
end
|
||||
end)
|
||||
end
|
||||
Remotes.event("Notify"):FireClient(player, {
|
||||
kind = "death",
|
||||
|
||||
Reference in New Issue
Block a user