Give the vault door a way out, a keypad, and the project's own colours - #197
Merged
Conversation
Three things the owner hit at the sealed vault door in Bunker 5, and one sizing bug found in the same pass. The dead end. A player carrying the Golden Key but not this week's Paper opened the door, found an empty code box, and read the screen as having no exit but quitting the game. Both exits were in fact already there — they were just invisible: this window borrowed #containerWindow's cream parchment theme, and .ghost-btn is `color:var(--green)`, so neon green on #e9e2d0 rendered "back to the bunker" and "leave the bunker" as barely legible ghosts. The window now says up front which of the two weekly items the wallet actually holds, what the missing one is for, and where both drop; and both buttons are spelled out, the irreversible one in the warning tint. Ownership is read from the same weekly claim records /api/vault/submit gates on, so the line cannot disagree with the submit result — and it is display only, since a missing-items submit is rejected server-side without spending an attempt. The keyboard. Tapping the code field opened the phone's own keyboard, which covers half the screen, re-lays out the overlay and stalls visibly on a mid-range Android. The field is readonly with no autofocus now and a 12-key pad drives it, so nothing native ever opens. Desktop still types normally — a window-level handler takes digits, Backspace and Enter while the window is up, since the field is never focused. The colours. Black and dark green, the project's own, with the vault's violet kept only as a rim accent so the door still reads as special. The window scrolls and centres via auto margins rather than the inherited align-items:center, which would have cut off the top of an overflowing card, and the whole thing now fits a 360x640 without scrolling at all — which is the size the exits most need to be visible at. The Supply Crate. It drew at 34x34 next to 42x54 stacked crates and a 46x56 barrel stack, and resizing it was not just a def edit: procedural props are drawn at hardcoded pixel coordinates, so def.w/def.h only ever moved its hitbox. Adds an optional drawScale applied inside the same transform as shape(), its tint mask and the hit flash, and sizes the crate's footprint to match what is now on screen.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
0xward
added a commit
that referenced
this pull request
Jul 30, 2026
Owner played on MiniPay, entered Bunker 1 floor 1, and could not move out of the spawn area — could not test anything else at all. Reproduced by flood-filling from the spawn across generated floors, using the engine's own wall test and its own NS_solidDecorAt footprint: crate 44x44, as I shipped it in #197 .... 5 sealed in 60 crate 34x34, as it was before ........... 2 sealed in 60 no decor at all ......................... 0 in 100 So this is partly mine. Widening the crate to 44 to match its new art also widened its collision footprint — decorSolidAt reads def.w directly — and that took a latent bug from uncommon to hit-on-first-play. But shrinking it again would only hide it. A corridor is one tile (40) and the player's radius is 14, so anything with a solid footprint over 12px seals one, which is every prop in the game. spawnDecorInto keeps props off doorways and hugging room walls, yet a room with a narrow exit, or two props either side of a gap, still closes the last opening. Hence a guarantee instead of a size. _ensureFloorTraversable runs at the end of ensureFloor: walk the floor from the spawn, and if the lift cannot be reached, delete whichever props sit on the frontier of the reachable region and walk it again. That is the minimal set that can be responsible, so it settles in a pass or two and rarely drops more than one prop. Vault doors and sealed/premium caches are never removed — they are content, and they sit inside rooms rather than in doorways. The footprint test is now one function used by both the live collision check and the generation-time guarantee, so the two cannot drift on what counts as blocking. Two measurement mistakes worth recording, because both produced confident wrong answers on the way here. The first check demanded the player reach the lift's exact pixel, which is usually wall-adjacent and unreachable for a 14px body, so it called walkable floors sealed. And the first fix probed only a blocked cell's centre when deciding which prop was guilty, while the walk had probed the body's edges too — it kept concluding there was nothing to remove on 2 floors in 100. 0 in 150 after the fix, across every depth. Kept as npm run test:traversable so this cannot come back the next time a prop is resized.
0xward
added a commit
that referenced
this pull request
Jul 30, 2026
) Owner played on MiniPay, entered Bunker 1 floor 1, and could not move out of the spawn area — could not test anything else at all. Reproduced by flood-filling from the spawn across generated floors, using the engine's own wall test and its own NS_solidDecorAt footprint: crate 44x44, as I shipped it in #197 .... 5 sealed in 60 crate 34x34, as it was before ........... 2 sealed in 60 no decor at all ......................... 0 in 100 So this is partly mine. Widening the crate to 44 to match its new art also widened its collision footprint — decorSolidAt reads def.w directly — and that took a latent bug from uncommon to hit-on-first-play. But shrinking it again would only hide it. A corridor is one tile (40) and the player's radius is 14, so anything with a solid footprint over 12px seals one, which is every prop in the game. spawnDecorInto keeps props off doorways and hugging room walls, yet a room with a narrow exit, or two props either side of a gap, still closes the last opening. Hence a guarantee instead of a size. _ensureFloorTraversable runs at the end of ensureFloor: walk the floor from the spawn, and if the lift cannot be reached, delete whichever props sit on the frontier of the reachable region and walk it again. That is the minimal set that can be responsible, so it settles in a pass or two and rarely drops more than one prop. Vault doors and sealed/premium caches are never removed — they are content, and they sit inside rooms rather than in doorways. The footprint test is now one function used by both the live collision check and the generation-time guarantee, so the two cannot drift on what counts as blocking. Two measurement mistakes worth recording, because both produced confident wrong answers on the way here. The first check demanded the player reach the lift's exact pixel, which is usually wall-adjacent and unreachable for a 14px body, so it called walkable floors sealed. And the first fix probed only a blocked cell's centre when deciding which prop was guilty, while the walk had probed the body's edges too — it kept concluding there was nothing to remove on 2 floors in 100. 0 in 150 after the fix, across every depth. Kept as npm run test:traversable so this cannot come back the next time a prop is resized.
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.
Three things the owner hit at the sealed vault door in Bunker 5, plus one sizing bug found in the same pass.
1. The dead end (the real bug)
A player carrying the Golden Key but not this week's Paper opened the door, found an empty code box, and read the screen as having no exit but quitting the game.
Both exits were in fact already there — they were just invisible. This window borrowed
#containerWindow's cream parchment theme (#e9e2d0), and.ghost-btniscolor:var(--green). Neon green on cream rendered "close (check Paper)" and "leave the bunker" as barely legible ghosts.Fixed on both sides:
✓ PAPER/✗ GOLDEN KEYchips), what the missing one is for, and where both drop.▾ BACK TO THE BUNKERandLEAVE WITHOUT OPENING →— with the irreversible one in the warning tint, since it is what ends the last bunker and rolls the ending.Ownership is read from the same weekly claim records
/api/vault/submitalready gates on (paperClaims/andgoldenKeyClaims/), so the line can never disagree with the submit result. It is display only: SUBMIT stays enabled either way, because a missing-items submit is rejected server-side without spending an attempt, so a slow or unreachable status check can never lock anyone out of a code they legitimately hold.2. The phone keyboard
Tapping the code field opened the OS keyboard, which covers half the screen, re-lays out the overlay and stalls visibly on a mid-range Android — reported as the game feeling like it hung.
The field is now
readOnly/inputMode="none"with no autofocus, driven by a 12-key in-game pad, so nothing native ever opens. Desktop still types normally: a window-levelkeydownhandler takes digits, Backspace and Enter while the window is up, since the field is never focused.3. The colours
Black and dark green — the project's own palette — with the vault's violet kept only as a rim accent so the door still reads as a special container rather than another looted cabinet.
The window scrolls and centres via auto margins rather than the inherited
align-items:center, which would have cut off the top of an overflowing card and made it unreachable. With the copy tightened and the two exits sharing a row on phones, the whole thing fits a 360×640 with no scrolling at all — which is the size the exits most need to be visible at.scrollHeight640 =clientHeight640)4. The Supply Crate
Circled by the owner as "too small". It drew at 34×34 next to 42×54 stacked crates and a 46×56 barrel stack.
Resizing it was not just a def edit: procedural props are drawn at hardcoded pixel coordinates, so
def.w/def.honly ever moved its hitbox — which is why the earlier pass at this same complaint could only fix the ambient crate stacks (those are sprites, sized fromdef.h). Adds an optionaldrawScaleapplied inside the same transform asshape(), its tint mask and the hit flash, and sizes the crate's footprint to match what is now on screen.Verification
tsc --noEmitcleannext buildpassesnext lint— 34 errors / 3 warnings, unchanged frommain(all pre-existingreact/jsx-no-comment-textnodes)npm run check:copy— no banned MiniPay copy, no connect-wallet prompt, no message signingnpm run check:cssvars,npm run audit,npm run check:attribution— all passNot verified from here: the crate's on-screen size at 1.3× and the keypad's feel on a real phone — both want a look in-game.
Generated by Claude Code