Back to Outbreak: Soycoon City
SOURCE / PINNED RELEASE

Made of little things.

Outbreak: Soycoon City

Release
db7750b1d009…
Author-recorded commit
3ee3f5fd27a6…
License
LICENSE
Author’s source reference
nostr://npub182jczunncwe0jn6frpqwq3e0qjws7yqqnc3auccqv9nte2dnd63scjm4rf/wss%3A%2F%2Fgit.napplet.soy%2F/n-b87c04571a9

Archive hash verified: dbebdc772b142a1c…. The source-to-build association is the author’s claim; it has not been independently rebuilt.

README.md
# Outbreak: Soycoon City

A small PS1-inspired survival horror game starring Soybert, built with Three.js inside the existing soyLI napplet workspace. Explore six rooms in the Soycoon City Police Department, clear eight zombies with a pump shotgun, and build new layouts in the integrated stage editor. The Evidence Room, Records Corridor and Holding Room now connect to a Briefing Room, Forensic Lab and Maintenance Room through seven paired doors and alternate routes.

[Gameplay preview](preview-rerender.png) · [Preview video](preview-outbreak.webm) · [Graphical editor preview](preview-editor-polish.png) · [Phone preview](preview-rerender-phone.png)

The game uses fixed 4:3 cameras, tank controls, low-poly characters and a 480×360 pixelated render. The demo has 32 shots, including 14 priority doorway approaches and six wide recovery views. Triggers can be rectangles or concave polygons. Backgrounds are baked static images; the matching 3D geometry supplies collision and depth occlusion for live actors. Authored colors remain consistent in either host theme.

## Play

Press Begin patrol. W/S move; A/D turn; arrows also work. Hold Shift to run. Hold K for slower aiming turns, I (or K + Up) to aim upward, Space or J to fire, R to reload, E to enter a nearby door or use a green herb, Escape to pause. Close upward blasts within 2.1 meters destroy zombie heads. Herbs restore up to 35 HP and remain on the floor when health is full. Facing stays unchanged at a camera cut. The shotgun is strongest inside 3.2 meters and cannot shoot through props. The magazine holds six shells; reserve starts at 24. Clear every zombie to secure the precinct. Death and completion offer a restart.

Phone layouts provide movement, aim/aim-up, fire, reload and interaction buttons. Movement and aim can be held with separate pointers. Frames below 280×300 show an expansion notice and preserve the session. Multiple floors, animated door sequences and inventory are future work.

## Character assets

Editable Blender sources, rigged GLBs and export instructions live in [models/README.md](models/README.md). Soybert retains his tofu face and block silhouette with a taller narrow body and jointed limbs. Zombies use slender humanoid proportions. Named Blender actions provide walk/run, aim/upward aim, shooting recoil, reload, stagger, attack and death through Three.js AnimationMixer. Corpses finish and hold their death pose; pause freezes animation. Native source and runtime asset hashes are checked together.

## Controller

Standard USB/Bluetooth pads work through the native browser Gamepad API. Press a button after connecting, then focus the game. Left stick or D-pad controls tank movement; LT aims (right stick up raises the barrel), RT fires, X / □ reloads, A / × interacts with doors/herbs, B / ○ runs and Start begins/resumes/pauses. A dead zone prevents drift. Disconnect and focus loss pause gameplay. Unknown controller layouts retain keyboard/touch controls.

## Repository and player levels

The canonical layout is [levels/demo.json](levels/demo.json), with a [JSON schema](levels/level.schema.json) and a hash-linked artwork inventory. Developer instructions are in [levels/README.md](levels/README.md). Additional level JSON files in that folder appear in the Levels picker. Level settings let authors change starting health, reserve ammo, zombie health/speed and bite damage.

Open Levels to browse recent player maps or publish the current editor map. Sharing uses public NIP-78 records through the host’s OUTBOX, linked to an immutable Blossom JSON package and verified background files. The host asks for upload and publication approval. Connect a viewer Nostr identity to publish; visitors can browse anonymously. Remix / edit copies a level into the editor; Publish as new creates your own attributed record. Reopen your own level to edit and Update selected; stale updates are rejected. Retry retains prepared publication work. Unpublish writes a public tombstone; previously shared copies and files can remain available.

Discovery is a bounded recent view from the host’s configured storage relay. The copied address includes relay hints; configure the matching relay in host Network settings when opening an address from elsewhere. Preview and published napplet scopes are separate. Unsupported hosts retain local gameplay, JSON editing and export. Reopened drafts and JSON imports restore linked art through resource support; unavailable art leaves a playable procedural background and a visible message. Public relay visibility and physical controller behavior still need real-service/hardware validation.

## Sound

[sounds/demo.json](sounds/demo.json) plans 49 cues and 146 variants: shotgun/reloads, footsteps, zombie groans/attacks/falls/head bursts, doors, player reactions, six room ambiences, music and UI. Every entry has a prompt, timing/loop target, output path and mix guidance. [Production instructions](sounds/README.md) describe the later ElevenLabs computer-use session. The [first batch](sounds/first-batch/README.md) now plays in the game: shots and delayed pump cycles, reload start/insertion/finish, stone/concrete footsteps, nearby zombie groans and attacks, corridor ambience and patrol music. Begin patrol enables browser audio; the header Sound button enables or mutes it. Controller-only starts may need a click on Enable sound first. Pause, focus loss, help and editor/library mode stop playback; camera cuts preserve music.

[sounds/runtime.json](sounds/runtime.json) records 33 selected normalized MP3s with hashes and provider provenance. Original downloads, duplicate WAV reviews and superseded takes were removed at the user’s request. Future catalogue outputs are MP3 too. These remain trial selections; the larger production queue is still planned. The current reload uses one insertion cue during its 1.5-second timer. Falls, head bursts and player death now have simulation hooks; their recordings, door effects and the remaining ambiences are still pending.

## Stage editor

Precinct map shows the whole floor. Drag room centers to position rooms; drag empty space to pan. Connect doors accepts two taps on room edges or a drag between them. Move / select lets you drag door dots along walls, select a connection and remove its two endpoints. Several connections can share a room or wall, with 1.4 m spacing, corner clearance and unobstructed arrivals. Fit and zoom controls keep large maps manageable. Map X/Z fields offer precise room placement. Moving a room on this map preserves its backgrounds; editing a doorway changes the geometry and needs new art.

Room plan edits the selected rectangular room. Set its dimensions, name and art description. The plan snaps to quarter-meter increments:

- Select: drag a prop or zombie spawn; Delete selected removes it.
- Prop: choose a wall, shelf, desk, crate or bench, then drag its footprint.
- Zone: drag a rectangle, or Draw polygon and tap 3–24 vertices in order. Finish closes the shape; Undo/Cancel preserve the old trigger. Drag polygon vertices to refine concave areas. Invalid crossing/degenerate edges are rejected.
- Herb: tap clear floor to place a selectable, draggable green herb.
- Zombie / Spawn: tap clear floor to place an enemy or Soybert.
- Camera: drag the camera and look-target handles in the plan.
- Dress: place pinboards, framed photographs, posters, scattered papers, broom/bucket sets or pipes. Wall details snap to an edge; details can be selected, moved and removed. Dressing is cosmetic; solid props control collision.

Add cameras, move their handles, then adjust the live height and lens sliders. Classic, Eye level and Frog presets provide a starting angle; exact XYZ/look-target fields remain available. Frog cameras sit near the floor and look slightly upward, with a visible ceiling. Three demo shots use this perspective. Set areas so they cover the walkable floor. Existing camera coverage has a small edge hysteresis to prevent flickering. Higher-priority areas override lower ones; same-priority cuts have a small hysteresis. Cameras that crop the player are rejected, and a frame recovery shot covers blind corners. Door associations choose the closer approach when zones overlap. The coverage indicator flags missing door/floor framing; Frame selected door composes a shot and priority polygon. Frame recovery marks a wide safety view. A room always keeps one camera.

Room description & connections pairs doors to another room. Both endpoints are created or removed together. Test stage validates and restarts with the edited map; it catches spawns inside walls/props and invalid connections. Save draft writes geometry and prompts through optional shell storage. Custom imported background bytes travel in Export map JSON; they are intentionally omitted from the 512 KB storage draft. Load/import refuses to discard unsaved edits; save or export first. Map JSON also provides a copy/paste route.

## Schema to prerender

1. Select a room and camera. Faces + edges displays the exact camera schema.
2. Export schema PNG, Export prompt and optionally Camera JSON. The shell creates session exports; download them in its Files panel.
3. Feed the PNG and prompt into your image generator. The map's Base style is the shared art direction; each derived prompt adds the room description and precise camera metadata.
4. Preserve geometry, camera, perspective, doorways and object silhouettes. Dress surfaces, keep the floor clear, and omit characters/UI. Inspect alignment against the schema.
5. Import a 4:3 PNG/JPEG/WebP smaller than 2 MB. Rendered scene previews it. Geometry/lens changes invalidate the custom image; reimport art after regenerating it.
6. Export map includes custom art. Reimporting that JSON restores the map and art together.

All 32 demo views have regenerated 640×480 JPEG backgrounds in `src/art/`, including every door approach and frame recovery shot. Current schemas and exact generation prompts are in [docs/schema-shots](docs/schema-shots/README.md); [the render manifest](docs/room-render-manifest.json) links each view with hashes. Superseded PNGs and the previous `art-v2` set were removed. The shared master style lives in level JSON and [the game brief](docs/game-brief.md). Pinboards contain notes, maps and period photographs; scenes include framed portraits, litter, cleaning gear and utility detail. Ceiling lights are omitted from schema geometry and described in the prompt, avoiding ambiguous floating shapes. Demo art is bundled and tied to the original geometry. Geometry changes fall back to an immediate procedural bake. The editor does not call an image service at runtime or require an API key. Generation can drift, so schema matching is a visual review step.

## Develop and verify

Read [docs/napplet-space.md](docs/napplet-space.md) for tooling and host boundaries. The workspace is already scaffolded. Use `soyli dev --no-open` and its printed hosted URL; stop the owning session with Ctrl+C after testing.

```sh
pnpm verify
pnpm test:conformance
soyli check
```

For repeatable host interactions, keep the printed preview URL running in another terminal:

```sh
SOYINDENT_PREVIEW_URL=http://127.0.0.1:<printed-port>/ pnpm test:hosted
SOYINDENT_PREVIEW_URL=http://127.0.0.1:<printed-port>/ pnpm test:editor
SOYINDENT_PREVIEW_URL=http://127.0.0.1:<printed-port>/ pnpm test:polish:hosted
SOYINDENT_PREVIEW_URL=http://127.0.0.1:<printed-port>/ pnpm test:features
SOYINDENT_PREVIEW_URL=http://127.0.0.1:<printed-port>/ pnpm test:audio:hosted
```

`verify` includes guidance guards, game/rule/camera/polygon/model, controller, sharing and audio tests, checked-in level/asset and sound-catalogue checks, TypeScript and a single-file Vite build. Conformance uses real Chromium in an `allow-scripts` iframe. Its manifest/wire/lifecycle checks may skip without evidence; a skip is not verification. Browser scenario coverage and actual frame sizes are recorded in [docs/verification.md](docs/verification.md). The current repository retains compressed room JPEGs and gameplay MP3s. Original/review audio duplicates and superseded room artwork were removed to fit the source archive budget. Verification records the final source and HTML sizes.

No required NAP domains. Optional storage saves maps, fs imports/exports session copies, and config supplies resolution and scanline settings with local defaults. Optional identity/outbox/upload/resource enable level sharing; the documented helper observes the shell’s existing app-data policy. No direct network, browser persistence, signer access, relay escape hatches, backend, or host DOM access exists in game code. Three.js and assets are inlined in `dist/index.html`; the original Vite napplet plugin owns bundling. The SDK was updated to 0.28.0 for its standard fs helpers; host capability absence and call failures remain recoverable.