Make a week of playing always pay: Vault Fragments - #199
Merged
Conversation
Old Paper and the Golden Key were pure 16% rolls on rare containers, capped one per wallet per week. That produced two outcomes and both were bad. A lucky player got both on day one and had nothing to do for six days. An unlucky one ground all week and went home with nothing — and a week of effort that paid zero is not a setback, it is a reason to uninstall. It also produced the dead end that started this: reach the vault door holding only one of the two and there was no recourse at all. The rule now is that luck may shortcut the grind but effort must guarantee it. Opening an interactive container earns a fragment; twelve grants the Paper, twenty-eight the Golden Key. The 16% roll is untouched and still fires on top, so the early thrill survives — it just no longer gates the reward. What this really buys is the thing the game did not have: playing on day two now visibly purchases the day-six payout. The grant writes the SAME paperClaims/ and goldenKeyClaims/ records that /api/paper/claim and /api/goldenkey/claim already write, through the same abort-if-present transaction. So the weekly cap is enforced by the records themselves, a fragment grant racing the lucky roll for the same item resolves to exactly one winner, and /api/vault/submit honours an item earned this way without a line changing. openContainerWindow is the credit hook precisely because of what does not reach it: onOpenButtonTap routes the vault door and the sealed/premium caches elsewhere, and Decor.open() guards on this.opened, so neither the door nor a re-opened chest can farm the bar. The request carries no amount — a client that could name its own reward would not need to play. The client grants the item locally before the server answers, so a fragment grant also zeroes that run's remaining roll for the same item; without it a player could briefly hold two Papers against one claim record. Thresholds are estimated from the spawn code (max five props per room, 12% rare, northOnly types falling back to tables on side walls) at roughly 8-15 containers per bunker — about one bunker for the Paper and three for the Key. That is a reading, not a measurement, and the module says so: watch the first week and raise both if the bar fills on day one. Verified the award logic against a stubbed RTDB: grants land on exactly the threshold, exactly once, never a second time for an item already held by luck, with the lucky claim record left intact, and weeks and wallets isolated from each other.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Owner asked whether the fragment bar was crowding the loot grid, and whether earning fragments would compete with looting food and gear. Neither, as it turned out — the bar shrinks below, and lockable containers are already the best gear source in the game, so the two incentives point at the same chest. But checking the second question turned up something much worse. Decor.open() marks a prop `opened`, and updateActionButton skipped anything opened when choosing a target. So a thing could be opened exactly once, ever, whatever state it was left in. For the vault door that is the dead end the owner reported, one layer below where we thought it was. closeVaultWindow's own comment promised "the vault door stays interactive, so you can check your Paper and re-open it to enter the code" and it was simply not true: the door was already marked opened by then, so the target scan skipped it forever. Tapping the button that says BACK TO THE BUNKER — the escape hatch made prominent two PRs ago — locked the player out of the vault for the rest of the run, leaving only LEAVE WITHOUT OPENING, which ends the campaign. For containers it destroyed loot. Close the window with slots untaken, which on a phone is one mis-tap, and that loot was gone with nothing said. _canReopenDecor now keeps the vault door permanently re-targetable, and keeps a container re-targetable while it still holds untaken slots, where the button reads REOPEN. Closing a container with loot inside says so in the run log, since a player who closed by accident has no other way to know anything is still in there. Neither is farmable. rollLootSlots memoises on this.lootSlots, so a reopened container shows the same remaining slots rather than a fresh roll, and the vault fragment moved out of openContainerWindow — which is now also the reopen path — into the first-open branch of onOpenButtonTap, where reaching the line at all means open() returned true. The vault door and the sealed/premium caches take earlier branches and never earn one. Bar shrunk to a single line as asked: label, count, hairline track, and the how-to-earn sentence moved to a title attribute. 62px to 34px, measured in headless Chromium at 390px wide — about half an item cell.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First item from the
GAME-DESIGN.mdbuild order. No contract changes — Firebase and the engine only.The problem
Old Paper and the Golden Key were pure 16% rolls on rare containers, capped one per wallet per week. Two outcomes, both bad and both common:
It also produced the dead end that started this whole thread: reach the vault door holding only one of the two, and there was no recourse at all.
The rule now
Luck may shortcut the grind; effort must guarantee it.
The 16% roll is untouched and still fires on top, so the early thrill survives — it just no longer gates the reward.
What this really buys is the thing the game did not have: playing on day 2 now visibly purchases the day-6 payout.
How it stays safe
The grant writes the same records the old path did.
paperClaims/andgoldenKeyClaims/, through the same abort-if-present transaction/api/paper/claimand/api/goldenkey/claimuse. So the weekly 1-per-wallet cap is enforced by the records themselves, a fragment grant racing the lucky roll for the same item resolves to exactly one winner, and/api/vault/submithonours an item earned this way without a line changing.openContainerWindowis the credit hook because of what does not reach it.onOpenButtonTaproutes the vault door toopenVaultWindowand the sealed/premium caches tograntCacheLoot, so neither can farm the bar.Decor.open()guards onthis.opened, so a container cannot be credited twice.The request carries no amount. The client reports "a container was opened"; the server decides what that is worth. A client-supplied quantity would let anyone mint the weekly reward in one request.
No double-award on the client either. The engine grants the item locally before the server answers, so a fragment grant also zeroes that run's remaining roll for the same item — without it a player could briefly hold two Papers against one claim record.
Where the player sees it
On the thresholds
12 and 28 are estimated from the spawn code, not measured: max 5 props per room, 12% rare,
northOnlytypes falling back to tables on side walls → roughly 8–15 interactive containers per bunker. That puts Paper at about one bunker and the Key at about three.lib/server/vault-fragments.tssays so in a comment, in as many words: watch the first week and raise both if the bar fills on day one.Verification
Award logic checked against a stubbed RTDB — all passed:
Plus:
tsc --noEmitclean ·next buildpasses (/api/vault/fragmentsregisters ƒ) · lint 34 errors, unchanged frommain· engine parses and minifies ·check:market,audit,check:copy,check:cssvarsall pass.Not verified: how the thresholds feel in real play, and the bar's look on a real phone.
Docs
GAME-DESIGN.md§5.1 flipped[TARGET]→[TODAY]per its own rule, with the container list corrected (plaque_coinwas missing — it is interactive too).game-mechanics.mdgains a player-facing explanation.Generated by Claude Code