Compare commits

..

36 Commits

Author SHA1 Message Date
m3ultra
91a27b56a4 A contact sheet, and the luminance ceiling the pipeline never had
127 sprites had been generated and about eight had ever been looked at. The
pipeline will happily render the wrong object, confidently and well-lit, and no
assertion can tell — barrier and flightCase are both "a grey box with edges" as
far as any test goes. tools/gen/contact_sheet.py puts every shipped sprite on one
page at integer upscale on the venue's own floor colour. It immediately showed
about twenty props reading as pale blobs.

First instinct was that the vertex baker had lost the albedo. That was wrong:
sat=0 on ashUrn, marbleSink and pillar is honest, because stainless and marble
and concrete really are grey. The fault was BRIGHTNESS. Props that read sit at
median luminance 23-123 (patioHeater 23, arcade 45, poolTable 53, cdj 68); the
blobs were 150-190. The venue is painted at ~35 under a 50% black sheet and props
are lit by the room's own LIGHTS, so a prop arriving at 180 doesn't read as a
bright object — it reads as self-illuminated. Every prop that worked before
worked by accident of subject matter; the first pale subjects exposed the gap.

props_import --dim scales RGB until median opaque luminance is <=110. Only ever
darkens, so anything already in band passes through untouched. Fixed 48 sprites
with no regeneration at all — the 512px Blender renders were still in
art_incoming, which is exactly why that directory is kept.

Also: poster7 shipped with 29% of its pixels and poster9 with 42%, because the
near-black-to-alpha pass was eating the dark half of a dark poster. Posters are
rectangular plates on a wall, so 4-9 now keep their background and fill the frame.

And cf_flux --probe was reporting EXHAUSTED on an account with a full 10,000
neurons: the probe prompt was "a grey square", Cloudflare's safety filter refused
it as NSFW, and every non-429 fell through to SystemExit. A health check that
can't tell "refused" from "empty" will eventually call a healthy system dead.

Gate: lint clean, build clean, 821 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 10:19:32 +10:00
m3ultra
4ee4cf343b The door stops being 28 rectangles
The rope is where the player spends most of the night and it was still coloured
primitives behind a single street plate.

- kebabShop: the moral centre of the game (design §5) was three rects and the
  word KEBABS. The warm spill on the footpath stays procedural — it is the only
  warm light in the scene and it is what says the shop is open.
- front:<venueId>: one facade per rung of the ladder, so a promotion is visible
  from the footpath. ROOM also loses the procedural NOT TONIGHT sign, because
  "no sign. no socials." is its actual entry in data/venues.ts.
- Footpath: a street lamp, a bin, a waiting cab, and brass stanchions on the
  carpet. The cab is alpha'd back and depth-1 so it never looks clickable next
  to the kebab shop, which is.
- poster4..poster9, so four venues stop sharing one wall of three. Mangled
  lettering is correct on posters and always has been.

And a composition bug I put in this same wave: the per-venue street plates were
first prompted as "frontage", so The Royal's backdrop was a whole pub with its
own central door and the venue facade then sat on top of it — two pub fronts,
two doors. Voltage's original plate has always been a WALL, which is what a
backdrop has to be. Re-prompted all three as blank walls and regenerated. No
test would have caught that; I found it by looking at the screen.

127 sprites now, none missing.

Gate: lint clean, build clean, 821 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:10:02 +10:00
m3ultra
e0ead6698b Handover: wave 2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 23:19:54 +10:00
m3ultra
67a5d8cf58 Twenty-six more: the rooms are furnished and the floors have grain
Wave 2 lands complete — 26/26, no failures. 112 sprites in public/props, and
every one of the 91 prop kinds and 10 materials the four venues reference has
art. Nothing anywhere renders as a placeholder.

Ten material plates (carpet, concrete, deck, parquet, looTile, paving, plaster,
brick, timber, steel) and sixteen props: the filler for The Royal's central
carpet and ROOM's east hall, the fire kit and signage every venue now carries,
and two more staff figures.

Gate: lint clean, build clean, 821 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 23:18:59 +10:00
m3ultra
74cbd71ad3 Materials, and the floor-cache bug that would have eaten the promotion
Two things, one of them a real bug.

THE BUG: bakeTiles baked to a single global 'floor:tiles' and early-returned if
that key existed. Textures outlive a scene, so the first venue you played baked
the floor for every venue after it — you would survive a week at The Royal, get
promoted, walk into Voltage and still be standing on the pub's carpet. It only
shows on promotion, which is exactly the moment the venue ladder is supposed to
pay off, and never in a dev route because those reload the page. The baked
texture is now keyed per venue; verified by switching venues inside one session
and watching the concrete arrive.

MATERIALS: FloorLayout.materials names a generated plate per tile kind and the
baker stamps it TINTED to the palette colour. The plate carries grain, the
palette keeps hue — an untinted photo-real plate blows straight past the
brightness band the whole room was tuned in, and darkness is the mechanic.
Plates are 16x16, the game's own tile, because at that size "carpet" is
structured noise, which is also what pub carpet looks like from head height.
Ten of them: carpet, concrete, deck, parquet, looTile, paving, plaster, brick,
timber, steel. No plate named, or art not landed, falls back to flat colour
exactly as before.

Wave 2 filler for the two spaces the review found genuinely empty — The Royal's
central carpet (four props across ~500 tiles) and ROOM's east hall (~23% of its
interior with no lights and three props) — plus the kit every real room has and
no game room does: fire extinguishers, exit signs, CCTV, bins, a notice board,
ceiling fans. Voltage gets the same pass; being the reference room is how it
quietly missed the last one.

The invariant caught a duplicate prop id I introduced while placing these, which
is what it is for.

Also relaxed one ROOM assertion that keyed on array order: it checked that the
FIRST sodium light stands over the loading dock, which broke the moment the east
hall legitimately burned the same colour. It now checks that one of them does.

Gate: lint clean, tsc clean, 821 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 21:56:20 +10:00
m3ultra
7225eed349 Forty-eight sprites: every prop in every room is real art now
37 generated props -> 86. Every one of the 76 prop kinds placed across the four
venues has a sprite; nothing renders as a placeholder.

tools/gen/ is the pipeline: assets.py is the manifest (one entry per sprite —
prompt, ship size, rake, route), run_batch.py walks it, resumable, --workers N.
Cloudflare Workers AI first for its 10k free daily neurons, falling back to
MODELBEAST flux_local automatically. Today's allocation was already spent when
the run started — confirmed from Cloudflare's own error body rather than assumed
— so this batch is entirely farm-rendered.

The mesh tier is the part worth keeping: TRELLIS's defaults (1024_cascade + a
2048px metal PBR bake) cost 5-12 minutes each on a queue that runs one gpu job
at a time, which is four hours for a tileset. mb.FAST_MESH (512 + vertex baker)
lands in ~90s, and A/B'd at ship size the difference does not survive the
downscale to 32px.

Also adds the door's per-venue street plates, keyed on the venue id exactly —
'theRoyal', not a case fold, because props_import writes ':' as '_' and a
lowercased key looks for a plate nobody made.

Gate: lint clean, build clean, 821 tests passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 21:14:33 +10:00
m3ultra
22bd43857c Review pass: the room-specific bugs a shared FloorView was hiding
Three independent reviewers checked each new venue against its brief. No
blockers, all three rooms genuinely distinct — but two of the findings were
mine, in the file the layout authors were told not to touch.

FloorView was still drawing two things at Voltage's coordinates:
- The scan beams pivoted on a hardcoded (38,23) — Voltage's mirror ball. In The
  Royal that swept two beams across the empty middle of the pub, twenty-five
  tiles from that venue's dance floor. Now derived from the layout's own
  discoball, and a venue without one gets no beams, because the beams ARE the
  ball's light.
- The resident DJ stood at a hardcoded (55.5, 22.5) — Voltage's booth, which in
  The Royal is the middle of the bistro. Now placed from the venue's own gear
  and stepped clear of `posts.decks`, so a player on a DJ shift is never
  standing inside him. The beat-bob had the same constant baked into it.

Elevate's staffDj prop is dropped as a consequence: with a resident DJ derived
per venue it would have made two DJs on the plinth, and three once the player
took the shift.

New invariant: a staff prop may not stand on a post tile. Elevate's bartender
was on the exact tile the bar shift teleports the player to, so the shift would
have been played from inside her. Caught by the rule, then fixed.

`mirror` and `graffiti` kinds added. Elevate was standing BOTH its mirrors up as
`poster3` (the author raised it as a contract request and stubbed it honestly),
which would have hung the same torn gig poster in a marble bathroom and called
it a mirror. ROOM's toilets get the graffiti its brief always asked for.

The Royal: TAB screens moved onto the wall they belong on rather than floating
mid-carpet, the trough given its own fluoro (the one fixture that room is known
for was rendering unlit), the beer garden's dark middle band lit — 288 tiles on
two lights left the gate everyone walks through in the dark — the out-of-order
sign moved off the tile the queue stands on, and two comments corrected to
describe what the code actually does.

Also hardened the farm client: `_req` raised SystemExit, which is a
BaseException, so `except Exception` in the batch's worker threads did not catch
it and one stray 401 during a poll killed a 43-asset run after a single asset.
It now raises a normal error and retries transient 401/429/5xx with backoff.

Gate: lint clean, tsc clean, floor suite 271 passing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 20:01:40 +10:00
m3ultra
4caa901df2 Four venues, four rooms: the ladder stops being one map with different numbers
The venue ladder has always listed four venues in data/venues.ts, but they
shared ONE floor map and differed only by difficulty knobs — so a promotion you
survived a whole week for looked exactly like the room you had just left.

- venueMap.ts grows a FloorLayout contract (map + props + lights + posts +
  probes + palette) and the newGrid() primitives every room is painted with.
  Voltage stays IN venueMap rather than moving to layouts/, so the new rooms can
  import primitives from it without closing an import cycle.
- Three new rooms in src/scenes/floor/layouts/: The Royal (horseshoe public bar,
  pool room, pokies corner, trough + two cubicles, a beer garden that is plainly
  the nicest room in the pub, and a DJ "corner" that is a folding table because
  this pub never built a booth), Elevate (open-air rooftop — most of the grid is
  sky, the DJ is on an unwalled plinth, you arrive by lift), ROOM (concrete
  warehouse, pillars you path around, central booth, loading-dock smoking area,
  twelve lights in the whole venue).
- Nothing about a room is a module singleton any more. FloorView, sweep and
  FloorDemoScene take the layout; the door picks its street plate by venue id.
- FloorDemoScene's six hardcoded station spots (TAPS_SPOT, DECKS_SPOT, ...) were
  Voltage's tile coordinates. At four venues a hardcoded (47,3) puts the bar
  shift inside The Royal's pool room, so each layout now names its own stations
  and the scene reads them from there.
- tests/floor/layoutInvariants.ts is an executable rulebook: perimeter holds,
  every walkable tile reachable from the entry, anchors on walkable ground,
  posts not sealed (a post on a sealed tile freezes the player for the night —
  that has shipped twice), probes reachable, props on-grid. Proved against
  Voltage BEFORE the new rooms were authored against it.

Dev route #floor:<venueId> boots the floor straight into one room, because
otherwise seeing ROOM means surviving three weeks of the ladder.

Gate: lint clean, build clean, 821 tests passing (was 784).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 19:51:54 +10:00
type-two
ae036d9d0e One camera for the whole tileset: nine chunky props re-meshed and ortho-rendered
9/9 through flux product shot -> trellis2_mlx -> glb_to_sprite, unattended.
Rake corrected after the first pass: tall objects need a STEEPER angle (76), not
a shallower one — an arcade at 55 is a front-on slab. Re-angled from the meshes
already on disk, no re-generation, which is the point of keeping the GLB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 14:55:19 +10:00
type-two
433bf77a78 The [GLB] hop, closed: headless Blender ortho-render turns TRELLIS meshes into props
tools/glb_to_sprite.py completes SPACES.md's 3D route — fixed ortho camera fitted
to the mesh bounds, flat light, transparent film, straight into props_import.
A/B'd on one pool table: TRELLIS wins for objects with volume (worn felt, real
pockets, rails), flux stays for flat things. Rake is 60 not 90 — straight down
turns a fridge into a grey box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:37:36 +10:00
type-two
9b6bc6355c Furnish the empty rooms: the dunnies get fittings, the bar gets fridges, the yard gets a heater
Audit found the dunnies were the biggest room in the venue with ONE prop in it
(and a minigame happening there). Nine new kinds placed across the five thinnest
spaces. House-style note recorded: props are raked three-quarter top-down, not
strict orthographic — a fridge from directly overhead is a grey box.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-27 13:29:55 +10:00
type-two
9bc7dd1bfd Three jobs: sweep out of the god object, story beats per role, and dolls that breathe
- scenes/floor/sweep.ts: the closing sweep extracted behind an accessor host.
  Scene 2100 -> 1981 lines, behaviour verified identical.
- data/roleBeats.ts: 18 beats across 6 roles x 3 nights, landing in the venue
  group chat. The glassie is spoken about; the HoS is spoken to.
- dollPlan(p, pose, frame): 4-frame idle on the queue pose. NOT pre-rendered
  sheets — those would hide the outfit tells the dress code convicts on, which
  design 4.1 forbids; the pre-render path must go UNDER the outfit rects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 20:49:42 +10:00
type-two
195325f8f1 Role permissions: the glassie can see everything and touch nothing
authority (eject/pat-down/cut-off/busts) and stations (taps/decks) are now per
role. Gated verbs become 'radio it in' — reusing the staff competence roll, so
~2 in 3 calls bring somebody over and the rest just hang in the air. Doorgirl
keeps floor authority on purpose: that loop is the shipped game.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 20:02:54 +10:00
type-two
700bd48bcb The bar sells the room, and the inspector makes one bad pour matter
- pourAdjust pays hype: clean 0.03, heavy 0.05, short nothing. The crowd-pleaser
  is also what walks the room toward the RSA line — same lever, both ways.
  Role pay gap closes from ~$180 to $45.
- breachSeenChance(inspectorWatching): 0.35 alone, 0.9 with a lanyard in the room
  (design §6). Corrects SOLO-19: detection was never the weak part — dedupe caps
  strikes at one a night and 0.35 already saturates across several pours.
- Sim harness was missing the 3 AM audit and under-reporting late-night strikes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 19:53:25 +10:00
type-two
fbc959fde8 The report catches up: frequency-aware interest weights and eleven banks for the floor's own paperwork
A bar shift logs ~26 serves and buildReport takes the top 3 with no dedupe, so
bartender nights filed three identical generic pour questions. Weights now price
frequency as well as interest, and the loaded kinds have real questions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 19:43:06 +10:00
type-two
3dd61fef36 Sim harness: state the bar sim's coverage limits (it would not have caught the escalation-seam bug)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 21:05:02 +10:00
type-two
754f2b4767 Floor-economy sim: bot nights for the carpet and the bar — caught the carpet's uncapped hype ratchet (vibe-pin 0.27 to 0.71) and capped the trickle
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 21:03:44 +10:00
type-two
7af3732f39 Fix build break in the shoe tests: freshNightState takes (venueId, nightIndex, licensed)
vitest does not typecheck, so these passed under `npm test` while `npm run build`
failed. The gate is lint AND build AND test for exactly this reason — run it in
that order after touching tests, not before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 03:18:49 +10:00
type-two
4118a60aea Review sweep: close the softlock class with data+tests, un-deadlock the door, and make the booth shoe real money
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 03:17:39 +10:00
type-two
0d3ce80c6b Six defects from the adversarial review: two softlocks, a dead door, and a bar that punished the right call
- DJ post stood the player inside the sealed djbooth (same class as the taps
  softlock): every direction blocked, and since the sweep needs you to walk to
  the entry, the night could never be paid. DECKS_SPOT moves to the booth's west
  counter, which is where the map comment always said the gear faces from.
- Role stations are now DATA (venueMap POSTS/PROBES) with tests/floor/stations.test.ts
  pinning the whole bug class: posts must be walkable AND escapable, probes must
  have somewhere walkable within interact range. Written as a MOVEMENT test, not
  a tile-name test — the question is whether the player can leave.
- DoorScene.busy is released by a delayedCall on the scene clock, and stopping a
  scene discards pending events, so a ruling in the last 2.6s of a night left it
  stuck true: a dead door — no rope, no verdicts, no way inside — for the rest
  of the run. Now reset per night, along with seenCards/kebab/franko/retiredRules.
- Bar WATER and CUT OFF never settled the patron, so watering a maggot from
  behind the taps left them ticking as unhandled and re-logging every grace
  period: the call that fixed the problem kept being charged for it.
- Every bar verb logged as 'barServe', putting drinks in the record that were
  never poured. One kind per verb; the report system takes unknown kinds by design.
- carpetMsFor() is consumed on read: a regular parked, recalled and knocked back
  came round again later and was paid the entrance dividend a second time.
- Sweep state joins resetNightState() so an interrupted floor score cannot carry
  its cash, or its previous-night pay callback, into the next night.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 03:13:09 +10:00
type-two
bcc06c104a Handover: record the taps softlock fix
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:32:44 +10:00
type-two
3b8682dd40 Fix the run-ending softlock: handing the taps back stranded you on a stool tile
toggleTaps() teleported the player to TAPS_FRONT on exit, and TAPS_FRONT was
tile (47,6) — inside venueMap's stool rect, which is not in WALKABLE. Verified
in the live build: after handing the taps back the player sat at (760,104) and
W/A/S/D each moved them exactly 0px, for the rest of the night. The bartender
roster role mounts the taps automatically, so one keypress ended the run.

Exit no longer teleports at all: you stay behind the bar and walk out around
its east end, which is both walkable (verified end to end) and how staff
actually leave a rail. TAPS_FRONT moves to row 7 so the approach probe sits on
the punter side rather than inside the furniture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:32:11 +10:00
type-two
6d2fc56bfb Handover: FABLE-SOLO-12 — three lifecycle fixes and a soak against the roster wave
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:28:48 +10:00
type-two
164b4480c5 Fix floor-start shifts booting inert, and the floor carrying last night into this one
applyLocation() only moved flags — it never announced the move. FloorDemoScene
latches `present` when it binds the night context, which (now the night preloads
every prop texture) happens BEFORE the initial applyLocation runs, so every
floor-start shift — bartender, glassie, DJ — came up visible but completely
inert, with the audio filter still in door mode. The night now emits
night:phaseChange and audio:location for the starting post.

Phaser reuses scene instances across restarts, so class-field initialisers run
once per GAME, not once per night: a DJ shift left djMode set and the next
night's floor booted with movement locked and the keyboard eaten, last night's
puddles kept slipping people through destroyed sprites, and the handled-patron
sets marked fresh arrivals as already dealt with. resetNightState() now wipes
all of it in create().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:24:22 +10:00
type-two
79cd80dc01 Fix the dev route killing the door: N mid-night left a live Night driving a dead Door
showScene() stopped 'Door' (it was in the stop list) and then declined to
restart the already-active 'Night', leaving an unplayable black screen with no
way back. Route only ROOT scenes, and restart the target when it is already
running so N means 'fresh night'. NightScene.teardown() now stops Door and
Floor, making real the ownership main.ts always claimed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 02:13:47 +10:00
type-two
d4f802407b The floor score: lights on at close — sweep the notes, the shrapnel, the untouched kebab; the baggie is a choice and the pay line knows
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:40:24 +10:00
type-two
ec9afaff0f The roster board: role × venue level select — six shifts, wages on the card, the night opens wherever the shift stands you
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 03:10:17 +10:00
type-two
e008fb442f Radio command: the Head of Security verb — Bump sorts the mess, Shan waters the worst, Kayden holds the rope (Elevate+, competence not guaranteed)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:49:14 +10:00
type-two
5334a30150 Prop batch 2: monitor, booth lamp, dishwasher, pool table, wet-floor cone, high tables, plants, and a real red-carpet plate for the door
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:39:11 +10:00
type-two
5ebdfc61eb The red carpet: 3-slot velvet holding pen — park them, they pay hype; patience by archetype, storms, and the entrance dividend on admit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:32:15 +10:00
type-two
b7bb8f49ab The money layer: booth tips (cash buys the yes, not the landing), the pour meter, bar tabs with the card jar and the 3-card handback
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:17:45 +10:00
type-two
022ea32005 Handover: fix deploy URL typo
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:06:49 +10:00
type-two
c20a689086 ROOM boss week: venue 4 — seeded 15-min dress-code shuffle (the board is the law), lip-read rope dialogue, ROOM crowd/knobs; SCENARIOS shelf cleared
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 02:06:16 +10:00
type-two
b273c5c833 The bartender shift: hold the taps — per-stage order lines, SERVE/WATER/CUT OFF priced per §4.3, RSA breach rides a deferred write-up
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 01:56:49 +10:00
type-two
41e93d01ab Door tween leak: tutorial fade spawned an 800ms tween per frame — now pure tutorialAlpha() driven from update()
Ported from claude/epic-faraday-332679 (6c5889c) — merge was permission-blocked,
same diff applied directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 01:41:21 +10:00
type-two
fbcbb2e349 The DJ shift: hold the decks — bass-out builds, bar-line-judged drops, booth requests with odds
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 19:49:33 +10:00
189 changed files with 9560 additions and 162 deletions

4
.gitignore vendored
View File

@ -1,2 +1,6 @@
node_modules node_modules
dist/ dist/
art_incoming/
public/props/manifest.lock
__pycache__/
*.pyc

View File

@ -29,6 +29,31 @@ by parallel "lanes" coordinated through files, reviewed by Fable.
branch. An unpushed session didn't happen. branch. An unpushed session didn't happen.
- Remote is Gitea: `ssh://git@100.71.119.27:222/monster/not-tonight.git`. - Remote is Gitea: `ssh://git@100.71.119.27:222/monster/not-tonight.git`.
## Dev notes (venue expansion landed 2026-07-28)
- **The ladder's four venues now have four different rooms** (`docs/VENUES.md`).
Layouts live in `src/scenes/floor/layouts/` (`theRoyal`, `elevate`, `room`);
**Voltage stays in `venueMap.ts`** so the others can import primitives from it
without an import cycle. A night picks its room from `NightContext.venue.id`.
- Nothing about a room may be a module singleton any more. Props, lights, posts,
probes and the tile palette all hang off `FloorLayout`. `venueMap.VENUE/PROPS/
LIGHTS` still exist and are still Voltage's — they are the reference room, not
"the venue".
- **Dev route `#floor:<venueId>`** boots the floor demo straight into one room
(`#floor:room`, `#floor:theRoyal`, `#floor:elevate`). Plain `#floor`/F = Voltage.
- `tests/floor/layoutInvariants.ts` is the executable rulebook every layout runs:
perimeter, reachability, anchors on walkable tiles, posts not sealed, probes
reachable, props on-grid. Add a room, add it to `LAYOUTS`, it gets checked.
- Asset generation is `tools/gen/``assets.py` is the manifest (one entry per
sprite), `run_batch.py` walks it, resumable, `--workers N`. **Cloudflare Workers
AI first** (10k free neurons/day, resets 00:00 UTC), falling back to MODELBEAST
`flux_local` automatically when the day's allocation is spent. Meshes use the
**512 tier + vertex baker** (`mb.FAST_MESH`): ~90s vs ~6min, and the difference
does not survive the downscale to 32px. Heartbeat: `~/.jobs/not-tonight-assets.json`.
- `props_import.py` takes its sizes FROM `tools/gen/assets.py`, so sizes cannot
drift between the farm and the game. It locks `manifest.json` — parallel imports
used to lose entries to a read-modify-write race, which shows up as a prop that
is on disk but renders as a placeholder. `tools/gen/rebuild_manifest.py` repairs.
## Dev notes (Phase 2 landed 2026-07-19) ## Dev notes (Phase 2 landed 2026-07-19)
- The game boots into the NIGHT (Thu→Fri→Sat run, saved). Controls: click the - The game boots into the NIGHT (Thu→Fri→Sat run, saved). Controls: click the
rope/verdicts at the door; click the venue doorway to step inside; on the rope/verdicts at the door; click the venue doorway to step inside; on the

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 169 KiB

View File

@ -70,10 +70,22 @@ Status: ✅ implemented · 🔜 next nibbles · 💡 backlog.*
## Systems worth a whole phase ## Systems worth a whole phase
- 💡 **Venue 4 / ROOM boss week** (design §6): dress code re-randomises every - ✅ **Venue 4 / ROOM boss week** (2026-07-21, first cut): fourth rung on the
15 in-game minutes; dialogue rendered as lip-read guesses under the loudest ladder (promotes from Elevate). No Dazza rule chronology — the board IS the
mix arc. law and re-randomises every 15 in-game minutes (3 rules per window, seeded,
- 💡 **The DJ shift** (role ladder): the booth is built, the engine's mix is with a toast on the turn); every rope line renders as bracketed lip-read
already externally scriptable — requests at the booth, energy management. guesses (`[FIST? LIST?]`) because the techno ate the dialogue. 60 licensed,
- 💡 **Bartender shift**: the bar geometry and RSA scoring already exist; 1.2 arrival scale, inspector working, crowd of heads and VIP-claimers.
pour-and-cut-off from the other side of the counter. - ✅ **The DJ shift** (2026-07-20, first cut): E at the booth hands you the decks
while the resident steps out. B pulls the bass (the room leans in); SPACE
drops, judged against the LIVE bar line (clean/late/clang — early and late
are the same offence); requests arrive at the booth glass with per-request
odds ("got any dnb", nan's song, the DUN DUN one) and three answers that all
cost something. A build held too long runs out of stairs. Movement locks
while you hold them; the floor and the door keep happening without you.
- ✅ **Bartender shift** (2026-07-21, first cut): E at the till hands you the
taps (movement locks; the floor keeps happening). Orders arrive as choices —
the order line degrades with the patron's stage (the spelling IS the sobriety
test) — SERVE / WATER / CUT OFF all legal, all priced. Serving messy/maggot
is the RSA breach: the vibe pays up front, and 35% of the time somebody with
a lanyard saw it (ONE deferred write-up per night, deduped by reason).

View File

@ -5,6 +5,14 @@ fleet's asset factories. Written 2026-07-20. Code contract: everything lands
behind data tables (`venueMap.PROPS` / `LIGHTS`) and a sprite drop-in convention — behind data tables (`venueMap.PROPS` / `LIGHTS`) and a sprite drop-in convention —
generated art replaces placeholders with zero code changes.* generated art replaces placeholders with zero code changes.*
> **Superseded in part, 2026-07-28 — see [VENUES.md](VENUES.md).** This document
> describes ONE venue floor, which is what the game had when it was written. The
> venue ladder now has four distinct rooms, and props/lights/posts/probes hang
> off a per-venue `FloorLayout` rather than the module singletons named below.
> The pipeline sections (§4 sprite drop-in, and the settled prop pipeline at the
> foot of this file) are still exactly right and still the house rules — only
> "the venue floor" in §2 is now specifically *Voltage's* floor.
## 1. Design principles ## 1. Design principles
1. **Darkness stays the mechanic.** Props read as silhouettes in ambient dark and 1. **Darkness stays the mechanic.** Props read as silhouettes in ambient dark and
@ -113,3 +121,42 @@ palette/density once.
*(flux params for all [MB] jobs: `model flux2-klein-4b, steps 4`; put "no text, *(flux params for all [MB] jobs: `model flux2-klein-4b, steps 4`; put "no text,
no lettering" in every prompt EXCEPT the posters, where mangled text reads as no lettering" in every prompt EXCEPT the posters, where mangled text reads as
authentic gig-poster grot.)* authentic gig-poster grot.)*
## Prop pipeline — settled 2026-07-22 (A/B'd, not guessed)
Two routes, both free and unlimited on MODELBEAST. Pick by object, not by habit.
**[MB] flux direct** — `flux_local``tools/props_import.py`. Fast (~9s).
Use for FLAT things: posters, decals, graffiti, signage, floor markings.
**[GLB] TRELLIS → Blender** — `flux_local` (product shot) → `trellis2_mlx`
(`asset_id` is a TOP-LEVEL job field, NOT inside `params`) →
`tools/glb_to_sprite.py <mesh.glb> <kind>` → sprite + manifest, headless, no
GUI. Use for objects with real VOLUME: tables, fridges, machines, furniture.
Why the split, from the A/B (same pool table, both routes): flux picks its own
camera every generation — the same prompt style gave a perfectly top-down
urinal and a front-on fridge in one batch, and mismatched camera angles never
read as one room. The mesh route renders every prop from one fixed ortho
camera, and TRELLIS carries detail flux flattens: worn felt, real pockets,
rails and legs, clean alpha.
**RAKE by object HEIGHT — and I had this backwards first time.**
Low and wide (pool table, booth table, crate): **60°**. Tall (arcade, fridge,
speaker, anything standing): **~76°**. The instinct to *lower* the rake for tall
objects "so you see more face" is wrong — a tall object already shows nothing
but face; it needs to be steeper to read as a floor prop at all. A speaker at
55° is a featureless black slab.
**Judge sprites at SHIP size, not render size.** A 512px render of a fridge from
above looks ambiguous; the same sprite at 32x32 under the game's own point light
reads fine, because the venue's LIGHTS do half the identifying work (the fridges
carry a cyan glow, the arcade a flickering blue). Do not re-roll a prop off the
back of the big preview.
**The old guidance, kept because it is still true for low objects:** The venue's props are
three-quarter top-down, not straight down. Re-rolled from directly overhead, a
bar fridge is a grey rectangle — physically correct and visually dead, because
the glowing bottles that say "fridge" are on its front. 60° keeps the top
surface dominant while leaving enough face to identify the object at 32px.

150
docs/VENUES.md Normal file
View File

@ -0,0 +1,150 @@
# NOT TONIGHT — the four venues
*Written 2026-07-28. The venue ladder in `src/data/venues.ts` has always been
four venues; up to now they shared ONE floor map and differed only by difficulty
knobs. This document is the design contract for giving each its own room.*
## 0. Why bother
Design §6 sells the ladder as *promotion* — survive a week, get a better door.
But a promotion you cannot see is a number, not a reward. Walking into Elevate
and finding The Royal's carpet under your feet undoes the fiction the whole run
is built on. Each venue now has its own bar layout, its own dunnies, its own
smoking area and its own DJ booth, because those four things are exactly what a
bouncer actually learns about a room.
## 1. Shared contract (all four)
- **Grid is fixed at 80×45 tiles.** Venues differ by ARRANGEMENT, not extent —
the camera, minimap and bounds maths all key off `MAP_W`/`MAP_H`, and a
per-venue grid size would be a refactor with no visible payoff. A small venue
reads small by walling its unused grid to `void`, not by shrinking the array.
- **Every layout exports a `FloorLayout`**: `{ id, map, props, lights, posts,
probes }`. Nothing else may be a module singleton — that was the old shape and
it is what made four venues impossible.
- **Every layout must satisfy the same invariants** (`tests/floor/layouts.test.ts`):
1. every `AnchorKind` has ≥1 anchor, and every anchor is walkable;
2. all walkable tiles are mutually reachable (flood fill), except sealed
cubicle interiors, which must be reachable from their `StallDef.door`;
3. every `POSTS` entry is walkable and has a walkable neighbour (a post on a
sealed tile freezes the player for the night — this has shipped twice);
4. every `PROBES` entry has a walkable tile within reach;
5. no prop hangs off the grid.
- **Materials are grain, the palette is hue.** `FloorLayout.materials` names a
generated plate per tile kind (`tex_carpet`, `tex_concrete`, …) and the baker
stamps it **tinted to the palette colour**. That is deliberate: an untinted
photo-real plate blows straight past the brightness band everything else was
tuned in, and the room stops being dark. Plates are 16×16 — the game's tile —
because at that size "carpet" is structured noise, which is also what pub
carpet looks like from head height. No plate named, or art not landed: flat
palette colour, exactly as before.
- **The baked floor is keyed per venue** (`floor:tiles:<id>`). Textures outlive a
scene, so a single global key meant the first venue you played baked the floor
for every venue after it — you would survive a week at The Royal, get promoted,
and walk into Voltage still standing on the pub's carpet. It only shows on
promotion, which is precisely when the ladder is supposed to pay off.
- **Light signatures survive** (SPACES.md §1): bar = amber, dance = pulsing
pink on the real beat, DJ = deep blue, toilets = flickering green, smoking =
cool blue, entry = venue pink. A venue may add ONE signature colour of its
own — Elevate's skyline gold, ROOM's sodium orange — and no more, or the
navigate-by-glow rule stops working.
- **Darkness stays the mechanic.** No venue may be bright enough to scan from
the doorway.
## 2. The Royal — "a dive with a dance floor"
Licensed 80 · regulars and punters · nobody checks anything.
A suburban Australian pub that had a dance floor bolted on in about 2004 and has
not redecorated since. Patterned carpet, a horseshoe public bar, and the dance
floor is plainly the least important thing in the building.
| Space | What's in it |
|---|---|
| **Public bar** (horseshoe, west) | the long counter, taps, till, keg stack, a TV showing the footy, bar fridges |
| **Pool room** (north-west) | two pool tables, cue rack, a dartboard on the wall |
| **TAB / pokies corner** (north-east) | bank of poker machines, TAB screens, stools, its own miserable light |
| **Bistro** (centre-north) | bistro tables, bain-marie counter, the meat-raffle drum |
| **Dance floor** (south-east) | small, an afterthought, one mirror ball, a jukebox on the wall |
| **DJ corner** | not a booth — a folding table with a controller, beside the dance floor |
| **Dunnies** (east) | a stainless TROUGH, two cubicles (one out of order), one basin |
| **Beer garden** (south, open sky) | picnic tables, umbrellas, patio heater, butt bin — the smoking area, and the nicest room in the pub |
Light: warm amber everywhere, green cone over each pool table, the pokies' own
sickly blue, and the beer garden cool blue. No pink except the dance corner.
## 3. Voltage — "valley institution"
Licensed 110 · the tuning baseline · the inspector drinks here.
**This is the existing map and it does not change.** It is tuned under the
darkness sheet, its reachability is asserted, and every existing floor test
targets it. It stays the default layout and the reference for the other three.
## 4. Elevate — "rooftop, small room, big opinions"
Licensed 70 · influencers and owner's mates · every second person is a VIP.
The whole venue is outdoors, which makes the rain a design element rather than a
yard-only effect. Small footprint — a third of the grid is sky. You arrive by
lift, not off the street, so the entry is a lobby.
| Space | What's in it |
|---|---|
| **Lift lobby** (west) | lift doors, a rope line, the stamp podium, one mirror |
| **Cocktail bar** (north) | short backlit bar, no taps — bottles and a champagne bucket |
| **VIP booths** (east) | banquettes behind velvet rope posts, low tables |
| **Dance floor** (centre, small) | it is a terrace with a dance floor, not a club |
| **DJ plinth** | raised, open, no booth walls — the DJ is on display |
| **Toilets** (north-east) | two unisex cubicles, marble basin, enormous mirror |
| **Terrace edge** (south + east) | glass balustrade, planters, the city skyline beyond |
| **Smoking** | the whole roof is open air; a designated corner with a standing ash urn and heat lamps |
Light: warm amber bar, cool blue-white terrace, deep blue DJ, and the venue's
own signature — **skyline gold** spilling from the city card beyond the glass.
## 5. ROOM — "no sign, no socials"
Licensed 60 · heads and chancers · the board is the law.
A concrete warehouse. No branding anywhere, because branding is how you get
found. The sound system is the most expensive thing in the building by an order
of magnitude and everything else is borrowed.
| Space | What's in it |
|---|---|
| **Main floor** | concrete pillars, no booths, the crowd is the furniture |
| **The stacks** | Funktion-One-style speaker towers + subs — huge, four corners |
| **DJ booth** | low, central, facing the floor, no barrier — CDJs not turntables |
| **Bar** (west) | a plywood plank on scaffolding, cans only, no taps, no till |
| **Toilets** (north-east) | industrial, graffiti on every surface, three cubicles of which one works, a cracked basin, no mirror |
| **Loading dock** (south, open sky) | roller door, pallets, a wheelie bin — this is the smoking area |
| **Chill-out** (north-west) | two ruined couches under a single bulb |
| **The board** | the rule board that rewrites itself (`shuffleDressCode`) — a physical prop by the entry |
Light: almost none. Sodium orange over the loading dock (ROOM's signature),
one flickering green fluoro in the dunnies, strobes on the floor, and the
stacks' own power LEDs. This is the darkest venue in the game on purpose.
## 6. Prop vocabulary added for these rooms
Route per SPACES.md §"Prop pipeline": **[F]** = flux direct (flat things —
signage, boards, screens, backdrops); **[M]** = product shot → TRELLIS.2 →
Blender ortho render (things with volume). Rake follows the house rule —
**60° low and wide, ~76° tall**.
| Venue | Kinds |
|---|---|
| The Royal | `pokie`[M76] `tabBoard`[F] `bistroTable`[M60] `picnicTable`[M60] `trough`[M70] `keg`[M76] `dartboard`[F] `jukebox`[M76] `raffleDrum`[M60] `bainMarie`[M60] `tvSport`[F] `beerUmbrella`[M80] `ashtray`[M60] |
| Elevate | `cocktailBar`[M60] `banquette`[M60] `ropePost`[M76] `planter`[M60] `balustrade`[M76] `djPlinth`[M60] `marbleSink`[M70] `ashUrn`[M76] `champBucket`[M60] `loungeChair`[M60] `liftDoor`[F] `skylineCard`[F] |
| ROOM | `stackF1`[M76] `subBass`[M60] `plywoodBar`[M60] `rollerDoor`[F] `pallet`[M60] `wheelieBin`[M76] `oldCouch`[M60] `pillar`[M76] `ruleBoard`[F] `strobe`[M76] `smokeMachine`[M60] `cableSnake`[M60] `brokenBasin`[M70] `canStack`[M60] `cdj`[M60] |
| Staff (set dressing, all venues) | `staffBartender` `staffDj` `staffGlassie` `staffSecurity` — all [M76] |
Staff figures are PROPS, not patrons. The procedural dolls stay exactly as they
are: `dollPlan` draws the specific items the dress code convicts on, so
replacing patrons with pre-rendered art would make the convictions invisible
(recorded in LANEHANDOVER, FABLE-SOLO-23). A bartender who never moves is set
dressing and carries no mechanical weight, which is why she can be a sprite.
Street plates (door scene, one per venue, [F], 640×176):
`street:royal` `street:elevate` `street:room``street:backdrop` stays Voltage's.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 836 B

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/props/ashUrn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

BIN
public/props/ashtray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

BIN
public/props/bainMarie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/props/balustrade.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

BIN
public/props/banquette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/props/barFridge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
public/props/barrier.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
public/props/binRound.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

BIN
public/props/boothLamp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 B

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
public/props/cableSnake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

BIN
public/props/canStack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

BIN
public/props/carpet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/props/cctv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

BIN
public/props/cdj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
public/props/ceilingFan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

BIN
public/props/cueRack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

BIN
public/props/dartboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
public/props/dishwasher.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

BIN
public/props/distroBox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

BIN
public/props/djPlinth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/props/exitSign.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

BIN
public/props/fireExt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

BIN
public/props/fireHose.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

BIN
public/props/firepit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
public/props/flightCase.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/props/front_room.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/props/graffiti.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

BIN
public/props/handDryer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

BIN
public/props/highTable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

BIN
public/props/iceWell.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

BIN
public/props/jukebox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/props/kebabShop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
public/props/keg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

BIN
public/props/liftDoor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

View File

@ -1,24 +1,131 @@
{ {
"props": [ "props": [
"arcade", "arcade",
"ashUrn",
"ashtray",
"bainMarie",
"balustrade",
"banquette",
"barFridge",
"barShelf", "barShelf",
"barrier",
"beerUmbrella",
"binRound",
"bistroTable",
"boothLamp",
"boothTable", "boothTable",
"brokenBasin",
"buttBin", "buttBin",
"cableSnake",
"canStack",
"carpet",
"cctv",
"cdj",
"ceilingFan",
"champBucket",
"cloak", "cloak",
"cocktailBar",
"crate", "crate",
"cubicleDoor",
"cueRack",
"dartboard",
"deck", "deck",
"discoball", "discoball",
"dishwasher",
"distroBox",
"djPlinth",
"exitSign",
"fireExt",
"fireHose",
"firepit",
"flightCase",
"front_elevate",
"front_room",
"front_theRoyal",
"front_voltage",
"glassRack", "glassRack",
"glassStack", "glassStack",
"graffiti",
"handDryer",
"highTable",
"iceWell",
"jukebox",
"kebabShop",
"keg",
"liftDoor",
"loungeChair",
"marbleSink",
"mirror",
"mixer", "mixer",
"monitor",
"mopBucket",
"noticeBoard",
"oldCouch",
"pallet",
"patioHeater",
"picnicTable",
"pieWarmer",
"pillar",
"plant",
"planter",
"plywoodBar",
"pokie",
"poolTable",
"poster1", "poster1",
"poster2", "poster2",
"poster3", "poster3",
"poster4",
"poster5",
"poster6",
"poster7",
"poster8",
"poster9",
"raffleDrum",
"rollerDoor",
"ropePost",
"ruleBoard",
"sandwichBoard",
"sinkRow", "sinkRow",
"skylineCard",
"smokeMachine",
"speaker", "speaker",
"stackF1",
"staffBartender",
"staffChef",
"staffCleaner",
"staffDj",
"staffGlassie",
"staffSecurity",
"stampPodium", "stampPodium",
"stanchion",
"streetBin",
"streetLamp",
"street_backdrop", "street_backdrop",
"street_elevate",
"street_room",
"street_theRoyal",
"strobe",
"subBass",
"tabBoard",
"taps", "taps",
"till" "taxi",
"tex_brick",
"tex_carpet",
"tex_concrete",
"tex_deck",
"tex_looTile",
"tex_parquet",
"tex_paving",
"tex_plaster",
"tex_steel",
"tex_timber",
"till",
"topiary",
"trough",
"truss",
"tvSport",
"urinal",
"wetFloor",
"wheelieBin"
] ]
} }

BIN
public/props/marbleSink.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 B

BIN
public/props/mirror.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

BIN
public/props/monitor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

BIN
public/props/mopBucket.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

BIN
public/props/oldCouch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/props/pallet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

BIN
public/props/pieWarmer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

BIN
public/props/pillar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

BIN
public/props/plant.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

BIN
public/props/planter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/props/plywoodBar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
public/props/pokie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

BIN
public/props/poolTable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/props/poster4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/props/poster5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/props/poster6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
public/props/poster7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

BIN
public/props/poster8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/props/poster9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
public/props/raffleDrum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

BIN
public/props/rollerDoor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
public/props/ropePost.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

BIN
public/props/ruleBoard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 760 B

BIN
public/props/stackF1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/props/staffChef.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

BIN
public/props/staffDj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
public/props/stanchion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Some files were not shown because too many files have changed in this diff Show More