Add 3D execution plan, lane prompts, and THREADS log
PLAN3D.md: locked stack (vendored three.js r175 + stdlib server, DJsim house style), verified asset inventory on the M1 Ultra, module contracts, five parallel lanes (world/sail/weather/player/assets) with acceptance criteria and integration order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
06404d3505
commit
8338c0fa99
79
LANE_PROMPTS.md
Normal file
79
LANE_PROMPTS.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# Lane launch prompts (Opus 4.8, run on the M1 Ultra)
|
||||||
|
|
||||||
|
Per lane: clone `git@gitea.partly.party:monster/shades.git` to
|
||||||
|
`~/Documents/shades-lane<X>`, branch `lane/<x>`, paste the prompt.
|
||||||
|
Lane A starts first; B/C/D/E can start immediately after in parallel
|
||||||
|
(they develop against contracts + selftest mocks until A's M0 merges).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lane A — world, shell & integration
|
||||||
|
|
||||||
|
> You are Lane A on SHADES 3D. Read PLAN3D.md fully (you own §5 Lane A), then
|
||||||
|
> DESIGN.md, then play prototype/ (`python3 -m http.server 8642 --directory
|
||||||
|
> prototype`). Build the M0 skeleton exactly per PLAN3D §3/§4/§5-A: vendored
|
||||||
|
> three.js copied from ~/Documents/90sDJsim/web/world/vendor/, stdlib server.py
|
||||||
|
> on 8801, contracts.js, graybox 30×20 m yard with house edge/trees/posts/garden
|
||||||
|
> bed, third-person camera, sun lighting, selftest.html harness. Merge M0 to
|
||||||
|
> main as fast as possible — every other lane rebases on you. Then build the HUD
|
||||||
|
> against mock data, and act as merge shepherd per PLAN3D §6. Log every landing
|
||||||
|
> in THREADS.md.
|
||||||
|
|
||||||
|
## Lane B — sail simulation & rigging
|
||||||
|
|
||||||
|
> You are Lane B on SHADES 3D. Read PLAN3D.md fully (you own sail.js +
|
||||||
|
> rigging.js, §5 Lane B), DESIGN.md §geometry/§hardware, and prototype/game.js —
|
||||||
|
> your job is the faithful 3D port of its cloth/load/failure behavior. Build the
|
||||||
|
> 3D verlet cloth with per-FACE wind pressure (F ∝ area·dot(wind,normal)²) so
|
||||||
|
> hypar twist genuinely sheds load — prove it with the selftest assert (twisted
|
||||||
|
> rig peak load < flat rig peak load in the same storm). Corner load = smoothed
|
||||||
|
> incident-spring stretch; break after 0.4 s sustained overload; flogging must
|
||||||
|
> be emergent from the freed node. Then the prep-phase rigging UI with the
|
||||||
|
> prototype's economy. Until Lane A's M0 merges, develop inside selftest.html
|
||||||
|
> with a stub wind function; keep every module deterministic (dt,t in — no
|
||||||
|
> Date.now, no rAF in sim code). Log in THREADS.md.
|
||||||
|
|
||||||
|
## Lane C — weather, sky & debris
|
||||||
|
|
||||||
|
> You are Lane C on SHADES 3D. Read PLAN3D.md fully (you own weather.js,
|
||||||
|
> skyfx.js, debris.js, data/storms/, §5 Lane C) and prototype/game.js's gust
|
||||||
|
> scheduler — port its telegraph/ramp/hold/fade shape. Implement
|
||||||
|
> wind.sample(pos,t) per contracts.js: base curve + gusts + direction change +
|
||||||
|
> spatial noise + tree wind-shadow. Storms are data (JSON, PLAN3D §4) — author
|
||||||
|
> storm_01_gentle and storm_02_wildnight. Then instanced rain following local
|
||||||
|
> wind, storm sky + lightning flash, WebAudio layers (wind bed, gust whoosh,
|
||||||
|
> rope creak keyed to max corner load, flog when broken), and hand-rolled
|
||||||
|
> debris (crates/tubs from models/debris/) with player knockdown + sail impulse.
|
||||||
|
> No physics engine, no deps. Selftest: telegraph lead ≥1.2 s, wind continuity,
|
||||||
|
> storm JSON validator. Log in THREADS.md.
|
||||||
|
|
||||||
|
## Lane D — player character & interaction
|
||||||
|
|
||||||
|
> You are Lane D on SHADES 3D. Read PLAN3D.md fully (you own player.js +
|
||||||
|
> interact.js, §5 Lane D) and 90sDJsim's DEVMANUAL rigged-characters section
|
||||||
|
> (~/Documents/90sDJsim/DEVMANUAL.md) — its loading rules are law
|
||||||
|
> (SkeletonUtils.clone, head-bone height normalize, never blind setScalar).
|
||||||
|
> Copy a ped from ~/Documents/90sDJsim/web/world/models/peds/ into models/
|
||||||
|
> (copies rule), merge Walk/Running/Happy Idle clips via ~/Documents/
|
||||||
|
> character_kit/ pipeline; queue Climbing Ladder / crank / dig on the
|
||||||
|
> ~/Documents/mixamo-fetch wishlist for M3. Camera-relative WASD + anim state
|
||||||
|
> machine, wind slow/shove/knockdown per PLAN3D, and hold-E interactions via
|
||||||
|
> interact.register (re-rig with spare 2.5 s, per-corner turnbuckle trim 1.2 s,
|
||||||
|
> carry-one-item from shed table). Selftest: state machine table test. Log in
|
||||||
|
> THREADS.md.
|
||||||
|
|
||||||
|
## Lane E — nature & hardware assets (Blender)
|
||||||
|
|
||||||
|
> You are Lane E on SHADES 3D. Read PLAN3D.md fully (you own tools/blender/ +
|
||||||
|
> models/, §5 Lane E). Study the house Blender-scripting idiom in
|
||||||
|
> ~/Documents/3D-STORE/build_booth_room_v23.py and racks_to_glb.py, then write
|
||||||
|
> ONE deterministic tools/blender/build_yard_assets.py that generates every
|
||||||
|
> deliverable in PLAN3D §5-E (gum trees with named canopy/branch_anchor nodes,
|
||||||
|
> fence set, house_yardside with fascia_anchor empties, shed + table, garden
|
||||||
|
> bed with 3 damage states, raked sail post, ladder, close-up shackle/
|
||||||
|
> carabiner/turnbuckle, ref_capsule) and exports meter-scale Y-up GLBs, <15 k
|
||||||
|
> tris, low-poly stylized to sit beside the 90sDJsim ped fleet. Also copy +
|
||||||
|
> scale-check the debris set from ~/Documents/3D-STORE/clean_glbs/ into
|
||||||
|
> models/debris/. Verify every export by rendering a contact sheet against the
|
||||||
|
> 1.7 m ref capsule (the 3D=models/_thumbnails pattern). Commit script AND
|
||||||
|
> GLBs. Log in THREADS.md.
|
||||||
304
PLAN3D.md
Normal file
304
PLAN3D.md
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
# SHADES 3D — execution plan & lane instructions (for Opus 4.8)
|
||||||
|
|
||||||
|
*Port the proven 2D prototype (see `prototype/`, play it before writing code) to a
|
||||||
|
3D third-person game: you are a small person in a real backyard, rigging shade
|
||||||
|
sails against a storm you can see coming, then running repairs in wind and rain.*
|
||||||
|
|
||||||
|
**Read this whole file before starting your lane. `DESIGN.md` is the design
|
||||||
|
canon; this file is the build canon.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 0. Ground rules (all lanes)
|
||||||
|
|
||||||
|
- **Stack — locked:** three.js **r175 vendored** (copy `~/Documents/90sDJsim/web/world/vendor/` — three.core.js, three.module.js, addons) + **zero-dependency Python stdlib server** (`server.py`, http.server, no pip, no DB, no build step, no CDN, no npm). This is the proven house stack from 90sDJsim; do not relitigate it.
|
||||||
|
- **Where you run:** on the M1 Ultra (`johnking@100.91.239.7`, Tailscale). All asset
|
||||||
|
paths below are local there. Clone your lane from gitea:
|
||||||
|
`git clone git@gitea.partly.party:monster/shades.git ~/Documents/shades-lane<X>`
|
||||||
|
then work on branch `lane/<x>`. Push your branch; never force-push main.
|
||||||
|
- **Units:** meters, +Y up, world origin at yard center on the ground. Player height ~1.7 m. The yard is ~30×20 m. GLB exports: Y-up, meter scale, `*_v1.glb` naming into `web/world/models/`.
|
||||||
|
- **Asset copies rule (house rule from DJsim):** runtime models in `web/world/models/`
|
||||||
|
are COPIES. Canonical sources stay in the shared libraries
|
||||||
|
(`~/Documents/3D=models/`, `~/Documents/character_kit/`, `~/Documents/3D-STORE/`,
|
||||||
|
`~/Documents/FBX/`). Never hand-edit a game-local GLB; rebuild at source and re-copy.
|
||||||
|
Raw `.fbx`/`.blend` are gitignored; runtime asset is always `.glb`.
|
||||||
|
- **Rigged characters:** follow 90sDJsim DEVMANUAL "rigged characters" rules —
|
||||||
|
`SkeletonUtils.clone()` for instances, height-normalize by head-bone height,
|
||||||
|
never blind `setScalar`. The Mixamo pipeline is `~/Documents/mixamo-fetch/`
|
||||||
|
(README inside; wishlist → `fetch.cjs`); already-fetched clips sit in
|
||||||
|
`~/Documents/FBX/` and `~/Documents/3D=models/animations/`.
|
||||||
|
- **Testing:** the game must run headless-testable. `web/world/selftest.html`
|
||||||
|
loads the sim modules WITHOUT rendering and runs assert suites (fast-forward
|
||||||
|
a 90 s storm in a loop, print pass/fail JSON to console + DOM). Every lane
|
||||||
|
keeps its module importable there. NOTE: `requestAnimationFrame` pauses in
|
||||||
|
hidden tabs — selftest must drive the sim with fixed-dt loops, not rAF.
|
||||||
|
- **Commit style:** small commits on your branch, imperative messages, no binary
|
||||||
|
churn (don't re-export unchanged GLBs).
|
||||||
|
- **File ownership is the merge strategy.** Lanes only edit files they own (see
|
||||||
|
lane sections). Shared contracts live in `web/world/js/contracts.js` — Lane A
|
||||||
|
lands it in M0 and after that it changes only by agreement (note in THREADS.md).
|
||||||
|
- **Coordination:** append-only log in `THREADS.md` at repo root — one line per
|
||||||
|
landed feature / contract change / open question, prefixed with your lane letter.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. What we're building (M0 → M3)
|
||||||
|
|
||||||
|
**M0 — walkable yard (Lane A, serial, ~first).** Skeleton everyone builds on:
|
||||||
|
index.html + server.py + vendored three; terrain plane, house shell, placeholder
|
||||||
|
trees/posts; third-person camera; contracts.js. Merged to main before other
|
||||||
|
lanes' first merge (they develop against contracts + mock harnesses meanwhile).
|
||||||
|
|
||||||
|
**M1 — the rig.** Sail cloth sim attached to anchors with per-corner hardware;
|
||||||
|
prep-phase UI (pick 4 anchors, cycle hardware, tension); calm-day wind makes
|
||||||
|
the sail breathe. Character walks, camera follows, anims play.
|
||||||
|
|
||||||
|
**M2 — the storm.** Storm timeline: wind ramp + gusts (telegraphed), direction
|
||||||
|
change, rain; corner loads → weakest-link breaks → cascade; flogging sail;
|
||||||
|
player runs repairs (hold-E re-rig with spare); wind shoves player; debris
|
||||||
|
(3D-STORE crates/tubs) tumbles through.
|
||||||
|
|
||||||
|
**M3 — the game.** Garden bed coverage scoring, prep timer, forecast card,
|
||||||
|
end-of-storm aftermath screen, sound (wind/creak/flog/rain layers), and the
|
||||||
|
full loop: forecast → prep → storm → aftermath. Optional: deploy via the
|
||||||
|
90sDJsim pattern (docker on dealgod VPS).
|
||||||
|
|
||||||
|
The 2D prototype (`prototype/game.js`) is the reference implementation for:
|
||||||
|
gust scheduler shape, load = spring-stretch at corners smoothed, break =
|
||||||
|
0.4 s sustained overload, hardware tiers/prices, garden damage = f(uncovered),
|
||||||
|
wind-change event, repair hold. Port the *behavior*, retune the constants.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Asset inventory (M1 Ultra, verified 2026-07-16)
|
||||||
|
|
||||||
|
| Need | Have | Path |
|
||||||
|
|---|---|---|
|
||||||
|
| three.js r175 + addons (GLTFLoader, SkeletonUtils…) | ✅ vendored | `~/Documents/90sDJsim/web/world/vendor/` |
|
||||||
|
| Player character (small person) | ✅ rigged fleet | `~/Documents/90sDJsim/web/world/models/peds/` (man_casual_01-03, woman, elder…); canonical rigs `~/Documents/character_kit/` (hum_character.glb, female/); more in `~/Documents/3D=models/characters/` (53 people-normal + comical) |
|
||||||
|
| Locomotion anims | ✅ | `~/Documents/FBX/` (Running, Falling, Crouch To Stand, Reaction…), `~/Documents/3D=models/animations/` (Walk, Start Walking, Happy Idle, Injured Walk…, 32 clips) |
|
||||||
|
| Missing anims (climb ladder, crank/wrench, dig, hammer) | fetch | `~/Documents/mixamo-fetch/` — add to wishlist, run fetcher |
|
||||||
|
| Debris + yard clutter | ✅ perfect fits | `~/Documents/3D-STORE/clean_glbs/` (BlueCrate, BlackTub, WhiteTub, WoodenBin, LibraryTrolley…) + `~/Documents/3D=models/street-furniture/` (benches, streetlight, market_stall, food_cart, building_shell_01) |
|
||||||
|
| Furniture/props (granny-flat interiors later) | ✅ | `~/Documents/3D=models/furniture/`, `props-scenes/` |
|
||||||
|
| Trees, fence, house exterior, shed, garden bed, grass, shade-sail hardware | ❌ **GAP** | Lane E builds these (Blender is installed; house style is scripted builds — see `~/Documents/3D-STORE/build_booth_room_v23.py` for the idiom) |
|
||||||
|
| Blender / Godot / UE 5.7 | ✅ installed | `/Applications`, `/Users/Shared/Epic Games/UE_5.7` (UE/Godot NOT used for this — three.js only) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Repo layout (target)
|
||||||
|
|
||||||
|
```
|
||||||
|
shades/
|
||||||
|
├── DESIGN.md, PLAN3D.md, THREADS.md
|
||||||
|
├── prototype/ # 2D reference — do not modify, do not delete
|
||||||
|
├── server.py # stdlib static server + /selftest passthrough, port 8801
|
||||||
|
├── .claude/launch.json # "shades3d" config → python3 server.py
|
||||||
|
└── web/world/
|
||||||
|
├── index.html # game shell
|
||||||
|
├── selftest.html # headless sim asserts (fixed-dt, no rAF)
|
||||||
|
├── vendor/ # three r175 (copied, committed)
|
||||||
|
├── models/ # runtime GLBs (copies)
|
||||||
|
├── audio/
|
||||||
|
└── js/
|
||||||
|
├── contracts.js # SHARED interfaces — Lane A owns, change by agreement
|
||||||
|
├── main.js # boot + game loop + phase machine (A)
|
||||||
|
├── world.js # terrain, yard, props, lighting, sky (A)
|
||||||
|
├── camera.js # third-person rig (A)
|
||||||
|
├── sail.js # cloth sim, anchors, hardware, loads (B)
|
||||||
|
├── rigging.js # prep-phase UI + hardware economy (B)
|
||||||
|
├── weather.js # wind field, storm timeline, rain (C)
|
||||||
|
├── skyfx.js # storm sky, lightning, audio layers (C)
|
||||||
|
├── player.js # character, controls, anims (D)
|
||||||
|
├── interact.js # tool prompts, hold-E actions (D)
|
||||||
|
├── debris.js # tumbling objects, collisions (C)
|
||||||
|
└── hud.js # meters, forecast card, aftermath (A after M0, else propose in THREADS)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Contracts (the integration spine)
|
||||||
|
|
||||||
|
Lane A lands `contracts.js` in M0 with exactly these shapes (JSDoc-typed):
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Wind: THE shared primitive. Everything samples wind through this.
|
||||||
|
// weather.js implements; world/sail/player/debris consume.
|
||||||
|
wind.sample(pos /*Vector3*/, t) -> Vector3 // m/s, includes gusts & local effects
|
||||||
|
wind.gustTelegraph(t) -> {eta, dir, power}|null // for HUD + grass wave + player audio cue
|
||||||
|
|
||||||
|
// Storm timeline (data, not code): storms are JSON so design can tune without code.
|
||||||
|
// web/world/data/storms/*.json: {duration, baseCurve:[[t,speed]...], gusts:{minGap,maxGap,pow...},
|
||||||
|
// dirCurve:[[t,rad]...], events:[{t,type:"windchange"|"debris",...}], rain:{...}}
|
||||||
|
|
||||||
|
// Sail rig
|
||||||
|
sailRig.corners -> [{anchorId, hw:{name,cost,rating}, load, broken}]
|
||||||
|
sailRig.attach(anchorId[4], hwChoices, tension)
|
||||||
|
sailRig.step(dt, wind, t) // fixed-dt, deterministic
|
||||||
|
sailRig.coverageOver(rect) -> 0..1 // ground-projected shade
|
||||||
|
sailRig.events -> emits {type:"break"|"repair", corner}
|
||||||
|
|
||||||
|
// Anchors (world provides; sail consumes)
|
||||||
|
world.anchors -> [{id, pos, type:"house"|"tree"|"post", sway(t)->Vector3}]
|
||||||
|
|
||||||
|
// Player
|
||||||
|
player.pos, player.carrying, player.busy
|
||||||
|
interact.register({id, pos, radius, holdSecs, label, canUse()->bool, onDone()})
|
||||||
|
|
||||||
|
// Game phases
|
||||||
|
game.phase: "forecast"|"prep"|"storm"|"aftermath"; game.on(phaseChange)
|
||||||
|
```
|
||||||
|
|
||||||
|
Determinism rule: `sail.js`, `weather.js`, `debris.js` take `(dt, t)` — no
|
||||||
|
`Date.now()`, no internal rAF — so selftest can fast-forward storms.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Lanes (run these in parallel)
|
||||||
|
|
||||||
|
### Lane A — World, shell & integration (start first; owns main.js, world.js, camera.js, hud.js, contracts.js, server.py, index.html, selftest.html)
|
||||||
|
|
||||||
|
1. M0 skeleton per §3: copy vendor from DJsim, stdlib `server.py` (port 8801,
|
||||||
|
`--selfcheck` flag runs a headless node-free check by printing the selftest
|
||||||
|
URL; keep it dumb), launch.json, contracts.js, and a walkable graybox yard:
|
||||||
|
30×20 m ground with gentle height variation, house shell along north edge
|
||||||
|
(use `street-furniture/building_shell_01.glb` scaled, or graybox), 2 placeholder
|
||||||
|
trees, 2 posts, garden bed rect, boundary fence graybox. Third-person follow
|
||||||
|
camera (orbit on RMB, shoulder-follow default). Directional sun + hemisphere
|
||||||
|
light, calm sky. **Merge to main fast — everyone rebases on this.**
|
||||||
|
2. HUD after M0: wind meter + arrow, corner load bars (world-anchored sprites),
|
||||||
|
garden health, phase banner, forecast card, aftermath screen. Consume
|
||||||
|
contracts only; mock data until B/C land.
|
||||||
|
3. Integration duty: you are the merge shepherd. Rebase lane branches onto main
|
||||||
|
in order (E-assets swap is a drop-in; B and C rebase next; D last), run
|
||||||
|
selftest.html + a manual storm after each merge, log regressions in THREADS.md.
|
||||||
|
4. Swap in Lane E's GLBs as they land (tree_v1, fence, shed, house when ready).
|
||||||
|
|
||||||
|
Acceptance: 60 fps on the M1 Ultra in graybox storm scene; camera never clips
|
||||||
|
through house; selftest green after every merge.
|
||||||
|
|
||||||
|
### Lane B — Sail simulation & rigging (owns sail.js, rigging.js)
|
||||||
|
|
||||||
|
1. Port prototype cloth to 3D verlet: grid N=10 per side, nodes are Vector3,
|
||||||
|
structural+shear+bend constraints, 5 relaxation iterations, fixed dt 1/60.
|
||||||
|
Wind force per FACE (not node): `F = area * clamp(dot(wind, normal))² * ρ`
|
||||||
|
along face normal + tangential drag — this gives real hypar behavior: a
|
||||||
|
twisted quad sheds load, a flat one catches it. Prove it in selftest:
|
||||||
|
assert twisted-rig peak corner load < flat-rig peak load, same storm.
|
||||||
|
2. Corner load = smoothed stretch of springs incident to corner (prototype
|
||||||
|
formula); hardware tiers/prices from prototype; break after 0.4 s sustained
|
||||||
|
overload; broken corner frees the node → flogging is emergent. Sag under
|
||||||
|
gravity when calm; tension parameter scales rest lengths (0.6–1.4).
|
||||||
|
3. Rendering: BufferGeometry updated from nodes, double-sided, cloth material,
|
||||||
|
per-vertex normal recompute each frame. Sail casts real shadows (this IS the
|
||||||
|
shade mechanic — coverageOver() can raycast sun direction or ground-project).
|
||||||
|
4. Rigging UI (prep phase): click anchor markers to assign corners (max 4,
|
||||||
|
ring-order by angle), click corner to cycle hardware with budget, tension
|
||||||
|
slider, spare purchase. Reuse prototype economy numbers as the starting tune.
|
||||||
|
5. Selftest suite: flat-vs-hypar assert; cascade assert (break one corner at
|
||||||
|
fixed t → neighbor load must spike ≥2×); determinism assert (two runs, same
|
||||||
|
inputs → byte-equal load traces).
|
||||||
|
|
||||||
|
### Lane C — Weather, sky & debris (owns weather.js, skyfx.js, debris.js, data/storms/)
|
||||||
|
|
||||||
|
1. `wind.sample(pos,t)`: base curve + scheduled gusts (port prototype scheduler:
|
||||||
|
telegraph 1.5 s, ramp 0.8 s, hold ~2 s, fade) + direction curve with one
|
||||||
|
mid-storm change + spatial variation (smooth noise over x,z so the yard
|
||||||
|
isn't uniform; add tree wind-shadow discs downwind of trees — cheap, juicy).
|
||||||
|
Storm definitions load from JSON (§4). Author `storm_01_gentle.json`,
|
||||||
|
`storm_02_wildnight.json` to bracket difficulty.
|
||||||
|
2. Rain: GPU-friendly instanced streaks (~2–4 k), angle/speed follow local wind,
|
||||||
|
fade by intensity from storm JSON; splash rings on ground optional. Storm sky:
|
||||||
|
darken + cloud dome scroll + rumble; one cheap lightning flash event type.
|
||||||
|
3. Audio layers (files or synthesized WebAudio): wind bed pitched by speed,
|
||||||
|
gust whoosh keyed to telegraph, rain layer, rope-creak keyed to max corner
|
||||||
|
load (hook via sailRig.corners), fabric flog when any corner broken. Audio
|
||||||
|
unlock on first input (browser rule).
|
||||||
|
4. Debris: spawn events from storm JSON — pick from `models/debris/` (Lane E
|
||||||
|
copies 3D-STORE crates/tubs there in M0 week). Kinematic tumble along wind
|
||||||
|
with bounce on ground plane, sphere-vs-player knockdown (1.5 s stagger, drop
|
||||||
|
carried), sphere-vs-sail node impulse. No physics engine — hand-roll, ~150 lines.
|
||||||
|
5. Selftest: gust telegraph always ≥1.2 s before ramp; wind.sample continuity
|
||||||
|
(no frame-to-frame jumps >X); storm JSON schema validator.
|
||||||
|
|
||||||
|
### Lane D — Player character & interaction (owns player.js, interact.js)
|
||||||
|
|
||||||
|
1. Character: pick a ped from `90sDJsim/web/world/models/peds/` (copy into
|
||||||
|
`models/`, per copies-rule; man_casual_01 or woman — small relative to 4 m
|
||||||
|
posts reads "small person"). Load with DEVMANUAL rig rules. Clips: Walk +
|
||||||
|
Running + Happy Idle from the libraries; retarget/merge via character_kit
|
||||||
|
pipeline. Fetch "Climbing Ladder", "Turning Key/crank", "Digging" via
|
||||||
|
mixamo-fetch wishlist for M3.
|
||||||
|
2. Controls: WASD relative to camera, walk/run (shift), acceleration + turn
|
||||||
|
smoothing, anim state machine (idle/walk/run + one-shot interact). Gamepad
|
||||||
|
optional. Slope clamp to terrain height.
|
||||||
|
3. Weather effects on player: movement slow factor from local wind speed +
|
||||||
|
rain; gust shove = impulse along wind during gust hold (scale with speed²);
|
||||||
|
knockdown state (from debris or extreme gust): Falling clip + get-up
|
||||||
|
(Crouch To Stand), drop carried item.
|
||||||
|
4. Interactions via `interact.register`: hold-E with radial progress —
|
||||||
|
re-rig broken corner (needs spare, 2.5 s), tighten/ease turnbuckle at corner
|
||||||
|
(±tension at ONE corner, 1.2 s — new vs prototype, makes corners individual),
|
||||||
|
pick up/carry spare hardware from shed table (one item, hands-full rule).
|
||||||
|
5. Selftest: state machine table test (no stuck transitions); interact radius
|
||||||
|
respects busy/carrying flags.
|
||||||
|
|
||||||
|
### Lane E — Nature & hardware assets (Blender, scripted; owns tools/blender/, models/)
|
||||||
|
|
||||||
|
The gap lane. House idiom: **scripted Blender builds** (see
|
||||||
|
`~/Documents/3D-STORE/build_booth_room_v23.py` and `racks_to_glb.py` for the
|
||||||
|
export pattern). One `tools/blender/build_yard_assets.py` that regenerates
|
||||||
|
everything → `clean/` GLBs; commit script + GLBs.
|
||||||
|
|
||||||
|
Deliverables (meters, Y-up, low-poly stylized to match ped fleet, baked or
|
||||||
|
flat colors, <15 k tris each):
|
||||||
|
1. `tree_gum_01/02.glb` — trunk + 2-3 canopy blobs as SEPARATE named nodes
|
||||||
|
(`trunk`, `canopy_*`, `branch_anchor_*` empties at rig points) so Lane A can
|
||||||
|
sway canopies in wind and Lane B can query branch anchor positions.
|
||||||
|
2. `fence_panel.glb`, `fence_post.glb` (tileable), `gate.glb`.
|
||||||
|
3. `house_yardside.glb` — single-story rear façade: wall, 3 `fascia_anchor_*`
|
||||||
|
empties, gutter line, window, door. Doesn't need interior.
|
||||||
|
4. `shed_01.glb` + `shed_table.glb` (spare-hardware pickup point).
|
||||||
|
5. `garden_bed.glb` — raised bed + plant billboard tufts (damage states: full /
|
||||||
|
tattered / dead as morph or 3 variants).
|
||||||
|
6. `sail_post.glb` (raked steel post + footing collar), `ladder_01.glb`.
|
||||||
|
7. Hardware close-ups (visible at corners): `shackle.glb`, `carabiner.glb`,
|
||||||
|
`turnbuckle.glb` — tiny, but they're the fetish objects of the game; make
|
||||||
|
them read at 1 m distance.
|
||||||
|
8. `models/debris/`: copy + sanity-scale BlueCrate_v2, BlackTub_v2, WhiteTub_v2,
|
||||||
|
WoodenBin_v2 from `3D-STORE/clean_glbs/`; add `tramp_01.glb` (trampoline!)
|
||||||
|
if time.
|
||||||
|
9. Grass: NOT geometry — ship a 4-tuft billboard atlas texture; Lane A instances.
|
||||||
|
|
||||||
|
Acceptance: `blender -b -P tools/blender/build_yard_assets.py` regenerates all
|
||||||
|
GLBs deterministically; each GLB loads in a viewer with correct scale vs a 1.7 m
|
||||||
|
reference capsule (include `ref_capsule.glb` in the script).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Integration order & schedule
|
||||||
|
|
||||||
|
```
|
||||||
|
day 0: A lands M0 skeleton → main (B,C,D,E develop against contracts + mocks)
|
||||||
|
day 1-2: E drops first GLBs (trees/fence/house) → A swaps graybox
|
||||||
|
B lands cloth in selftest, then rendered sail on main
|
||||||
|
C lands wind+rain on main (sail immediately reacts — first magic moment)
|
||||||
|
day 3-4: D lands character + controls + weather effects
|
||||||
|
C lands debris + audio; B lands rigging UI/economy
|
||||||
|
day 5: M2 storm playable end-to-end; tune pass (everyone plays, THREADS notes)
|
||||||
|
day 6+: M3: scoring, forecast/aftermath, prep timer, sound polish, storm JSON tuning
|
||||||
|
```
|
||||||
|
|
||||||
|
Merge conflicts should be ~zero if file ownership is respected. If you need to
|
||||||
|
touch another lane's file: don't — post the need in THREADS.md instead.
|
||||||
|
|
||||||
|
## 7. Definition of done (M3)
|
||||||
|
|
||||||
|
- Full loop: forecast card → timed prep (rig 4 corners on any anchors, budget
|
||||||
|
$80, buy spare) → 90 s storm (gusts telegraphed, wind change, rain, ≥1 debris
|
||||||
|
event) → aftermath (garden %, hardware losses, cash delta).
|
||||||
|
- A flat drum-tight cheap rig MUST cascade-fail in storm_02; a well-twisted
|
||||||
|
mixed rig with one mid-storm repair MUST be survivable. Verify in selftest
|
||||||
|
AND by hand.
|
||||||
|
- 60 fps on the M1 Ultra, no build step, `python3 server.py` and it runs.
|
||||||
|
- Selftest green; THREADS.md tells the story; DESIGN.md updated where reality
|
||||||
|
diverged from plan.
|
||||||
6
THREADS.md
Normal file
6
THREADS.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# THREADS — append-only lane log
|
||||||
|
|
||||||
|
One line per landed feature, contract change, or open question.
|
||||||
|
Format: `[lane letter] YYYY-MM-DD — note`
|
||||||
|
|
||||||
|
[.] 2026-07-16 — repo seeded: DESIGN.md (canon), PLAN3D.md (build plan), prototype/ (2D reference, do not modify)
|
||||||
Loading…
Reference in New Issue
Block a user