Files
EscapistsReintroduced/docs/native-powered-flight.md
T

34 KiB
Raw Blame History

Native powered flight feasibility

This new WORKBENCH-only experiment uses the fixture pilot's native CharacterInputContext collective/cyclic/anti-torque inputs. It does not move an aircraft by setting velocity, angular velocity, transforms or angles, and does not copy original Escapists flight code. The initial probe compiles in archived 090203, but refuses all initial pad candidates before spawning its test aircraft. A later pad-search revision fails compilation in 090705; the corrected helper compiles in 091306 and the 128-point survey runs but refuses all candidates in 091819. The 208-point refinement compiles but refuses all candidates in archived 093319. The 377-candidate revision finds a safe airport pad in the 093749 run, then fails its immediate compound native-component/seat/fuel check before creating a pilot. Actual powered flight remains unqualified.

This supersedes the earlier aircraft audit's overly broad suggestion that no direct flight controls were exposed. A search confined to vehicle controllers missed the character input layer. There is still no demonstrated stock helicopter route/landing AI activity, but actual script-callable flight inputs exist:

  • Installed scripts/Game/generated/Character/CharacterInputContext.c:94–107: vehicle throttle, collective, cyclic forward/aside, anti-torque setters and getters.
  • scripts/Game/generated/Components/CharacterControllerComponent.c:82,473: GetInputContext and OnPrepareControls(owner, ActionManager, dt, player).
  • scripts/Game/Character/SCR_CharacterControllerComponent.c:1009: real script override of that native preparation callback. The opt-in hook calls its superclass first, then writes only the exact fixture-owned AI pilot's inputs. Whether that native AI preparation phase occurs and its values survive until vehicle simulation is a central feasibility assertion, not an assumption.
  • scripts/GameCode/Vehicle/SCR_HelicopterControllerComponent.c:72–94: native script callback normally reapplies global device preferences. A second opt-in hook calls its superclass, then changes only the exact fixture aircraft to CollectiveMode.Direct. It never changes global input/preferences. Its prior mode is restored when releasing an unclaimed test aircraft.
  • scripts/Game/generated/Vehicle/BaseVehicleControllerComponent.c:46–65: normal StartEngine and StopEngine; force-start/stop are cinematics-only and excluded. VehicleControllerComponent.OnEngineStart/OnEngineStop connects/disconnects native fuel consumption; actual fuel decrease is required.
  • VehicleHelicopterSimulation: real rotor state/RPM/target; VehicleBaseSimulation: actual internal transform/velocity/ground contact. These are read-only feedback, not substitutes for control inputs.

Experiment

Core-only opt-in outcome powered-flight, -errBaseSmoke 1. A separate real vanilla unarmed Mi8 may be spawned once only after a bounded candidate search finds a clear, flat pad apart from the registered extraction aircraft. The initial twelve candidates at 120 m all fail in archived 090203. The 128-point survey at 120–500 m compiles but finds no acceptable pad in archived 091819. The current draft tests at most 377 candidates: those 128 coarse points followed by 80 points in a fixed local grid around the frozen best above-water coarse sample, then 169 points in a 13-by-13 airport grid at 50 m spacing. The airport center comes from installed vanilla Everon location data; each point must independently pass the same clearance checks. It retains the 0.8 m terrain-difference limit and increases the clearance column to 40 m radius and 60 m swept height. See pad survey; the 093749 runtime log records candidate 213 passing the unchanged pad checks, but its later fixture initialization fails. The real extraction aircraft and player are untouched. One stock USSR character (the already-resolved vanilla mortar crew character resource, not a claim of pilot-specific clothing) is created through the actual pilot seat's native SpawnCharacterInCompartment mechanism into its own initially empty USSR group. No HQ response system is involved in this flight-mechanism test.

After allocating one airframe and one empty group, initialization polls the same native components for up to 30 seconds. It enumerates actual root pilot slots and selects the audited stock prefab object name PilotCompartment, requiring an accessible, empty, unreserved, unlocked PILOT slot. The stock copilot also has PILOT type and is deliberately excluded. Only once the simulation is valid and actual fuel exists does it request one native pilot spawn, latched before the request. The shared 30-second bound is not renewed for seating or settling; the controller’s active pilot assignment must subsequently match that exact occupied primary seat. Initialization logs separate simulation, seat, active assignment and fuel state every two seconds. Initial physics wakes once and must settle naturally. The probe waits for actual original pilot ownership/seat/one-agent group, real finite fuel and strict grounded readiness. It then requires both real native preparation hooks to run and native input readback to match. Before engine start, a new guard measures the complete native model/rotor envelope and requires its radius plus initial displacement, planned 8 m drift and a 1 m margin to fit the cleared 40 m corridor, with the corresponding 60 m height bound. This guard is still awaiting native evidence. Only then it makes one normal engine-start request, waits for real engine/rotor spin and observed fuel use, and applies a conservative newly authored height/velocity feedback controller to native inputs.

The target is 8 m above the aircraft's initial resting origin; success requires 7–9 m altitude, no ground contact, bounded speed/tilt/drift continuously for five seconds, then descent through inputs only. Landing requires native ground contact plus low speed/angular velocity/upright attitude continuously for two seconds, followed by normal engine shutdown. Input bounds and feedback signs are experimental; wrong input mapping, missing callbacks, ineffective input application, drift or failed hover must produce a retained failure, never a physics-position correction. Native setters do not document full numeric/direct-mode semantics, so both response and tuning require native evidence.

The controller revalidates server/explicit opt-in, exact unclaimed pilot/group/active seat, conscious pilot, engine/rotor/airframe health and native fuel before writing. Any player aboard prevents writes. Terminal/failure cleanup clears hooks and only the same unclaimed pilot's controls, restores that aircraft's local collective mode without a crew lock. Leaving the seat fails authority. It never kills the engine in midair, deletes an airborne actor, stabilizes a falling aircraft, restores health, changes fuel or creates replacements. Test entities remain mode-owned for the explicit fixture reset/diagnostic inspection. Normal engine shutdown is requested only after actual landing. Capture/fuel/health gates exist but deliberate destructive variants and multiplayer ownership are not exercised in this first probe.

The run is bounded to 240 s after fixture creation (30 s preparation, 5 s callbacks, 65 s startup, 65 s climb/hover, 65 s landing, 15 s shutdown are subordinate maxima; total still wins). A fixture whose native startup consumes most of the total budget may fail rather than overrun. Base runner should allow 420 s including mission preparation. No UI/input emulation is used, and all scripts are excluded outside WORKBENCH.

Evidence limits and next work

Six local tests cover: exhaustive actual authority gate, actual bounded input/height/hover/contact-landing policies, and source guards against physical driving/global input/force-start/fuel-health mutation. They do not compile Enforce or prove native input persistence, cyclic signs, throttle/collective mapping or a flyable control law.

A native failure at the callback/input stage would identify a real integration blocker; a native failure during lift/hover requires reviewing logged actual inputs, RPM, internal position, fuel and motion, not relaxing success. No successful gate should be described as a full autopilot, route following, obstacle avoidance, HQ delivery, aircraft support acceptance or multiplayer proof. If takeoff/hover/landing works, the next independent layer is bounded attitude/position control and explicit loss tests before radio/HQ sortie integration.

Archived attempts through 093319

090203 compiles and reaches the Core fixture, with 51 prior assertions passing, but its original twelve candidates produce no acceptable separate pad. It records two failure assertions and no smoke completion. The refusal occurs before fixture aircraft/pilot creation, engine start or native control-hook observation; it supplies no flight, fuel-use or landing evidence. The production extraction vehicle is left untouched. The missing pad is a failed feasibility run, not a reason to relax clearance.

090443 fails Game compilation first at ERR_NativeHQResponseProof.c:236, with repeated Formula too complex diagnostics and subsequent compiler errors. 090705 fails first at ERR_NativePoweredFlightProbe.c:36 with Unknown operator '%' in the expanded pad search, followed by further compiler diagnostics. Both have zero runtime assertions/completions. Raw logs are preserved without filtering. Later source corrections are not qualified by these failures or by the earlier 085442 Core victory run.

Those three earlier archives retain matching launch/stopped source manifests and verified console hashes. The corrected helpers subsequently compile in 091306; 091819 runs the 128-point survey and rejects three low-ground and 125 sloped candidates (best height delta 0.803917 m), before reaching cylinder/sweep checks or spawning an aircraft. 093319 compiles the 208-point/footprint draft but finds no safe pad: three low-ground, 182 slope and 23 cylinder rejections, with best terrain delta 0.0999985 m. Its 51 preceding assertions do not offset the two explicit fixture failures or establish flight. No aircraft is created and no measured-footprint guard is exercised. The later 093749 run observes the 377-point airport extension finding a safe pad, then fails before pilot creation. Native control callbacks, engine startup, real fuel consumption, takeoff, hover and landing still require successful source-bound observations. No production aircraft support or multiplayer claim follows from these attempts.

Deferred native initialization after 093749

The 09:37:49 run finds the safe airport point <4800.95,27.8202,11487.4> on candidate 213 and allocates its single airframe/group. The immediate readiness assertion then fails in the same millisecond. Because the old assertion combined simulation, controller-selected seat and fuel predicates, that evidence does not identify the failing predicate. Installed GetPilotCompartmentSlot documentation does not promise that an empty primary seat is available through the controller immediately after spawning.

The staged correction separates component observation, one-time pilot allocation and actual occupied-seat authorization. The installed BaseCompartmentManagerComponent.GetCompartments API and ExtBaseCompartmentSlot.GetCompartmentName(false) enumerate native slots and their prefab object names; the audited Mi8 root names its primary slot PilotCompartment and copilot Passenger_m01Cargo. This changes no controls, survey limits, footprint gate, fuel, health or transforms. It does not retry aircraft or pilot creation. Local tests verify those sequencing and ownership constraints; native compilation and initialization success still require the next source-bound run.

Seating timeout observed in 094843

The 09:48:43 run compiles the deferred initialization correction. At 09:49:34.776 the real root primary slot is accessible, empty and marked piloting; the copilot is separately identified. Simulation validity, fuel manager, controller-selected slot and finite fuel (1938.75) are present. One native pilot allocation succeeds. Stage 1 then reaches its unchanged 30-second seating/ground-settling deadline at 09:50:04.576. This establishes neither occupied-seat ownership nor settled ground contact: the old compound wait did not log those individual predicates. It also disproves any assumption that the controller's pilot-slot getter necessarily requires an occupant, because it returns a slot before pilot creation in this run.

The staged diagnostic records every two seconds (plus the deadline) actual pilot/group identity, physical selected-seat occupancy, controller active slot, vehicle membership, native entry/exit state, life/consciousness, one-shot wake count and stability time. It also records entity and internal simulation transforms, physics activation/motion, native contact and the existing conservative parked-support result. At the deadline, the existing support helper adds wheel/terrain trace detail when applicable. This is read-only observation: no native action, AI state, transform, health, fuel, readiness predicate or timeout is changed.

Installed BaseCompartmentSlot.SpawnCharacterInCompartment activates the real agent, requests native GetInVehicle, and adds its control agent to the supplied group; a non-null return proves the request was accepted, not that occupancy persists on later ticks. Likewise, physics activation does not itself prove contact. The next diagnostic run must distinguish lost native seating/group membership from motion/contact rejection before choosing any behavioral fix. No engine start or powered flight has been observed in 094843.

Queued group members identified in 095950

The 09:59:50 diagnostic run proves the primary pilot remains alive, conscious and in the intended group, but is outside the aircraft: occupancy and vehicle-membership checks remain false, with neither native entry nor exit in progress. The aircraft settles naturally and subsequently passes the strict readiness predicate. The group grows from zero to two, five and six agents despite the fixture allocating only one pilot. Installed Group_USSR_Base.et authors six unit slots, and SCR_AIGroup.EOnInit schedules those slots through its native spawn queue. Testing the immediate count for zero was therefore insufficient to establish an empty group.

The staged correction uses the installed memberless {000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et and explicitly initializes its USSR faction before activation. This prevents the unintended finite crew allocation at its source; no spawned actors are deleted or replaced to make counts pass. One native pilot allocation and all physical seat/authority checks remain required. The exact pilot control agent also receives one explicit permanent LOD 0/activation, following the existing physical mortar-crew setup; group LOD alone did not establish that member's LOD. Its prior setting is restored on Stop only while that pilot/group/aircraft remains unclaimed. Native LOD and activation telemetry are recorded. This addresses a source-supported distant-AI setup omission, but 095950 did not measure pilot LOD and does not prove LOD caused the missing occupancy. No boarding retry or seat lock is introduced.

A separate diagnostic limit remains: in 095950 the simulation's documented internal-physics transform reads as identity/origin zero while entity physics has settled at the airport. The existing footprint and flight checks are retained unchanged and must refuse inconsistent geometry; this patch does not treat that transform as verified world-space flight telemetry. Native compilation and single-pilot seating still await the next run.

Native control domain and coordinate correction after 100422

The 10:04:22 run proves the corrected memberless group contains exactly one real pilot, seated in the primary cockpit, with its active native agent at LOD 0. Strict grounded readiness passes and both native preparation hooks execute. The applied-input observer records the same sequence with immediate collective readback −1 but later applied collective 0, and native MainRotorCollective 0. This establishes that a signed negative minimum does not survive the native apply phase; it does not establish a complete positive input response or a flight-capable controller.

The staged correction keeps the feedback controller's signed state, gains and limits, but encodes its final collective demand as (clamp(signedDemand, -1, 1) + 1) / 2, in [0, 1]. Startup and completed landing therefore command zero; cyclic and anti-torque remain signed. The startup check still requires the actual native input to equal the requested minimum in Direct mode. Native applied-input and rotor-signal diagnostics remain available unchanged. Positive collective response, engine start, fuel use and powered flight require a subsequent native run.

The same run shows why world geometry cannot use VehicleBaseSimulation.GetWorldTransform: its documented return is in internal physics space, and it reports origin zero/identity while the actual aircraft entity settles at the airport. All control pose, altitude, drift and complete-footprint measurements now read the actual aircraft's IEntity.GetWorldTransform, matching the coordinate space of native model world bounds and rotor PointInfo world transforms. Internal simulation pose is retained only as comparison telemetry. RotorGetTransform remains explicitly local, and native velocities/contact/RPM remain read-only. No transforms or velocities are written; no footprint, drift, tilt, altitude, landing or fuel gate is relaxed.

Final native apply callback after 101342

The 10:13:42 run passes the exact complete footprint gate (110 entities, 93 meshes, 74 hitzones, complete radius 27.6823 m, initial drift 0.100174 m), issues one ordinary engine start, reaches native rotor RPM 196, and consumes actual fuel from 1938.75 to 1937.33. At 10:15:11 it fails the unchanged 8 m drift limit at 9.22315 m, with no stable hover or landing. This is a failed flight, despite the separate footprint/startup achievements.

Same-sequence native observations prove a broader overwrite than the earlier negative-input inference: sequence 543 writes positive collective 0.280161 but later reads zero; sequence 618 writes 0.631399 but later reads zero, while both cyclic commands also become zero. The preserved [0,1] command range is a bounded experimental choice; this run does not prove that the original negative input was merely domain-clamped or that the full input-to-thrust mapping is known.

The staged correction keeps native OnPrepareControls only as an exact-owned pilot observation counter. It moves the sole control integration and write path into the exact-owned pilot's native OnApplyControls(owner, timeSlice), after calling the installed vanilla implementation. The generated CharacterController declaration and installed SCR override confirm this callback exists; its ordering relative to final engine consumption is not fully documented. Native proof is therefore still required, rather than assumed from the callback name. No integration or control write remains in Prepare; no ownership, seat, life, fuel or physics guard changes.

After native RPM/fuel proof, a new at-most-three-second stage requests 0.05 collective with zero cyclic/anti-torque. Before any climb it requires fresh real apply callbacks and the existing MainRotorCollective signal to agree with the nonzero request on distinct fixture ticks spanning at least 500 ms. Missing signals or continued zero values fail; no signal is created or assigned. Engine, drift, height, tilt and callback freshness checks remain active in this stage. The proof does not depend on the optional diagnostics flag. All later physical hover and contact-landing checks remain required. The overall 240-second bound remains unchanged.

Optional diagnostics now observe native input at the start of Apply before this callback's final writes, then capture the final immediate write readback. These two snapshots are explicitly labelled beforeWrite/written; neither is alone called downstream consumption proof. Existing rotor signals and the mandatory positive gate provide the later observation. The optional file no longer adds a second native OnApply override, preventing hook-chain ordering from obscuring the comparison. This revision has local source/policy checks only until its next native run.

Actor-local action experiment after 102235

The 10:22:35 run compiles the Apply-callback revision and again passes single-pilot seating, complete footprint and real engine/RPM/fuel checks. Its mandatory positive gate then fails: five distinct observations report requested collective 0.05 but existing rotor signal zero, with 15, 30, 45, 60 and 75 real writes. The next Apply callback sees native input reset to zero. This is no demonstration of consumed flight controls, hover or landing. The rotor signal is an authored animation input, not a documented thrust sensor or guaranteed exact transfer function; its refusal preserves this experiment's limits rather than proving scripting flight impossible.

A separate experimental -errFlightActionInputs 1 mode is now available. The default retains the failed Apply-context writer for comparison. The experiment uses the supplied, exact pilot-local ActionManager in OnPrepareControls, before native super, following installed SCR_CharacterControllerComponent_Test.c:9–13. It requires that manager to equal the actual pilot agent's manager and differ from the global InputManager; the global object is read only for rejection, never mutated. Shared/missing managers fail. Only this owned manager's HelicopterContext is briefly activated using the installed duration1 pattern.

The exact configured actions are HelicopterCollectiveIncrease/Decrease, HelicopterCyclicForward/Back, HelicopterCyclicRight/Left and HelicopterAntiTorqueRight/Left. The fixture writes bounded nonnegative directional values and explicitly zeros the opposite action. Signed-to-collective encoding and control gains remain experimental; the config does not document final Direct-mode mapping. The selected mode is immutable during the run: the Apply writer returns immediately in action mode, and the action writer returns immediately in default mode. Both share one demand calculation; the integrator executes once per selected native callback. No engine, brake or autohover actions are injected.

On Stop, only the same owned, unclaimed manager receives zeros for these eight actions. The short context activation expires without further refresh; the duration parameter's units are not claimed. Capture/life/seat/authority checks and the mandatory <=3s positive rotor-signal proof remain unchanged, as do all footprint, fuel, height, tilt, drift, hover and landing bounds. Optional diagnostics distinguish actual virtual-action readbacks from native input at Apply and the existing rotor signal. Action mode observes throttle but does not write it. This branch is source-checked only until native compilation and consumption are observed.

The 104048 actor-manager test compiles but fails before engine start. The 104256 diagnostics show the exact owned manager's context is already active while ActivateContext returns false on four callbacks; requiring the undocumented return value incorrectly prevents all action writes. The revised path checks whether the context is already active, attempts activation only when inactive, and requires the observed active state. It never deactivates a preexisting native context. This corrects the fixture's activation assumption; action readback, native consumption and all physical bounds remain independently required.

The 105226 motion run again takes off and fails at8.00134m drift after reaching6.8385m. Rearward velocity is already reversing before refusal. The next bounded experiment changes only outer-loop velocity damping from0.3 to0.6; position0.08, attitude0.8, angular damping0.3, cyclic0.15 and all physical limits remain unchanged. A simplified acceleration model suggests less overshoot, but native lag must be tested. Measured acceleration follows the fuselage-up estimate much more closely than the transformed static rotor axis in these samples; no hardcoded/native-axis trim is justified from that diagnostic alone.

An installed-API/source review after105709 finds a concrete heading feedback bug: IEntity.GetAngles returns rotations aboutX/Y/Z, while GetYawPitchRoll returns named yaw/pitch/roll order. The fixture incorrectly read GetAngles()[0] as yaw in both capture and feedback. Both now use GetYawPitchRoll()[0], retaining action signs and all gains/bounds from the0.6 damping experiment. Vanilla SCR_HelicopterCinematicFlyComponent also uses GetAngles()[1] for yaw. Read-only desired-yaw/actual-yaw-pitch-roll telemetry accompanies the correction; native stabilization still must pass.

The heading correction holds observed yaw near its1.45-degree target in the next native run, confirming that pitch was the wrong feedback field. Pitch still oscillates with native angular rate reaching0.14rad/s and saturated cyclic demand. The next single-gain experiment raises pitch/roll angular-rate damping0.3→1.2, preserving the0.6 outer velocity term, position/attitude gains, yaw controller, input caps and all physical limits. This is still test-only tuning; a valid outcome requires native hover and landing, not merely improved snapshots.

Explicit native-autohover fixture variant

The WORKBENCH-only probe exposes bool SetAutohoverMode(bool enabled). The smoke caller selects true immediately after constructing its probe and before the first Tick; there is no separate probe Start method. A false return fails the caller's fixture configuration. Default construction retains the manual mode, including angular damping 1.2. Configuration is frozen once ticking starts, an airframe exists, the fixture binds, or the probe stops/completes. The integrated runner's explicit --flight-autohover requires --project core --smoke powered-flight --flight-action-inputs; it passes -errFlightAutohover 1 to that Core fixture. It is off by default.

The API is grounded in installed HelicopterControllerComponent.GetAutohoverEnabled() and SetAutohoverEnabled(bool). Vanilla SCR_HelicopterHoverAction.SetState calls that setter, and the stock Mi8 includes the action in its autopilot context. SCR_BaseGameMode.OnPlayerDisconnected also enables autohover on the server to help stop an occupied helicopter gracefully. Thus the call is a real per-vehicle native feature, not a simulated controller, obsolete helper or global player-input change. Vanilla's scripted OnPrepareControls sets collective preferences but does not itself reset autohover.

After the original single pilot is physically in its exact primary seat and all authority/fuel/health gates pass, the selected variant captures the exact controller and its prior autohover state, enables it once, and requires actual getter readback. Failed enabling is not retried. Subsequent ticks and control callbacks require that same controller and enabled state; losing the setting fails the run rather than silently re-enabling it. Periodic ERR POWERED AUTOHOVER telemetry records mode selection, saved state, native state and controller identity.

In this mode only, custom forward/right cyclic demands are explicitly zero. The chosen actor-action or Apply-input path still writes those neutral demands normally, leaving native autohover to supply its own lateral stabilization. Collective/altitude and yaw feedback, engine startup, rotor-signal consumption proof, finite fuel use, timeouts, 8 m drift/height/tilt bounds, actual 7–9 m five-second hover, and physical-contact landing requirements remain unchanged. Autohover must coexist with those controls in a real run; the installed script API does not reveal its gains, activation envelope, altitude behavior, AI ownership details or final input composition. An enabled bit alone cannot pass any flight milestone.

Stop restores the captured autohover state only while the same controller belongs to the same aircraft, the same unclaimed fixture pilot still occupies the selected primary seat, and no player has claimed or boarded it. It does not change a captured, replaced or abandoned controller. Restoration is attempted once and logged; a getter mismatch emits an explicit native smoke failure. No engine shutdown in midair, force/velocity/transform correction, fuel/health write, crew replacement, or production-aircraft change is introduced. As before, failed physical actors remain owned by the fixture for diagnosis/reset.

Offline tests execute the actual configuration/readback/restore methods against explicit controller doubles, including late configuration refusal, default no-write behavior, original true/false settings, rejected native enable/restore, changed ownership/controller, idempotent cleanup and neutral cyclic behavior. These do not compile Enforce or establish native autohover effectiveness. This variant requires its own retained native result before any takeoff/hover/landing claim, and does not qualify production route flying or multiplayer behavior.

The first native autohover trial (112320) compiled and confirmed the exact owned flag, but failed its unchanged pre-engine minimum-collective gate: the native controller changed the post-application collective to about -0.114 despite an action demand of zero. Its original autohover state was restored. This establishes that the native feature affects collective as well as lateral controls. The next staged variant therefore keeps autohover off through engine startup and the existing positive collective-consumption proof, then enables it immediately before the bounded climb. Native readiness is mandatory through flight and landing; no physical gate is relaxed. This delayed activation remains unverified until a separate native run.

Bounded signed actor-action experiment after 11:25:02

The archived manual 112502 run retained Direct mode (3), native collective and MainRotorCollective zero while climbing about 0.2 m/s; it exceeded the unchanged 18 m ceiling with horizontal drift below 8 m. This is physical evidence that zero did not arrest that climb, not proof of a particular blade-pitch or thrust mapping. The earlier 112320 autohover observation of negative collective used WorldY mode (5), so it does not establish negative Direct action consumption.

Installed Configs/System/chimeraInputCommon.conf:6152–6201 defines separate HelicopterCollectiveIncrease and HelicopterCollectiveDecrease actions, each limited to 1, with opposite input directions. The generated Vehicle/CollectiveMode.c and Character/CharacterInputContext.c expose the mode/input without documenting their transfer function. The fixture's old signed-to-unipolar conversion never exercised the decrease action. Its earlier interpretation of a clamped negative Apply write was superseded by evidence that native processing also overwrote positive Apply writes.

The next staged actor-action variant retains zero during initial preparation and engine startup, and retains the existing positive 0.05 consumption test. Only after that test passes does stage 10 request increase=0/decrease=0.05, with zero cyclic/torque, on the exact owned AI action manager. Within three seconds it requires Direct mode, autohover off, a running engine, fresh callbacks, negative native input and the existing rotor signal agreeing near -0.05 on distinct ticks spanning 500 ms. Signal mismatch or a missing signal fails. Interrupted observation resets the interval. This proof does not depend on optional diagnostics and does not assign a signal.

Only a successful negative test enables signed actor-action demand for flight stages 4–6; the legacy Apply branch retains its old encoding for comparison. Optional native autohover is enabled after both action-path proofs. Feedback gains, initial integrator value, single-aircraft/pilot allocation, overall timeout, footprint, fuel, drift, tilt, altitude, stable-hover and contact-landing requirements are unchanged. Negative signal consumption remains an experimental question until this revision runs natively; even a successful signal test alone proves neither hover nor landing.

Native113557 proves the signed-action hypothesis: both input and rotor signal hold -0.05, the same aircraft reaches a five-second 7–9m hover and lands with two seconds of ground stability. It then fails the immediate post-shutdown check. Inspection found stage7 returned neutral collective0 while the real rotors continued coasting; the next variant holds proven minimum pitch -1 during shutdown and records every landing predicate. No stability, geometry, timeout or damage limit changes. The failed run remains retained.

Native autohover and signed-control pass

114504 passes81 assertions with zero captured errors. Both positive and negative actor-local input/rotor-signal gates pass before autohover is enabled on the exact occupied controller. One normal engine start consumes native fuel; the same aircraft holds7–9m for five seconds, descends and maintains ground contact for two seconds, then passes the engine-off check at approximately-0.063m relative height,0.012m/s speed and0.063rad/s angular speed. Drift stays inside8m and height inside18m. The original autohover flag is restored. Rotors are still coasting at195.5RPM when engine-off is verified; this is not a rotor-stop or sustained parked-aircraft test.

This qualifies one bounded vertical mechanism, not route travel, operational HQ aircraft, human piloting or multiplayer. The manual113557 run's shutdown failure and114111 repeated-hover timeout remain archived.