Commit Graph
23 Commits
Author SHA1 Message Date
jwinterm 75b0f7acfb fix(render): Original pack uses the game's REAL original tileset (tiles.png)
The `original` pack was built on the Kenney sheet, so it didn't match the classic look the
ROT instructions + waiting screens use. Point it at html/tiles.png (32px, the legacy
tileMap sheet) with grid coords = legacy pixel coords / 32: floor [0,0], wall [2,1], door
[1,0], torch [32,1], treasure [30,0], plus the classic @ hero [2,0] and ~ goblin [31,1].
The tiled renderer now prefers a pack's player/monster TILE over the character sprite in the
DUNGEON (tavern keeps sprites), so the Original pack is fully classic. Suite 62/435 green.
2026-07-12 11:37:51 -04:00
jwinterm 42ed51af69 feat(monetization): lock the cosmetic ladder (loyalty model) + free Original pack
Nails down the premium unlock system per the design pass:
- FREE `original` topdown pack (NEW): the game's bare tiles — floor/wall/door/
  torch/features only, no furniture, so the free tavern reads plain (the intended
  "reason to unlock"). Registered in assetPacks (RK.THEMES.original) as the free
  default topdown pack; plain ASCII stays free (accessibility).
- Loyalty ladder (lifetime credits PURCHASED, cumulative, NOT deducted → buying to
  play also unlocks cosmetics): Interior 1, skins 5, iso 10, +tilepack 20, +iso 40,
  3D 50. Each row is data (tilepack OR skin) → operator appends more at any rung.
  DEFAULT_CATALOG (entitlements.js) + migration 028 + MONETIZATION.md ladder table.
- Tests updated to the new thresholds (catalogEntitlements_ultra, directEntryCredit_ultra).

Note: this reprices roguelike-interior from free → 1cr, so once deployed the free
tavern becomes bare (by design). Deploy is bundled with the single-player render-kit
migration so the free-tier change lands with its payoff. Suite 61/432 green.
2026-07-12 09:52:13 -04:00
jwinterm 4d673748df feat(iso): orientation-aware walls + floor variety + juice (shadows/vignette)
Fixes the "thin disconnected slabs" on the top-left/bottom-right walls and juices
the iso scene:
- Wall facing: iso walls have an orientation. A run along grid-x uses the _S
  rotation, a run along grid-y uses the perpendicular _W (I viewed the tiles:
  _S faces SW, _W faces SE — the two camera-facing rotations), and true corners
  use the corner tile. The renderer picks per-cell from neighbours. Enclosing
  walls now read as continuous faces on all four edges. Same logic gives
  windows/doors a Y rotation.
- Floor variety: deterministic per-cell hash sprinkles planksBroken into wood
  floors and stoneTile/stoneUneven into stone — no more flat identical sea.
- Juice: soft contact shadows ground every prop + character, and a warm radial
  vignette lights the room instead of it looking pasted onto black.
- Tavern map: barrels/crates line the side walls (clear of windows/spawn, via
  the wall-safe put()) so the lobby reads lived-in in every render mode.

Suite 58/419 green.
2026-07-11 15:11:26 -04:00
jwinterm be8594282b feat(iso): rich Kenney Isometric Dungeon set + correct facing + ASCII picker
A — RICH ISO. The old iso-dungeon was a 7-tile sliver of Kenney Isometric
Dungeon; wire the full set so town/dungeon are RICH and interchangeable:
- Real architecture: full stoneWall, stoneWallWindow (actual window),
  stoneWallDoorOpen (real door), archway, wood column, stairs.
- Distinct furniture per kind: table -> tableShortChairs (table+chairs),
  keg/barrel -> real barrel, crate -> woodenCrate, shelf -> woodenCrates,
  chest -> chestClosed (added to the floor+prop compositor). No more
  everything-is-a-chest.

Facing (was 90 deg off, twice): verified against live movement the sprites are
angled CLOCKWISE from NE (0=NE,2=SE,4=SW,6=NW), so up->Male_0, right->Male_2,
down->Male_4, left->Male_6. Now the run anim points the way you actually move.

ASCII picker no-op: ASCII draws glyphs and consumes no tile pack, so
projForMode(ascii)=null and the packbar hides for it (it only ever made sense
for Tiled/Iso).

Suite 58/419 green.
2026-07-11 14:53:24 -04:00
jwinterm ccaff7d29c feat(packs): Fancy dies as a mode → topdown packs; Roguelike Dungeon tile pack (B)
Modes are TECHNIQUES; 'Fancy' (tiles+FX) was really a topdown PACK, so:
- Remove 'fancy' from RENDER_MODES (saved 'fancy' falls back to tiles; its dead
  Pixi branch is short-circuited by canUseMode). Modes = Tiled/ASCII/Iso/3D.
- Modes now carry a ; a premium mode unlocks once the user has ANY
  unlocked pack for that projection (not a single hardcoded pack) — needed now
  that iso is multi-pack.
- New 'roguelike-dungeon' topdown pack: same sheet, a DUNGEON palette (stone
  floors + barrels/crates vs the wood interior) — a distinct 2D tileset with zero
  new assets. Registered + catalog (migration 027, topdown tier 1 / 1 credit).
  The tiled renderer's lighting/shadows/vignette are the built-in FX.
- Also: iso facing fix (Male 0=NW..6=NE) reflected in tests.

So the Tiled pack picker now offers Roguelike Interior <-> Dungeon, and Iso offers
Dungeon <-> Medieval — packs as products, proven in the best-looking mode too.
Suite 58/419 green.
2026-07-11 14:35:30 -04:00
jwinterm 4a91d91822 fix(iso): face the direction of visual movement (Kenney 45deg renders 0=NW..6=NE)
Male_0..7 are 45-degree renders (viewed: 0=NW, 2=SW, 4=SE, 6=NE). In this iso
projection grid up->NE, down->SW, left->NW, right->SE, so map facing to the visual
movement direction. Applies to both iso packs (shared characters).
2026-07-11 14:16:10 -04:00
jwinterm 3d9b5420ee feat(packs): Medieval Town iso pack (2nd iso environment) + pack picker
Proves the packs-as-products loop end to end:
- Copied Kenney Isometric Medieval Town wood tiles (floor/floor2/wall/window/
  door/banner) into assets/kenney/iso-medieval/.
- Registered 'iso-medieval' as a 2nd iso RENDER pack (its own tile geometry —
  Medieval tiles are shorter than the dungeon set; reuses the dungeon characters).
  Strong on architecture; no medieval furniture at this scale, so furniture kinds
  fall back to floor for now (shines most in the dungeon).
- Catalog product: DEFAULT_CATALOG + migration 026, iso tier 2 / 15 credits.
- PACK PICKER in the tavern: when a projection has >1 unlocked pack, a selector
  appears to switch live (setActivePack -> re-render). Uses ?unlock=1 to preview.

So: switch Iso ★, and the pack picker lets you flip iso-dungeon <-> Medieval Town
live. Adding the next pack = assets + registerPack + a catalog row. Suite 58/419 green.
2026-07-11 13:57:47 -04:00
jwinterm 11b7fb1272 feat(render): pack registry — multi-pack, interchangeable render environments
The engine behind 'add more 2D tilesets / iso packs / 3D skins as products'. A
pack is a self-contained render environment for a projection (topdown/iso/3d);
because scenes are kind-based, the SAME pack renders both town and dungeon
(interchangeable), and each maps to a catalog id (monetizable, entitlement-gated).

- packRegistry.js: registerPack / packsForProjection / unlockedPacks (canUsePack)
  / activePackId (saved-if-unlocked else first unlocked) / setActivePack /
  activePackAssets. Per-projection active-pack selection, persisted. In-memory
  store fallback so it's testable under Node.
- assetPacks: registers the 3 built-ins (roguelike-interior topdown, iso-dungeon,
  kenney-3d-characters) + activeIsoAssets()/activeThreeAssets() resolvers; RK.theme()
  now defaults to the active topdown pack.
- isoRenderer + avatarVisuals (iso/3d character lookup) read the ACTIVE pack.
- packRegistry loaded before assetPacks in tavern + game.

Backward-compatible: one pack per projection resolves to today's defaults — nothing
changes visually. Adding a pack now = registerPack(...) + assets + a catalog row.
Tests: +5 (register/list, unlock filter, active/saved/fallback, refuse locked).
Suite 58 suites / 419 tests green.
2026-07-11 13:40:29 -04:00
jwinterm 6d0334f4f2 feat(iso): furniture props in isometric mode (bar/kegs, tables, chairs, barrels)
The iso renderer only drew floor+wall (bar/table hardcoded). Generalize the
floor-base + prop compositing to all furniture kinds (bar/table/chair/keg/shelf/
barrel/crate) and map them to the iso-dungeon tiles: stacked barrels = the bar +
kegs, chest = tables/crates/shelves, chair = chairs. Half walls kept (full walls
would occlude the front row). Same coherent iso-dungeon art set. Client-only.
2026-07-11 12:57:11 -04:00
jwinterm 6a2010a023 fix(tavern): use the wooden table tile (191), not the green one (312) 2026-07-11 07:08:42 -04:00
jwinterm 24e738c733 feat(tavern): proper tavern — real bar, kegs, bottles, tables+chairs, windows, rug
Used the sheet's hand-labelled roguelikeSheet_meta.json to pick the RIGHT tiles
instead of guessing:
- New tile kinds + coords (window, counter, keg/barrel, shelf, table, chair,
  crate, rug, door) in sceneModel TAVERN_LEGEND/TILE_OF + assetPacks tileMap.
- tavernMap redesigned: windowed walls, a bar counter with a shelf of bottles
  behind it and a keg (beer!) at each end, six tables each with a chair, a
  central rug, corner barrels/crates, and a door. Chairs are walkable so standing
  on one reads as sitting. Warm wood floor color (was a dark green in the fallback).
- Bartender now stands BEHIND the bar (spawn + roam confined to the row between
  the top wall and the counter, sealed off by it).

Still TODO from feedback: a cat (no cat sprite on the sheet — needs an asset) and
richer bar bottles. Suite 57 suites / 413 tests green.
2026-07-11 06:50:05 -04:00
jwinterm 3f12d8f047 feat(credits): client consumes served catalog; direct entry counts as a credit purchase
① assetPacks.js merges the server-authoritative catalog (from the entitlement snapshot) into RK.PACKS — operator-added packs now appear client-side and existing packs pick up server definitions, retiring the client half of the split-brain. ② A confirmed direct/single_game payment now records as 'buy 1 credit + spend it': balance nets to zero but total_credits_purchased advances (recordDirectEntryPurchase), so direct play unlocks the same tier/threshold cosmetics as buying credits, and the client gets a fresh entitlement snapshot. +2 tests. Suite 49/345 green.

P1 foundation (branch feat/credits-catalog-foundation). Remaining: the buy modal reflects the unified credits model; a later pass can fully collapse single_game into the credit spend path.
2026-07-10 16:28:31 -04:00
jwinterm a05a10efd7 fix(ui): tavern floor, play-area focus border, and Smirk locked-wallet UX
Tavern: revert the per-cell 'varied floor/wall' tiles to coherent single tiles — mixing wood/stone/plank per cell read as visual noise (assetPacks.js).

Play area: draw the keyboard-focus outline inset (outline-offset -2px) so the yellow border shows on the right edge, which the container's overflow:hidden was clipping (ui.js).

Smirk: a locked wallet now shows a friendly 'unlock in the extension, then Retry' hint instead of a red error, and the LOCKED error code is preserved through connect()/signMessage(). Current Smirk builds auto-open the unlock popup on connect(); older builds throw LOCKED, which the Retry button re-invokes (smirkAuth.js).
2026-07-10 08:46:38 -04:00
jwinterm a62eefb47b fix: resolve security/correctness review + AAA graphics pass
Backend (Tier 0/1/3): single-payout double-pay -> needs_review; admin-retry tx_hash guard; UNIQUE index on games.payment_id (migration 023) + atomic claim; reconnect no longer resets block-timeout; completeGame keys on user_id+dungeon_seed (not socket_id); token-gated /api/user/:socketId/* endpoints; payout min/max enforcement; orphaned-active-game boot recovery; sessionManager cleanup FK fix; XFF rightmost-hop; global uncaughtException/unhandledRejection guard; server binds 127.0.0.1; provably-fair client-seed (HMAC) + RNG [0,1) bound; difficulty preset ranges reach the digger; chat no longer leaks full socket.id; removed dangerous-keyword SQL theater.

Match mode (Tier 2, still MATCH_ENABLED-gated): fixed match_queue/match_move crash paths + scheduler dead-code + leaked ceiling timer; pot collected before start with abort+refund; BigInt/basis-point fee math, capped payout; no-address winner claimable; winnerId==placement[0]; finalize schema + payout-first isolation; reconnect re-key with ownership; refunds on all cancel paths; real countdown; map/timer cleanup. +16 tests.

Graphics: new overlay FX layer (torch light, vignette, embers, sparkle/burst/flash/shake, self-suspending rAF); gameplay juice; atmospheric screens; CSS design-token chrome with framed modals; richer Kenney tile renderer; imported Kenney dungeon/interior sheets + fx particles.

Verification: 45 suites / 312 tests pass; 40 changed JS files parse; 20 server modules load clean; no regressions.
2026-07-09 17:46:58 -04:00
jwinterm 8fa8b06b20 feat: lively tavern (NPCs + speech bubbles), spectator camera, dungeon render adapter
- tavernLife.js: client-side NPCs (bartender, patrons, cat) with autonomous
    movement, random speech bubbles, and real-player chat bubbles
  - T2b: spectator camera — watch live dungeon runs from inside the tavern
    (game list, spectate_start/update, ESC to leave)
  - R1: sceneFromGameState adapter — converts dungeon game state to render-kit
    Scene with lighting grid and entity mapping
  - R2: pre-populated Kenney roguelikeSheet tile defaults for the tiled renderer
  - Dungeon renderer support: TileRenderer + AsciiRenderer handle lightGrid,
    dungeon features/items/monster entities
  - 3 new tests (242 total, 36 suites, all passing)
2026-07-09 06:31:35 -04:00
jwinterm 4ee03f24a6 fix: char customizer flakiness + wire real render-mode entitlement gating
- Equipment option tiles register for async redraw (were stuck on '...')
  - Render mode switching no longer silently mutates avatar identity
  - Dungeon renderer falls back to @ tile when overlay draw fails
  - Main-game customizer locked to topdown (no confusing render-mode picker)
  - equipRedrawers prevents unbounded redraw array growth
  - RENDER_MODE_TEST_UNLOCKS flipped to false; ASCII made free (accessible fallback)
  - Documented COSMETIC_PRODUCTS in .env.example
  - 5 new tests (239 total, 36 suites, all passing)
2026-07-09 06:15:00 -04:00
jwinterm fa18e99a94 correct iso avatar customization 2026-07-06 07:26:12 -04:00
jwinterm 49ea01606e fix designed-room iso character rendering 2026-07-06 07:04:26 -04:00
jwinterm f505a4fb8a make character customization projection aware 2026-07-06 06:38:19 -04:00
jwinterm c89c01e5f1 improve gear tinting and unlock render tests 2026-07-06 04:38:28 -04:00
jwinterm cb9efbe66c refactor: route render packs through avatar visuals 2026-07-06 03:53:13 -04:00
jwinterm 07cfe80591 feat: improve character customization colors 2026-07-05 21:09:52 -04:00
jwinterm 454e6ab69a feat: add tavern render kit and character entitlements 2026-07-05 20:57:46 -04:00