Engine: quest overrides with objective*/reward* fields on nested code quests
now WARN at boot (they merge nothing — QuestData prefers nested tables);
EngineConfig + ConfigAdmin reject non-finite numbers (inf/nan).
Plugin: Config group panels auto-size (fixed-height math clipped the last row
of big groups — Theme group lost its Bold font row); Stats panels get the gap
math right; the Engine Config explainer page now REBUILDS the window when the
engine appears (the old hint was impossible — pages were assembled once at
plugin load); create() refuses ids that already have an override (mirror
guard); failed Create/Override reasons render under the create row; rejected
config edits report in the footer; explicit navigation cancels a pending
debounced search jump; the mount-time page restore no longer clobbers the
saved last-page setting during an engine-less session; undo/redo refresh
skips while typing in one of the plugin's own text boxes; search results past
the 50-cap no longer render empty category headers.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dying again mid corpse-run drops a second bag (old + new coexist in the world,
each on its own 5-minute timer) and re-points the owner's beacon at the new
one. Previously the OLDER bag's later despawn/looting fired the unscoped
beacon-clear and wiped the beam pointing at the newer bag. LootBags now tracks
each owner's latest bag and only its destruction clears the beacon.
docs/loot-bags.md: documented the multi-bag + beacon-follows-newest behavior.
Live-verified: two coexisting bags, beacon on the newest; looting the OLD bag
left the beacon untouched; looting the NEW bag cleared it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause: with StreamingEnabled (the new-place default), respawning away
from the death spot let Roblox evict the bag from the owner's client — the
bag looked deleted, and the local Destroying event fired, permanently killing
the beacon (server bag was fine all along).
- The bag is now a Model set PersistentPerPlayer for its owner
(AddPersistentPlayer) — it never streams out of the owner's view.
- The beacon is position-driven plain data: no Instance in the remote, so no
replication race (the 0.5s delay hack is gone) and no streaming fragility.
- The beam clears on an explicit server nil-fire when the bag is truly
emptied/expired (plus a lifetime fallback), not on replica Destroying.
Live-verified (fresh bytecode confirmed via bag ClassName): beacon appears
instantly, survives respawn, bag stays visible to the owner, loot restores
everything, beam clears on empty.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
- ToolEquip: possession gate — a pin is only a pointer; never equip an item
the player doesn't carry (a stale/seeded pin without a backing stack could
conjure a usable ghost Tool).
- Hotbar UI: dim a pinned icon to 0.45 (the Crafting-tab convention) when the
player owns none of the item, so an inert pin reads as inert.
- Demo: husks spawn beyond aggro+wander reach of the spawn point — no more
farming fresh players before they pick up a weapon.
Verified live in Studio: a war_bow pin with zero carried refuses to equip and
renders dimmed; owned pins equip normally at full opacity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Promote CHANGELOG Unreleased → 0.7.0 and bump wally.toml. (VERSION already
0.7.0 in src/init.luau.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hunting & butchering (#13): mob defs gain flat carcass fields (carcassItem/Hp/
Tool/YieldMin/Max/Seconds); a slain mob leaves a butcherable CARCASS that is a
tagged Gatherable — the whole harvesting pipeline (tool gate, per-hit yields,
HP bar, gather:* hooks, progression counters) is reused as the butcher flow.
Carcass looks come from SurvivorCoreContent.Carcasses.<mobType>; reactions key
on "<mobType>_carcass"; fields editable in the admin Mobs editor. Gatherable
gains generic PromptText/PromptObject attributes.
Death loot bags (#19, TCE port): dying drops inventory AND worn equipment
(config-toggleable) into an anchored ground-clamped bag — IntValue contents,
instant-loot prompt for anyone, floating countdown, owner-only beacon, death
toast, LifetimeSeconds despawn. Pickup is loss-proof: equipment restores to
empty slots first (satchel re-grows capacity before stacks), the rest grants
up-to-fit and the remainder stays bagged. New player:died lifecycle → deaths
counters via Progression; lootbag:dropped/collected hooks; TCE respawn camera
fix. New Inventory APIs: getEquipment, clearAll (capacity-safe order), addUpTo,
restoreEquip.
Fixed: ToolEquip forces CanBeDropped=false on cloned creator templates.
Demo: stone_knife + raw_meat (risky raw: Hunger -25, Poison +8), boar carcass,
multi-objective hunt_boar quest, hunter/butcher/hard_way achievements. Docs:
mobs.md butchering section + loot-bags.md; CHANGELOG; site card copy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire the demo video (makertube uSGJ2MHEFjSSKxMiJBJ6Y5) into quests.md,
achievements.md, content-authoring.md and admin-plugin.md, and feature it in
the landing page's video grid (replacing the oldest embed; that video stays
linked from docs/inventory.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Promote CHANGELOG Unreleased → 0.6.0 and bump wally.toml. (SurvivorCore.VERSION
is already 0.6.0 in src/init.luau.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Quests (#10): a Quests registry + server runtime — objectives (gather/craft/
kill/use × count, blank target = any) and rewards, autoStart + requires chains
(completing a prerequisite auto-starts dependents), optional turn-in at a
tagged QuestGiver (component + prompt). Rewards are never lost: a full
inventory parks the quest as ready and the grant retries on inventory change.
Quests menu tab (L) with per-objective progress bars; QuestLog JSON attribute
replicates state; quest:started/progress/completed/blocked via Hooks + bus.
Achievements: an always-on runtime for the existing registry, ported
architecturally from TCE. A shared Progression layer translates bus events
into auto-derived counters (gathers_reed, crafts_total, kills_husk, …) so a
def is just { key, name, counter, threshold } — flat in code and no-code.
Unlock-once + toast + Achievements tab (J) with progress bars.
Toasts: themed top-right notification queue (Notify remote + Toasts.show).
No-code: admin plugin gains Quests (single-objective + "+ Quest giver" drop)
and Achievements (counter/threshold) editors; the engine loads both from
SurvivorCoreContent. Demo: a 3-quest chain + 4 achievements + a giver post.
Fixed: registerPanel now ADOPTS a template-scaffolded tab (hides the
placeholder, builds into the authored frame) instead of silently no-opping —
this replaces the Quests/Achievements "coming soon" placeholders.
EventBridge parity: gather:*, craft:* and item:use now also cross the bus.
Changed: rojo 7.6.1 → 7.7.0 (rokit pin; CI follows; gate verified).
Docs: quests.md + achievements.md (new), content-authoring/admin-plugin/
extending/README updated, CHANGELOG Unreleased, site feature card.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>