Docs and dev tooling: water write-up, PR H prepared, teleport mod

- 09-water.md: physics, camera, splash and look after in-play testing
- 10-sky-shader-test.md, README index
- PULL-REQUESTS.md: PR H prepared against upstream 60efdef
- water-test-teleport: F7 Aletown canal, F5 position readout, the
  "Teleported" text clears after 5 s
This commit is contained in:
Hails committed 2026-10-01 12:27:23 -06:00
1 parent 55776dc373
commit 477e9de3f7
5 files changed
+286 -20

No files matched your search

+247 -15
View File
@@ -1,6 +1,6 @@
# Water
Branch: `gameplay/water`. Status: **water bail and animated water confirmed in play. Splash/ripple effects not implemented.**
Branch: `gameplay/water`. Status: **behaviour matched to retail footage (shallow water solid, deep water floats, board floats, water camera with vignette, entry splash, `water.alpha` look approved in play; small bodies calmer and waves slowed, awaiting check).**
## Problem
@@ -124,11 +124,220 @@ WipeoutGround, where `Collision+3481` starts the water ragdoll and the
respawn timer. Logged as `WATER_BAIL tick=… state=…`. **Project choice**, not
recovered retail behaviour.
Not changed: water stays solid. The water buoyancy code
(`wipeout_state::body::special_surface`, which pushes parts up when below
height + 0.1) suggests that in retail the body sinks slightly into water, so
water may not be solid for the body in retail. Left alone until play shows
whether that matters.
### Water is not solid (skater sinks in and floats, board sinks)
User, from retail footage: the skater sinks into the water and floats; the board
sinks. One retail video frame shows the underwater-skating glitch (riding the
floor under the water surface), so the surface itself does not block anything.
The wipeout buoyancy code (`wipeout_state::body::special_surface`, pushing parts
up when below height + 0.1) agrees.
- `skate-core` `board_world.rs`: `is_water_tag` (type 12), `FLOAT_DEPTH = 0.5`.
**Water is not solid:** `query_primitives` (the only path that makes physical
contacts, for board and skeleton) skips water triangles, so bodies pass
through the surface and rest on whatever lies under it. Ray, line and
trajectory queries are untouched, so the wipeout's water trajectory check and
respawn checks still see all water. `water_surface_at(point, above,
max_depth)` returns the water height over a point (XZ barycentric on water
triangles); `water_shallow_at` tells whether geometry lies within
`FLOAT_DEPTH` under a surface point; `deep_water_surface_at` combines them.
History: making shallow water solid (first per triangle, then per contact
point) stopped the jitter but the body lay on top of the water like glass
(user: "looks quite bad"); the jitter was the buoyancy, not the non-solid
surface, so the surface is non-solid everywhere again and only buoyancy is
limited to deep water.
- Water used to be detected from contact reports, which no longer exist for deep
water. `skate-game` `physics/water.rs` restores the same signals from
position: `mark_board` (after the board ground state is rebuilt) sets
collision bit 25 and `surface_twelve_height`; `mark_skater` (end of skeleton
feedback, before the postphysics wipeout checks) sets `material_12` and its
height. Any water counts here, shallow or deep, so all water still bails. A
body counts as in water from 0.05 m above the surface down to 4 m below.
- **Final rule, from retail footage (RPCS3, University channel):** in the 5–10 cm
channel retail bails you and you **lie on top of the water** (body and board on
the surface, water camera, respawn ~3.5–4 s, no splash); in the deep Aletown
canal you sink in and float. So water is **solid where shallow** and non-solid
where deep, decided per contact point: `query_primitives` drops a water contact
only if `water_shallow_at(contact point)` finds no geometry within `FLOAT_DEPTH`
(0.5 m) under it. On-foot support uses the same rule (`contact_toolkit` line hit
point / nearby centre, `ground_query` lines via `Mesh.world`). Body buoyancy and
the board's buoyancy/drag apply only over deep water (`deep_water_surface_at`),
so nothing pushes a body resting on solid shallow water (no jitter). Traces:
University channel, lowest body part 67.996 on a 67.94 surface, calm (0.06 m/s);
Aletown, body floats (8.49–9.04 vs 8.93), board floats (8.91). The two
intermediate versions below (shallow water solid per triangle; then all water
non-solid with a "floor pass" for bodies in water) are superseded; the
floor-pass version was removed.
- *(superseded)* **Shallow floors:** a body lying in University's 5–10 cm channel
still looked like it lay on top of the water (user GIFs). While a body is in
water, geometry within `FLOAT_DEPTH` (0.5 m) under a water surface no longer
holds it: `BoardWorld::set_water_floor_pass`, set by `solve.rs` for the board
query when a board part is in water and for the skeleton query during a water
wipeout (`special_surface`). The body sinks past the channel bottom and floats
like in deep water (trace: parts 67.43–68.05 against a 67.94 surface, settled
bobbing 0.28 m/s, same as the reservoir); the board sinks to the plaza below
(66.22). Ground deeper than 0.5 m still holds. Buoyancy and board drag apply
in any water again (the deep-only masking below was an intermediate step).
- The wipeout buoyancy runs per part only where the water is deep
(`special_surface_where`, `water::part_floats`). User report: in the shallow
channel the body jittered; a part resting on the floor 5 cm under the surface
was pushed up every step (the retail push includes a constant +0.1 term),
lifted off, lost the push and its water drag at the line, fell back, repeat.
Masked, the body lies in the channel on the concrete with its parts half
under the water (part centres at the surface), calm (headless trace: mean
part speed 0.05 m/s once settled). Deep water is unchanged: the body floats about 1 m
deep with the top just above the surface (reservoir trace).
- `apply_board_drag` (just before the solve, after every state sets its drag):
board parts over deep water get at least 0.1 linear/angular drag per step and
no buoyancy, so the board sinks slowly (reservoir: ~1.5 m/s, settles on the
bottom). Project-chosen value.
- DownTown's reachable deep water: the Aletown canal next to the Aletown
spawn (user, from the PS3 version in RPCS3): open water at 8.93 m, 1.12 m deep,
3.3 m below the quay, x -125..-205, z 436..490. Trace: body floats (parts
8.50–9.02), board on the canal bed (7.90), camera 1.8 m above. Water triangles a
global scan reports as 20 m deep elsewhere in DownTown lie under walkable ground
(buried planes), not open water. University's reservoir is out of bounds in
retail (user).
- **Retail reference (PS3 version in RPCS3, Aletown canal, user GIFs):** the
board **floats** at the surface next to the skater (an earlier YouTube clip
suggested it sinks; the emulator footage is the reference); the body floats
spread-eagle just under semi-transparent water; a white mist plume plus droplet
sprites, ~3-4 m across, lasts ~0.7 s, with a small puff where the board hits
first; no ripple rings; the camera goes high above and behind, looking down
~60 degrees and drifting toward overhead, with a dark rounded vignette;
respawn after ~1-3.5 s; Thrasher "Hall of Meat" points count while floating.
Retail water close up: even steel blue-grey with fine dark streaks
(~10-20 cm) that shimmer in place (PCA loop) with a slow drift.
- **Board floats** (`apply_board_drag`): besides water drag, board parts in
water get buoyancy that cancels gravity with the part centre at the surface,
rising linearly to 3 g at 5 cm below and zero 5 cm above. Trace (Aletown):
deck settles at 8.91 against an 8.93 surface. Project-chosen values.
- **Ripple scale:** family 33 (`water.alpha`: DownTown fountains, Aletown canal)
uses 4x the decoded normal-map scale. Compared with `--verify` captures (scratch
camera mod aimed at the canal) against the RPCS3 frames: 1x gives ~1 m blobs,
4x matches the streak size, 8x is too fine and noisy. Colour/contrast still
differ (ours darker navy with bright reflection bands; retail an even steel
blue). Project choice; the user asked for a loose match.
- **Water camera (final):** `camera/water.rs` `WaterView`, applied to the final
frame in `CameraRuntime::advance`. Driven by the physics water state, not
proximity: `physics/camera_output.rs` passes the wipeout's `surface_height`
while in a water bail (`WipeoutGround` + `special_surface`). User report: the
earlier proximity test (water surface within 0.3 m under the root) fired while
standing on DownTown's fountain walkway, because water triangles reach under
it. The shot: 3 m above the water, 1.75 m behind the skater (60 degrees down),
drifting to 0.9 m (about 73 degrees) over 6 s, aimed 0.2 m above the root;
blends in over 0.25 s and out over 0.5 s; direction fixed at entry. A camera
under any water surface is still lifted 0.3 m above it.
- **Vignette:** the shot's weight (x0.85) goes through
`retail_exposure` (`Settings.timing.z` -> meter compute -> `state.w`) to the
tone pass (`retail_tone.wgsl`), which darkens the edges
(`smoothstep(0.55, 1.3, |uv*2-1|)`), corners nearly black as in retail.
- **Splash:** `water_splash.rs` (`WaterSplashPlugin`). Setup extracts the
game's particle sprites from the owned disc
(`tools/asset_pipeline/particles.py`, environment group: `miscboot.big`
`particletextures.rx2`, names from the `<name>.Texture` strings in texture
order: steam, dust, pebble, grass, leaf, fluff, cameraflash, water) to
`assets/private/particles/*.png`. On the frame the skater root or the board
deck enters **deep** water moving down faster than 1 m/s, a plume of `water`
sprites spawns at the surface: 13 x strength sprites (strength = speed/8,
0.4-1.2; board x0.45), random roll and spin, rising 1.6-3.8 m/s, spreading
0.4-1.6 m/s, drag and light gravity, growing 0.8-1.3 -> 1.8-2.8 m, alpha
0.45-0.72, life 0.55-0.85 s; unlit alpha-blended `StandardMaterial` quads
billboarded to the gameplay camera. No splash in shallow water (retail shows
none). A first version with a generated soft blob plus droplet dots "looked
like snow" (user); the retail sprite fixed that; the first sprite version was
"a bit strong" and was reduced (18 -> 13 sprites, lower alpha/brightness).
Without the sprite file there is no splash (logged).
- **Water colour (tried, rejected):** adding a steel-blue body colour under the
lighting and toning reflections down (strengths 1-3) made the water milky and
flat; the user judged it worse, so it was removed.
- **Water look (contrast, not colour):** measured water-only crops of the
RPCS3 canal frame (`rpcs3_2lxnl5eGDi.gif` frame 0) against our capture from
the same side of the canal. The mean colour already matched, which is why
adding a body colour only washed it out. Contrast was the difference:
| | mean sRGB | luma p5/p50/p95 | broad stdev (1/8 scale) | fine detail (vs 4 px blur) |
|---|---|---|---|---|
| retail | 71, 84, 95 | 56 / 84 / 93 | 6.3 | 5.3 |
| before | 81, 89, 100 | 30 / 89 / 140 | 28.7 | 11.8 |
| final | 75, 89, 100 | 74 / 86 / 105 | 7.1 | 5.2 |
Rendering one shader term at a time showed that the broad bright and dark
bands come from the environment-cube reflection. The lightmap, diffuse and
alpha terms are even. Final changes, family 33 only (`retail_world.wgsl`,
all project choices matched to the footage and approved by the user in play):
- **Cube blur:** the cube is read 3 mips blurrier. Tested +2/+3/+3.5/+4/+6/+9:
+3 matched the broad and fine statistics, and +4 or more was flat.
- **Tint:** the reflection is multiplied by (0.82, 1.0, 1.04). Unmodified, it
read grey (user: "not quite the same colour").
- **Anti-tiling and swells:** the normal used one fine layer at the 4x ripple
scale, which tiled visibly over large stretches (user screenshots of the
DownTown fountain). The normal is now the fine PCA wave plus the same wave
from a second sample (rotated 37 degrees, 0.613x scale, offset), plus 2x
the large slow layer's deviation (broad swells). The user picked this
variant ("less flat water looked really good").
- **Smaller bodies move less (user request):** `water_bodies.rs` groups the
triangles of family 33 materials that share vertex positions into bodies,
because a map splits one body into chunks on a 100 m grid. Each material
gets its body's area in `WorldParams.decal.y`. The shader scales
`size = log2(area / 100) / log2(40)` (0 at 100 m², 1 at 4000 m² and up):
fine waves x(0.6 + 0.4 size), swells x size². DownTown bodies: Aletown
canal 4368 m² (5 chunks, full motion), DownTown fountain 1268 m²
(size 0.69), others 99-4599 m². University's fountain channel is family
30 and unchanged.
- **Slower waves (user request: canal "a tiny bit too fast"):** the PCA wave
animation (30 frames at 30 Hz, shared with the ocean) now has a second copy
for family 33, `FrameStateData.pca_slow`. It runs at 0.75x
(`WATER_PCA_RATE`), interpolated between frames (PCA weights combine
linearly) and looping from the last frame into the first. The ocean keeps
the retail rate. The frame state grew from 144 to 256 bytes.
- **Tried and dropped:**
- Dark streaks from the reflection dipping 0.05 above flat. They matched the
canal statistics, but at steeper views (the fountain) they became
repeating blotches.
- A version keyed on normal tilt gave crescent shapes.
- A horizon threshold on the reflection elevation never triggered.
- Method: a temporary env hook in `FrameStateData.clock.w` picked the term or
variant without a rebuild, then was removed. The statistics script crops
water only, with no walls or walkway. Body areas came from a temporary
log.
- **Captures without the user:** `SKATE_VERIFY_AT` (seconds, default 4) sets when
`--verify` takes its screenshot. With a scratch mod that teleports the skater
into the canal (or calls `sdk.camera.set`) this captured the splash, camera
and vignette at chosen moments.
- Trace note: skeleton part 0 ("root") does not collide; judge penetration by
parts 1..23 (an early reading of root height wrongly suggested tunnelling).
Maps without water have an empty water list, so nothing changes there
(`check_maps.py`: all 10 maps ok, collision triangle counts unchanged).
First in-play test of this (user GIF, walking into the DownTown fountain on
foot): the skater stood on the water briefly ("like cement"), then sank, and
the camera followed the body under the surface, showing only the underside of
the water. Two more changes:
- **On foot:** on-foot ground support does not come from contacts but from
query scenes, which still treated water as floor. They now skip water too:
`offboard/contact_toolkit/world.rs` (`line`, `nearby`) and
`offboard/ground_query/lines.rs` (biped ground lines).
- **Camera:** `camera/water.rs` `WaterView`, applied to the final frame in
`CameraRuntime::advance`. While the skater root is in water (from 0.3 m above
water (any depth: a deep-only version let the low bail shot dip under the
5 cm channel's surface, user GIF), the camera eases to at least 1.8 m above the surface, 3 m
further back horizontally (first tuned 1.2 m / 1.5 m; user: still too close), and is re-aimed at the skater (blended by how far it
moved). A camera under water for any other reason is lifted 0.3 m above the
surface. It lifts fast (0.1 s) and settles back slowly (0.35 s). Values are
project choices; the retail footage only shows the camera pulled back above
the water.
Headless trace (`tests/water_drop.rs`, ignored diagnostic: drop into
University's fountain basin): the bail starts at the surface; the body sinks to
about 0.5 m, buoyancy brings it back to the surface, and it settles about 0.7 m
down, with the top of the body just above the water, until the respawn. The
camera ends at surface + 1.2 m (before the retune). At that spot the board rests on a solid concrete
ledge 5 cm below the water surface (`query_thin_line` under it: water 67.942,
concrete 67.888, floor 66.099), so it does not sink further; elsewhere it sinks
to the floor.
### Water rendering: extract the ocean animation table from default.xex
@@ -183,6 +392,16 @@ that in `clock.z`, used only by the water path (families 30/33); family 14 keeps
real time (its retail time source is unconfirmed). Behaviour re-implemented,
not copied; the disassembly was reference only.
The 5-unit restart then showed as a hard reset every 10 s (user): each scroll
layer jumps by speed × 5 (0.05 tile for still water, 0.5 tile for flowing
water's 0.1 layer). The PCA animation is not involved (its 29→0 step equals a
normal frame step). Project choice: keep the half-speed rate but loop over
1000 units (≈33 min). Every authored scroll speed (render-parameters
`water[1]`: 0.01, 0.2, 0.1; ocean 0.4, 0.22) is a multiple of 0.001, so each layer
completes whole tiles per period and the restart is invisible; t stays small
for f32 precision. A unit test checks the rate and that every authored speed is
seamless.
### University water looks darker than DownTown's (data, not a bug)
`RENDER_AT` shows the materials at each test spot: University fountain
@@ -209,7 +428,7 @@ No retail reference was found to compare; the user accepted the look for now.
- `tools.asset_pipeline.test_ocean_pca`: runs `convert` through the real
`spawn()` (text-mode pipes) for success and failure.
- `retail_render` tests pass (water time unit test included) except
`sky_shader_validates`, a known upstream failure.
`sky_shader_validates`, which was a known upstream failure (since fixed, doc 10).
- Asset-backed wipeout tests (`--ignored wipeout`): 4 pass; `marker_reply_restores_on_foot`
fails identically with these changes stashed (pre-existing).
@@ -217,9 +436,8 @@ No retail reference was found to compare; the user accepted the look for now.
1. Where does retail write `Collision+3481` / `+28`? The wiring above is the
best match to the evidence; it is not confirmed against retail.
2. Water triangles are solid one-sided surfaces in our collision world. Does the
retail board/body pass through type 12, or rest on it? (In play: does the
skater stand on the University reservoir?)
2. Answered: water is not solid in retail (user footage). Implemented above; drag
value and the 4 m depth limit are project choices.
3. Industrial's sea: retail respawned the player (user's memory), possibly
out of reach in retail. No collision data exists for it; see section 4.
5. Water rendering (resolved, see above; kept for the record): static texture on the fountains, black on the
@@ -233,9 +451,13 @@ No retail reference was found to compare; the user accepted the look for now.
normal encryption and LZX compression, and setup never unpacks it. Fallback
family 1 shows the static diffuse; `ocean.default` has no diffuse, hence black.
This affects upstream users equally.
6. Splashes and impact ripples when the player hits water: not implemented.
The executable has a `cWaterEffect` class; the engine has no particle/effect
system for it yet.
6. Splash: done (entry plume from the retail sprite). Retail shows no ripple
rings. The Thrasher "Hall of Meat" counter seen while floating in retail is a
separate scoring feature, not checked here.
7. `water.alpha` look: blurred and tinted cube, anti-tiled normal with swells,
calmer small bodies, waves at 0.75x (see above). The user approved the
canal look; the size calming and slower waves are waiting on their in-play
check.
4. What is surface type 13 (DownTown 88, University 17,790 triangles)? It may be
related (shallow water or a splash surface) or something unrelated, such as grass.
@@ -245,8 +467,18 @@ No retail reference was found to compare; the user accepted the look for now.
- `crates/skate-game/src/physics/player_input/mod.rs` (`publish_water`, unit test).
- `crates/skate-game/src/physics/frame.rs` (call site).
- `crates/skate-game/src/physics/wipeout.rs` (water bail request).
- `mods/water-test-teleport/` (dev-only test mod: F2/F3/F4 into the water, Shift+F2/F3/F4 view spots; not committed, not for upstream).
- `crates/skate-game/src/retail_render.rs` (frame state written in place, `water_time`, per-shader fallback log), `retail_world.wgsl` (water uses `clock.z`).
- `mods/water-test-teleport/` (dev-only test mod: F2/F3/F4/F7 into the water, Shift+key view spots, F5 position readout; the "Teleported" line clears after 5 s; committed on the fork for testing, dropped from the upstream branch).
- `crates/skate-core/src/physics/board_world.rs` (`is_water_tag`, water skip in `query_primitives`, `water_surface_at`) and `board_world/tests.rs` (`water_is_not_solid_but_reports_its_surface`).
- `crates/skate-game/src/physics/water.rs` (new), wired from `physics.rs` (`finish_skater`), `skeleton_feedback.rs` and `frame.rs`.
- `crates/skate-game/src/camera/water.rs` (new), `camera/runtime.rs` (`water` argument, `water_vignette`), `camera.rs`, `physics/camera_output.rs` (water bail state).
- `crates/skate-game/src/retail_exposure.rs`, `retail_exposure.wgsl`, `retail_tone.wgsl` (vignette).
- `crates/skate-game/src/water_splash.rs` (new), `main.rs`, `app.rs` (plugin).
- `tools/asset_pipeline/particles.py` (new), `test_particles.py`, `asset_exports.py`, `versions.py` (environment group).
- `crates/skate-game/src/verification.rs` (`SKATE_VERIFY_AT`).
- `crates/skate-game/src/physics/offboard/contact_toolkit/world.rs`, `offboard/ground_query/lines.rs` (water skipped for on-foot support).
- `crates/skate-game/src/tests/water_drop.rs` (ignored diagnostic), registered in `physics.rs`.
- `crates/skate-game/src/retail_render.rs` (frame state written in place, `water_time`, per-shader fallback log), `retail_world.wgsl` (water uses `clock.z`; family 33 ripple scale, cube blur and tint, anti-tiling and swells, size calming, `pca_slow`), `retail_material_bindings.wgsl` (`FrameState.pca_slow`), `retail_character.rs` (test initialiser).
- `crates/skate-game/src/water_bodies.rs` (new: water body areas, tests), `main.rs`.
- `tools/asset_pipeline/test_ocean_pca.py`.
- `crates/skate-data/src/xex/{mod,aes,lzx}.rs`, `crates/skate-data/src/ocean_pca.rs`, `crates/skate-data/src/lib.rs`.
- `crates/skate-data/examples/xex_unpack.rs` (diagnostic: unpack + locate table).
+9 -1
View File
@@ -14,6 +14,8 @@ verification, open questions).
| D | Gameplay data | Skip collision volumes that have no surface IDs | [05](05-collision-volumes.md) | `dec7ade` | — | Draft upstream [#25](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/25) |
| E | Performance | Indexed stock collection lookups (game startup −5.5 s) | [07](07-collections-index.md) | `810defa` | — | Draft upstream [#26](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/26) |
| F | Tooling | Streaming map validator (`--validate-maps`) wired into setup | [06](06-map-validator.md) | `18f41a3` | E (speed only) | Draft upstream [#28](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/28) |
| H | Gameplay + rendering | Water: detection and bail, shallow water solid / deep water floats, board floats, water camera + vignette, entry splash, water look (family 33 cube blur + tint, anti-tiling, body-size calming, slower waves), animated water (frame-state buffer fix, ocean PCA from default.xex, XEX2 unpacker), ripple scale | [09](09-water.md) | `gameplay/water` branch (`af1b350` onwards) | — (copies #28's `install.py` `spawn()` split) | Prepared 2026-10-01, not opened: applies to upstream `60efdef`; failing tests match upstream exactly |
| I | Test fix | `sky_shader_validates`: add the `VERTEX_POSITIONS` shader def Bevy sets for real meshes | [10](10-sky-shader-test.md) | on `gameplay/water` | — | Not opened; tiny, can go upstream alone |
| G | Performance (setup) | Skip decoding duplicate stream copies; run the customiser beside the maps; parallel clothing library and pro roster, plus a native RefPack DLL in `Build.ps1` | [08](08-setup-performance.md) | `8327e94` (+ overlap hunks of `install.py` in `18f41a3`) | — | Draft upstream [#29](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/29) |
Opened 2026-10-01 as drafts from per-PR branches cut from upstream `60efdef`
@@ -47,7 +49,13 @@ Notes for whoever opens them:
skate-game `production_factory_routes_three_handlers_and_all_five_conditions_to_grind_owner`,
`embedded_static_rwcm_hits_distinct_actor_query_ids`,
`pipelines_accept_valid_group_outputs_when_fingerprint_changes`,
`sky_shader_validates`; and three skate-data examples that do not compile
`sky_shader_validates` (fixed on `gameplay/water`, see
[10](10-sky-shader-test.md)); and three skate-data examples that do not compile
(`apt_data`, `hud_data`, `scoring_flow_data`).
- PR H includes setup changes (environment group: `ocean_pca.py`, `particles.py`)
that refresh that group once, and a dev-only mod (`mods/water-test-teleport/`)
that must be dropped from the upstream branch. The frame-state buffer fix
(`retail_render.rs` `write_frame_state`) also unfreezes family-14 scrolling and
the shadow floor, so it could go upstream on its own first.
- Fork-only commits not meant for upstream: `167605a` (ignore the local
`.claude/` workspace) and `c2be42b` (docs index; the docs travel with each PR).
+2 -1
View File
@@ -14,7 +14,8 @@ Each document stands alone. File paths are relative to the repository root.
| 3 | [SDL3 gamepad input](03-sdl3-gamepad-input.md) | Game (Rust), build scripts, vendored `sdl3-sys` | Done, verified in play with an Xbox Elite Series 2 |
| 4 | [Authored map spawns](04-map-spawns.md) | Asset pipeline (Python) | Done, all 10 maps confirmed in play |
| 5 | [Invisible collision volumes](05-collision-volumes.md) | Game data loader (Rust) | Done, all four affected maps confirmed in play |
| 9 | [Water](09-water.md) | Game physics (Rust), diagnostics | Water flag wired up (DownTown, University); awaiting in-play test |
| 9 | [Water](09-water.md) | Game physics, camera and rendering (Rust), setup, diagnostics | Matched to retail footage (RPCS3): shallow water solid, deep water floats, board floats, water camera + vignette, entry splash, canal water look matched, small bodies calmer |
| 10 | [Sky shader validation test](10-sky-shader-test.md) | Game tests (Rust) | Done; all six shader validation tests pass |
## Environment used for verification
+27 -2
View File
@@ -2,7 +2,7 @@
-- collision (centroids from `WATER_POINTS=1 cargo run -p skate-data --example
-- water_surfaces`). Shift+F2/F3/F4 stand on dry ground facing that water
-- (`WATER_VIEW=x,y,z[,reach,rise]`). The University spots only make sense on
-- University, the DownTown ones only on DownTown. F6 is the game's camera key.
-- University, the DownTown ones (F4, F7) only on DownTown. F6 is the game's camera key.
local SPOTS = {
F2 = {
water = { label = "University fountain basin (water 67.94 m)", position = { 340.3, 69.94, -294.3 }, heading = 0 },
@@ -16,11 +16,35 @@ local SPOTS = {
water = { label = "DownTown fountain (water 18.72 m)", position = { 44.3, 20.72, 241.5 }, heading = 0 },
view = { label = "DownTown fountain, view", position = { 44.2, 19.49, 247.9 }, heading = 3.120 },
},
F7 = {
water = { label = "DownTown Aletown canal (water 8.93 m, 1.1 m deep)", position = { -182.3, 10.93, 465.9 }, heading = 0 },
view = { label = "DownTown Aletown spawn, facing the canal", position = { -183.4, 12.76, 433.2 }, heading = 0.034 },
},
}
local held = {}
local show_position = false
-- Seconds the "Teleported" line stays on screen.
local MESSAGE_SECONDS = 5
local message_timer = 0
return {
on_update = function()
on_update = function(event)
local dt = (event and tonumber(event.dt)) or 0
if message_timer > 0 then
message_timer = message_timer - dt
if message_timer <= 0 then sdk.ui.text("water-test", "") end
end
-- F5: toggle an on-screen position readout (to report water locations).
local f5 = sdk.input.down("F5") == true
if f5 and not held.F5 then
show_position = not show_position
if not show_position then sdk.ui.text("water-position", "") end
end
held.F5 = f5
if show_position then
local p = sdk.player.read().position
sdk.ui.text("water-position", string.format("Position: %.1f, %.2f, %.1f", p[1], p[2], p[3]))
end
local shift = sdk.input.down("ShiftLeft") == true or sdk.input.down("ShiftRight") == true
for key, spot in pairs(SPOTS) do
local down = sdk.input.down(key) == true
@@ -28,6 +52,7 @@ return {
local target = shift and spot.view or spot.water
sdk.player.teleport({ position = target.position, heading = target.heading, velocity = { 0, 0, 0 } })
sdk.ui.text("water-test", "Teleported: " .. target.label)
message_timer = MESSAGE_SECONDS
end
held[key] = down
end
+1 -1
View File
@@ -4,6 +4,6 @@
"name": "Water Test Teleport (dev)",
"version": "0.1.0",
"author": "Hails",
"description": "Dev only, for branch gameplay/water: F2 University fountain basin, F3 University reservoir, F4 DownTown fountain drop the skater into the water; Shift+F2/F3/F4 stand on dry ground facing it. F6 is the camera key.",
"description": "Dev only, for branch gameplay/water: F2 University fountain basin, F3 University reservoir, F4 DownTown fountain, F7 DownTown Aletown canal drop the skater into the water; Shift+F2/F3/F4 stand on dry ground facing it. F5 toggles a position readout. F6 is the camera key.",
"entry": "main.lua"
}