Files
EscapistsReintroduced/docs/convoy-migration.md
T
jakub 1b1a8b5173 Add mission customization, HQ support and aggression-driven AI
Integrate faction and random settings menus, generated objectives, scouts, convoys, air support, mortar stations and body-intel recovery. Add identified-body aggression, finite hunter UAZ deployment, dedicated objective defence and maximum AI skill with separate reduced aim accuracy. Include policy tests, native probes, evidence and documentation.
2026-09-23 15:07:14 +02:00

180 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Finite physical convoy controller
> Superseded production behavior: see [Supply convoys](supply-convoys.md) for the original default-three fleet, full troop truck, base circuit and dismount/reboarding implementation. The evidence and implementation notes below describe the earlier single-convoy stages.
Independent adaptation of owned `escapists-ai/Scripts/Game/EscapistsAI/EAI_SupplyConvoys.c`, SHA-256 `a896fdacfd9c0f2db52e588642623545a3a5d6e8041fb72000a68e720fc2b7a5`. Reused responsibilities are the six-vehicle catalog/order, native seat creation, independent native crew groups, finite cargo and owned-waypoint release. Original Escapists/ScrtCore helpers, original game mode hooks and `EAI_GroupLookup` are excluded. Native `BaseCompartmentSlot.SpawnCharacterInCompartment`, group vehicle manager and waypoint APIs replace those dependencies.
The round owns one `ERR_ConvoyPool(mode,maxConvoys)` and one `ERR_ConvoyService(mode,pool)`. Reserve a unique authored source ID; dispatch its canonical one-use receipt with six authored positions/angles and a sealed, nonlooping Core `ERR_ForceRoute`. Resource, terrain/water/obstacle, faction and shared budget validation precede consumption. Consumption precedes native entity creation. Partial native startup consumes the slot and preserves every successfully created group, vehicle and actor; there is no refund or automatic retry/replacement.
The exact composition is PKM UAZ, ammunition Ural, troop Ural, PKM UAZ, BMP-1, PKM UAZ. It allocates 19 bodies: three UAZ driver/gunner pairs, one ammunition-truck driver, troop-truck driver plus eight infantry, and BMP driver/gunner/commander. Capacity failure does not shrink this plan. The selected own memberless USSR group and vanilla character catalog are explicit; other factions require a reviewed catalog. BMP driver, gunner and commander seat declarations were independently inspected in the installed WCS PAK; [convoy-bmp-seat-audit.json](convoy-bmp-seat-audit.json) records resource-byte hashes and declarations without redistributing assets.
Outstanding receipts plus physical, noneliminated Core ledger strength must fit 60 bodies; ledger records plus outstanding convoy groups must fit 128 formations. The same exact group moves from outstanding budget to its CONVOY record before normal mode registration. A 40-body world can reserve one full 19-body convoy, giving 59. Use one allocator for the round; creating independent pools would not share outstanding reservations. The fixed convoy limit and consumed source IDs survive losses within that pool.
The controller waits up to 30 seconds for exact original native crew membership and vehicle registration. Once ready it issues native move waypoints along the supplied finite road route. Each vehicle retains one owned waypoint at a time; arrival advances once, a ten-minute leg deadline releases stalled orders. Death, captured/reparented crew, destroyed vehicles and explicit Stop release orders without deleting physical entities. A player entering any convoy vehicle or crew releases the convoy task. Native combat may interrupt movement. No perception information or reinforcements are invented here.
The ammunition truck receives one bounded pass of eight AK74 and 48 matching magazines. Native capacity or failed operations may reduce actual cargo. Accepted asynchronous operations are never repeated or replenished. Status separates native insertion completions, failures and pending callbacks; completions are not an inventory snapshot after looting. Native accepted insertions cannot be cancelled by these callbacks, including after a controller Stop.
This is a partial convoy migration. HQ now exposes opt-in preparation/dispatch for the authored supply seed; native vehicle driving and physical cargo evidence remain separate requirements. Original two-team infantry dismount/flank/reboard tactics, delivery/unloading, rearming, route/base selection and Cylon gunner specialization are not claimed by this slice. No autonomous convoy spawn timer or unsupported convoy setting is installed.
Tests execute actual shared-budget, dispatch, seat allocation, readiness admission, cargo request and waypoint lifecycle bodies against native API doubles. They prove bounded/idempotent policy and partial-failure ownership; they do not prove native seats, AI driving or multiplayer replication.
## Road preparation and clearance
`ERR_ConvoyRoadPlan.Build(seed, out positions, out angles, out route)` selects deterministically among actual native roads within a 500m query. It refuses more than 128 road candidates, widths below 4m, polylines over 1024 points, and roads shorter than 390m. Each road gets at most 33 candidate formations: the preferred projection followed by offsets +35m, −35m, +70m, −70m, up to ±560m along that same polyline. Offsets outside the valid start interval are refused rather than clamped into duplicate formations. Every one of the six starts and the sampled formation center must lie within 500m of the explicit seed. Eligible candidates are ranked by formation-center distance and deterministic geometry ties before expensive clearance queries when a better clear candidate already exists. This bounded scan can find clear alternatives to an obstructed initial projection; it is not an exhaustive search of all possible formations.
Six starts remain 35m apart along the actual polyline with a 15m rear margin and at least 200m forward route; every intermediate bend is retained, with refusal at the Core route's 64-point limit. Tight bends that place any two starts less than 18m apart are rejected. Native terrain grounding preserves the road XZ coordinates. There is no random, offroad or scenery-removal fallback.
Each oriented start checks nine terrain/water samples across a conservative 4m by 9m footprint. Terrain must be above 0.3m, vary by no more than 0.75m across the footprint, and agree with the starting altitude. The enclosing volume extends from 0.05m above the lowest grounded sample to 3.5m above the highest. A filled native `TraceBox` checks that volume with a 0.01m upward sweep against entity and ocean geometry; a nonfinite result or trace fraction below one refuses placement. An entity AABB query remains bounded diagnostic context only: overlapping bounding boxes or its visit cap no longer veto a geometrically clear footprint. These admission rules do not guarantee that native drivers can negotiate the whole road.
The focused road/placement tests execute the installed method bodies with geometry and native API doubles. They cover exact minimum geometry, reversed direction, offset ordering/refusal, locality of all selected starts, an obstruction requiring an alternative formation, degenerate and dense polylines, bend retention, tight-hairpin rejection, deterministic ties, rotated footprint bounds, terrain/water rejection and filled-volume collision results. Native-query doubles distinguish a tree's overlapping broad bounding box from an actual blocking shape.
The first native convoy run compiled all scripts but refused the authored supply seed before spawning entities (`native-2026-09-20-020706-convoy-road-refusal`). Road diagnostics subsequently found valid long roads. The placement diagnostic archive `native-2026-09-20-021626-convoy-placement-diagnostic` identified broad tree bounding boxes 6–12m outside the pavement and overhead power-line bounds as false positives; actual sampled road terrain spans were 0.10–0.73m. That evidence motivated the filled-geometry check without relaxing terrain limits. The later crew/cargo run below validates selection and a real-vehicle collision positive control; full convoy driving remains unproved.
## Preventing queued default crew
Native readiness archive `native-2026-09-20-023545-convoy-readiness-regression` exposed at least six native agents in every group, including vehicles intended to have only one, two or three crew. The vanilla faction group `Group_USSR_Base.et` authors six soldier slots (inspected resource SHA-256 `77a7c5caee98e13ba45204d1084636f4bf50f9414e2b048e43a60e1966535e96`), and native `SCR_AIGroup.EOnInit` queues those slots asynchronously. Checking that group for zero agents immediately after spawn did not exclude its pending default allocation.
The convoy now uses independently authored `{7A968AB297475FA7}Prefabs/ERR/ConvoyCrew.et`, inheriting the memberless vanilla `{000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et` (inspected SHA-256 `a8defc28500877cdd215f9c41d1eb003359f9455b1b063c5b8f15c644958c889`). It declares USSR faction, disables immediate spawning and has no authored slots before native initialization. A strict runtime template guard checks all three conditions—no immediate spawn, no agents and no authored slots—before finite seat allocation. It neither deletes unexpected soldiers nor cancels another group's spawn queue. Actual-method and resource regressions pass. The subsequent engine run confirms exact post-initialization membership as described below.
## Native crew and cargo checkpoint
[02:40:35 crew/cargo run](evidence/native-2026-09-20-024035-convoy-crew-cargo/report.json)
passed 109 assertions before a deliberate interruption, with no script/runtime
failures. All six original vehicles retained exactly 2/1/9/2/3/2 native seated
members, totaling nineteen, and six new Core ledger records. The actual truck
inventory contained eight new AK74 rifles and at least forty-eight matching
magazines after the single finite cargo batch. Repeated dispatch and a second
reservation were rejected. A filled collision query against the actual lead UAZ
returned a blocking fraction of zero, while road placement had accepted the empty
formation positions.
The lead drove approximately 51.8m, but the minimum vehicle displacement stalled at
8.0m. This does not satisfy the fixture requirement of every vehicle moving20m
and the lead100m. The run was interrupted through the runner's cleanup handler
after sustained stagnation; it has no completed smoke round. Four external
localization errors remain. Source and external files were unchanged and owned
process cleanup was confirmed. Per-vehicle driving diagnosis is the next step;
this checkpoint does not qualify delivery, combat, unloading or multiplayer.
## Matching native waypoint completion
[02:46:43 movement diagnostics](evidence/native-2026-09-20-024643-convoy-native-completion/report.json)
identified the stall: the lead, troop truck and BMP had no current native waypoint
and had switched to idle, while their retained owned waypoints still reported
native group completion. Vehicle-origin distances were35.5m,38.5m and37.7m.
The controller's separate vehicle-centre test against35m therefore missed valid
native completion. It now uses the owned waypoint's
`IsWithinCompletionRadius(Group)`, matching the stock group waypoint decorator.
The authored35m radius, original-crew validation, finite route and one-owned-order
rules stay in place. Focused actual-method regression verifies progression after
native removal, exactly one next waypoint and no duplicate advancement; updated
native driving validation is recorded below.
## Completed native driving check
[02:50:35 convoy driving](evidence/native-2026-09-20-025035-convoy-driving/report.json)
completes one scripted round with181 passed assertions and no script/runtime
failures. All six original vehicles drove at least20m and the lead over100m,
without fixture movement. Exact original seated membership, all six Core records,
the finite eight-rifle/48-magazine cargo batch and repeated-dispatch rejection
were verified again. The result includes subsequent native prisoner death,
spectator transition and mission cleanup. Source/external inputs stayed unchanged
and hidden, muted process cleanup was confirmed.
The same four external string-table errors keep the strict native qualifier
failed. This single short road run establishes the initial physical controller;
it does not prove full-route reliability, native combat/dismount/reboarding,
logistics delivery/unloading, multiplayer or FPS improvements.
## Delivered HQ mounted-cover follow-up
This follow-up adds per-vehicle HOLD/RESUME travel commands to the existing finite
convoy. It does not change the six-vehicle receipt, nineteen original crew,
finite initial cargo or opt-in manual dispatch. The earlier native driving
archive above predates these combat commands.
[HQ planning](../addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c) uses two delivered inputs:
a living, nonclosed original crew's own status position no older than 180 seconds,
and a positive sighting less than 60 seconds old within 400 m of that reported
position. Exactly 400 m and exactly 180 seconds are accepted; exactly 60 seconds
is no longer a planner contact. The executor permits a HOLD report age up to
60 seconds, but HQ rechecks its stricter current-contact rule at delivery.
Neither the planner nor a silent crew substitutes a live vehicle or hidden enemy
position for those reports. Body/distress beliefs do not become convoy fire targets.
Each original crew uses its existing shared HQ downlink. A queued
[combat command](../addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c) contains the
convoy source ID, original group, vehicle index, monotonically increasing command
ID, originating sighting ID/time, issue time and an expiry at most 30 seconds
later. Queuing does not stop travel. Only successful physical radio delivery can
reach the executor; it rechecks current contact evidence, own-status freshness,
canonical consumed receipt, matching physical Core record and exact original crew.
Foreign, duplicate or expired commands cannot replace the current order. A newer
nearby sighting still justifies an in-flight HOLD, so reports arriving faster than
the downlink cannot starve cover delivery. A superseded RESUME is rejected.
An accepted HOLD removes only that vehicle group's owned move waypoint and
preserves its route index. A newer delivered sighting can refresh the held
lineage without repeatedly clearing waypoints. A RESUME is considered only after
60 seconds since the held sighting, with fresh own-position status and no current
qualifying contact. It must match the held sighting ID/time. New contact arriving
while the downlink travels invalidates an older RESUME; a failed HOLD refresh
cannot accidentally authorize it. Missing radio or stale own status retains the
current travel/hold state. There is no independent timeout that silently resumes
a held vehicle. A successful RESUME creates one native move waypoint at the
preserved route index. Failed native recreation consumes that command ID and
releases the vehicle's order instead of retrying the same command.
At admission, [ConvoyService](../addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c)
calls the native `utility.AddUsableVehicle(usage)` helper after vehicle-manager
admission. This registers the native deletion/damage callbacks and mounted combat
activity omitted by raw manager insertion alone. Native perception, weapon aiming
and firing remain the engine's responsibility. HOLD supplies no target coordinates
to a gunner and does not prove that the gunner fires or suppresses a player.
This is mounted cover, not migrated infantry dismount/flank/reboard tactics.
Player occupation of any convoy vehicle or crew still stops the whole task.
Release clears owned orders and temporary forced detail while leaving vehicles,
weapons, cargo, casualties and survivors physical. HOLD/RESUME introduces no new
crew/vehicle spawn, ammunition grant, cargo refill or replacement receipt.
The separate [small-arms status model](hq-ammunition.md) does not estimate mounted
vehicle ammunition or provide convoy rearming.
[Combat executor tests](../tests/test_convoy_combat.py) and
[HQ radio/planner tests](../tests/test_hq_convoy_combat.py) execute the actual
methods against boundary doubles. They cover freshness, lineage/replay, shared
pending downlinks, changed evidence in transit, owned waypoint hold/resume,
original crew/ledger identity, capture and failed recreation. These are policy
regressions, not native mounted firing or multiplayer evidence.
The [04:11:50 native driving recheck](evidence/native-2026-09-20-041150-convoy-cover-driving/report.json)
compiles this follow-up and completes one round with 181 assertions and zero
script/runtime failures. All six vehicles move at least 20 m, the lead exceeds
100 m, and the original nineteen seat occupants, six records and finite truck
cargo remain intact. This includes the native mounted-combat registration but
**does not exercise a combat HOLD/RESUME or prove firing**. Those transitions
still need a direct native scenario. Source and six external dependencies stayed
unchanged, and hidden/muted process cleanup was confirmed. Four external
localization errors keep strict native qualification failed. Full-route,
dismount/flank/reboard, unloading, multiplayer and FPS work remain outstanding.
## Cover test and seat-retention diagnostic
The opt-in `--smoke convoy --convoy-cover --rounds 1 --timeout 900` test first requires the existing physical driving/crew/cargo proof, then moves only the canonical local prisoner beside the original lead vehicle. It observes genuine perception, completed uplink, HQ HOLD, completed downlink and owned-waypoint removal, conceals that same prisoner at a distant authored site, and waits for ordinary evidence expiry and delivered RESUME followed by 20 m of physical travel. Temporary player damage protection is restored on success, refusal or shutdown. No AI, ammunition, reports, radio routes or production timers are created or altered by the cover arrangement. The cover-only smoke timeout is 840 seconds; ordinary convoy timing remains unchanged.
[05:09:06 diagnostic](evidence/native-2026-09-20-050906-convoy-seat-diagnostic/report.json) compiled the current addon sources and passed 170 assertions, but failed the final driving-stage population check: original crew member 18, the final UAZ gunner, failed the combined conscious/original-seat/identity assertion. Exact group membership still matched the six-vehicle plan. That combined failure alone cannot distinguish unconsciousness, a seat switch, dismount or another predicate; failure-only diagnostics now record each condition without changing the assertion. The cover arrangement never started; this run does not validate HOLD/RESUME. The failure is retained without weakening the seat check. Four installed RHS/WCS localization errors also remain; private cleanup and unchanged launch sources were confirmed.
`test_native_convoy_cover_probe.py` executes the fixture's observation, snapshot, delivery and cleanup methods against native doubles, including rejected/failed radio routes, unapplied orders, unchanged HOLD refresh measurement, exact resumed route index, quiet age and damage restoration. Runner refusals occur before launch for an incompatible smoke mode or insufficient cover timeout. These policy tests do not replace the still-pending native cover sequence.
The [20 September 05:15:05 convoy cover run](evidence/native-2026-09-20-051505-convoy-cover-diagnostic/report.json) passed the baseline six-vehicle driving, original crew/seat and cargo assertions. After arranging the existing prisoner beside the lead vehicle, it captured no qualifying visual reports and failed the combined physical-force/player invariant about 34 seconds later. It therefore does not establish native HOLD/RESUME behavior, nor identify a production defect. The retained logs do not distinguish an ordinary completed route from a released vehicle, crew-state change, controller change or physical-force-list difference. The lead route advanced from index14 to18, but that alone does not establish task completion: production ends the task only when all six orders have arrived or been released, and the fixture allows an individual arrived vehicle. Failure-only diagnostics are now included for a future run; no additional convoy test was launched at this checkpoint.
## Nearby infantry supply follow-up
The [infantry resupply service](infantry-resupply.md) can reserve the existing ammunition truck for a reported nearby patrol. A reservation leaves driving active until the stop command arrives by radio. Delivery pauses its owned route waypoint, and cleanup resumes the same route index. This remains the one manually dispatched convoy; general cargo unloading, automatic supply dispatch and native resupply qualification remain unfinished.
## Automatic initial deployment
[Automatic convoy startup](convoy-startup.md) now starts the same canonical finite convoy by default after existing force admission. The saved on/off switch takes effect next round. The earlier manual native evidence above remains historical; current native evidence is linked from current-status.