# Track note: carrier (milestone M2, walk the carrier) Written by the Coder of the carrier track. Everything under "Works" was run in this copy (`.wt\carrier\TheDescentUE`) and the numbers are measured. ## State at the end of the task Build PASS, 0 warnings. `import_assets.ps1` PASS. `run_tests.ps1`: 35 tests PASS (28 old + 7 new). Scenarios PASS: `smoke`, `core_sim`, `kazah_showcase`, `kazah_closeups`, `m2_walk`, `m2_dry`, `m2_exterior`, `m2_moving_base`. ## What was built (files) * `Vehicles/CarrierLayout.*` (`FLayout`: 16 rooms, 15 doors, 7 windows, 15 station anchors, route graph, `HullRadius`, `IsDryLocal`, `RoomAt`), `CarrierMeshBuilder.*` (pure geometry builder, winding derived from normals), `CarrierBuild.*` (rooms, doors, hull, pool, fixtures, signs as pure functions), `CarrierBlockout.*` (`UCarrierBlockoutComponent`: components, collision, lights, signs, stencil and channels), `DescentCarrier.*` (`ADescentCarrier`, boot step `SpawnCarrier`, dry volume, stream focus, sim step 2, debug motion, `carrier` section). * `Systems/DescentFixture.h/.cpp`: `ADescentFixture` + 10 stub classes (helm, chart table, bed, nutrient port, vat, packer, storage, terminal, carousel console, ladder): prompt, E answers with a toast naming the milestone. * `Player/`: `DescentMode.h`, `DescentInteraction.*` (interface, registry, focus component), `DescentCharacter.*`, `DescentCharacterMovement.*`, `DescentPlayerController.*` (Enhanced Input made in C++, intent to the sim, modes Title and Foot, HUD model writes, boot steps `PlaceCharacter` 500 and `EnterFirstMode` 510, `player` section). Game classes registered at priority 100. * `Debug/DescentCommands_Player.cpp` (`Place`, `PlaceLocal`, `MoveTo`, `Look`, `Use`, `Mode`), `DescentCommands_Carrier.cpp` (`Motion`, `Stop`), `Scenarios_M2.cpp`; `Tests/CarrierTests.cpp`, `PlayerTests.cpp`; `Tools/ue/assets_35_carrier_materials.py`; `Core/Tuning/DescentTune_Carrier.h`, `DescentTune_Player.h`. ## Acceptance table (DESIGN 10, M2) | Row | Result | Evidence | |---|---|---| | `Descent.Carrier.Layout` | PASS | all 16 rooms' eight corners inside `HullRadius(x)`; all 15 doors join two different rooms; every room has lamps, a door, a stop point that `RoomAt` finds | | `Descent.Carrier.DryVolume` | PASS | `IsDry` true at all 16 room centres; false 1 m outside the hull (side, below, above, beyond the nose, stern taper) and 1 m below the pool surface | | `Descent.Carrier.Temperature` | PASS | 26.0 exactly inside (bridge, engine room), the water formula outside, through the real env-query seam with the carrier's provider | | `m2_walk` | PASS | real-input walk bridge > corr3 > stair landing > down the ramp > stair foot > galley > cargo > refinery > engine > bay gallery > bay floor; at each stop the room matches and feet z is 1.5 / -3.0 / -7.5 within 0.05; 16 shots `room_`, mean luma 0.196-0.447 (band 0.10-0.45; corr3 0.447, hab 0.444, fab 0.438 are close to the top); no rescue | | `m2_dry` | PASS for everything the carrier side owns; rest waits for the merge (below) | dry volume registered, eye dry, 26.0, HUD model `CABIN 26.0 °C`, 54 of 54 interior primitives with stencil 1 and lighting channel 1 only, 40 m outside not dry with the water temperature | | `m2_exterior` | PASS | `carrier.exterior_lights == 6`; `exterior_dark.png` (mean luma 0.060): one large dark hull with sail and mast, only the green nav light, the mast flash, the stern light, the pool glow and the flood beam on the seabed | | (extra, asked) `m2_moving_base` | PASS | see below | | fixture stubs show a prompt | PASS | in `m2_walk`: `E Sleep ...` at a bed, `E Jack in ...` at a port, `E Take the helm ...` on the bridge reach `FDescentHudModel::Prompt`; `Descent.Player.Use` answers with a toast | Pictures looked at by the Coder (in `Saved\Shots\`): `m2_walk_room_bridge`, `_stair`, `_bay`, `_galley`, `_engine`, `_q4`, `m2_exterior_exterior_dark`. Floors, walls, doors, ramp, pool and rails are where the layout puts them and nothing has a hole; the bridge windows show black because this copy has no water (the sea is the look track's); the reactor core is only visible through two slits. ## R2, walking on the moving carrier (`m2_moving_base`): plain character movement is good enough, the fallback was NOT needed Setup: `Descent.Carrier.Motion 2 0 0 5.73 10 8 T`: forward 2.0 m/s, yaw 5.73 deg/s (0.10 rad/s), pitch sine +-10 deg with an 8 s period (peak pitch rate 7.9 deg/s, faster than the design's ~4), roll -0.25 omega (1.43 deg). The carrier is moved with `SetActorLocationAndRotation(bSweep=false)` in sim step 2; the character uses the settings of DESIGN 3.1 (`bFastAttachedMove`, `bStayBasedInAir`, impart base velocity, tick prerequisite on the sim). Measured peaks equal the commanded ones. Fixed 1/30 s step. All numbers are CARRIER-LOCAL feet positions sampled every frame: * standing 15 s: drift 2.5 mm max, largest frame-to-frame step 2.5 mm. Stated tolerance 10 mm. * walking 16 m out and 24 m back along the corridor at 2.9 m/s: z deviation 6.6 mm, sideways 83 mm (steering), mean speed 2.75 m/s, peak 2.96 m/s, no stutter, no sliding. Tolerance z 20 mm. * up and down the 22.9 degree ramp while the hull pitches (slope up to 33 deg): at most 99.7 mm from the ideal ramp plane, which is the capsule's own lift on a slope (65 mm) plus the visual step blocks; never fell, never caught. Tolerance 120 mm. ## Deviations from the design, and why 1. Start position (41.8, 0, 1.5) instead of v2's (40.5, 0): the chart table (radius 1.1 at x 39.5) reaches x 40.6. 2. Couch of the habitation room is laid along X (against the -y wall) instead of v2's long side along Y, which poked through the wall. 3. A character outside the dry volume hovers (`MOVE_Flying`) instead of falling forever, and walks again inside; a fall out through the belly (below z -16 inside the hull footprint) is put back on the bridge. Reason: swimming is M3, and the old `smoke` scenario teleports "the pawn" and checks the position. 4. The pool gap in the railing is blocked by a low invisible barrier until M3 (swimming) exists. 5. The mouse look is written as raw counts x 0.12 deg per count; Enhanced Input is assumed to deliver raw counts for `Mouse2D` (not checkable without a mouse). 6. Hull shading is flat per facet (64 segments); the real hull model replaces it. 7. The trace channel "Placement" is used as `ECC_GameTraceChannel1` by number; the project ini does not name it (one line for the Administrator: `+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Placement")` in `[/Script/Engine.CollisionProfile]`). 8. Stairs: the collision is the design's smooth ramp wedge; the visible steps are 16 solid blocks without collision (up to 14 cm above/below the ramp). ## Calibration (read before the look track changes the exposure) All interior brightness was calibrated against a manual post-process `AutoExposureBias = 1.0` set by the scenarios' own environment (`Scenarios_M2.cpp`, `Tune::Carrier::CalibrationExposureBias`): lamp brightness unit 2700 (`DescentTune_Carrier.h`, console variable `descent.Carrier.LampScale` scales it live) and, in `assets_35_carrier_materials.py`, `EMISSIVE_NITS` 800 and `AMBIENT_NITS` 15. If the final bias is B, multiply all three by 2^(1 - B), re-run `import_assets.ps1 -Only carrier -Force` and the `m2_walk` shots. The design's relative lamp intensities (0.9-1.5, flood 5.0, nav 0.4) are kept. ## Waits for the merge (printed as `WAITS FOR MERGE`, not failures) * `m2_dry`: the `env` section (`env.state == "Dry"`, `env.volumetric_fog == false`, `env.snow_instances_visible == 0`, `env.temperature_c == 26.0`), `Descent.Look.Set WaterPP 0`, and the requirement that the window region of `bridge_water_on` and `bridge_water_off` differ by more than 0.01. The interior-region comparison (< 0.01) is written and runs, but is trivially 0.0000 until `PP_Water` exists. The stencil value and the lighting channels are proven to be set on every interior primitive; that PP_Water honours the stencil is not. * The scenarios bring their own exposure, haze, seabed and a dim scenario-only "hull fill" light for the exterior picture; they stop mattering once `ADescentEnvironment` exists. ## HUD-model gaps None blocking. Written: `Mode`, `bUiWindowOpen`, `bCrosshair`, `Prompt`, `DepthM`, `DepthText`, `TemperatureC`, `TemperatureLabel`, `TemperatureText`. Not written (not mine at M2): `Band`, vitals, vehicle panel, compass. A title screen needs no field: the UI reads `Mode == "Title"`. ## Shared-file changes None. (`TheDescent.Build.cs` needed no new module; `DefaultEngine.ini` untouched, see deviation 7.) ## Not run, guessed, not finished * Not run: a real keyboard and mouse (E, F, WASD, mouse look and the Title click are wired through Enhanced Input but were exercised only through the intent path and `Descent.Player.*`); PIE in an editor window; a non-unity build (`-DisableUnity`). * Guessed: air control constant 3.0 (v2 had none), `MouseDegPerPixel` delivery, hull ambient (0.45 nits) and the pool water look. * Not finished (later milestones, by design): carousel motion and hoist, helm physics, swimming and the ladder, biomass, build mode, the packer/pipes, the fabricator and refinery as placeables, door animation. The 10 fixtures are stubs. The door labels are `UTextRenderComponent`s with the engine font; their legibility was only seen in passing.