Capture current mission, AI, map and administration development

Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
2026-10-13 22:52:53 +02:00
parent a951a96edc
commit 6a667d8deb
8104 changed files with 2124945 additions and 2061 deletions
@@ -0,0 +1,37 @@
# Cessna dedicated-server check — 8 October 2026
Reforger 1.8.0.13, Cessna 172 1.0.0, Propeller Flight Core 1.0.18. Private Everon
server, loopback-only network namespace, separate profile and frozen source;
no Steam player profile, live server or published addon was changed.
The retained fixture advances HQ on the otherwise empty server, transitions to
the normal escaped phase and places three active opposing AI actors near the
runway. It does not manufacture sightings, reports, radio delivery or aircraft
motion. The patrol uses its production airport survey, native crew boarding,
engine start and PFC flight controls. After 120 seconds airborne, the fixture
destroys the aircraft through its damage manager, waits for the replacement to
take off, then changes its faction to check release and restoration of controls.
Results in `native-summary.log`:
- Native crew sighting reached HQ with the plane group as its source.
- Original plane took off from the airport and remained alive through the patrol.
- Replacement took off 108.1 seconds after destruction, including the minimum
60-second delay, additional clearance search and engine/ground takeoff time.
- Faction takeover retained the living aircraft and restored its original rates.
- Separate native compile without either plane addon passed.
- Menu structure/routing, setting validation, settings import/migration and HQ
registration checks passed; the development source bundle audit passed without
adding aircraft addon dependencies.
`result.json` contains source hashes and explicit test limitations. The native
snapshot matches the production sources listed there; its runway survey has one
additional diagnostic Print on rejected clearance, and the fixture is injected
as a separate script. `isolated-runner.py` records the local fixture setup; its
runtime, downloaded addon and RDB paths are machine-specific prerequisites.
This is **not** a clean full-mission or multiplayer playtest: two optional-site
initial guard preparations failed during the busy escaped-phase fixture. They
are retained in the summary rather than hidden. No connected human client was
used, so first-person visuals/audio and an actual player boarding takeover still
need normal gameplay validation.
@@ -0,0 +1,27 @@
#1 t=4.9s M0 PLANE AVAILABLE optional Cessna detected; airport survey runs in background [session=1791412316-1]
#54 t=35.5s M0 PLANE SPAWN wave=1 position=<4766.76,28.4438,11279.9> heading=5 [session=1791412316-1]
#75 t=38.6s M0 REGISTER group=4 force=plane-recon-38649.4 faction=USSR position=<4781.76,27.9438,11279.9> members=2 home= dedicated=1; policy=maximum skill/regular aim with ten percent less dispersion/alert recognition [session=1791412316-1]
#76 t=38.6s M0 SPAWN MEMBER group=4 force=plane-recon-38649.4 actor=SCR_ChimeraCharacter<0x00007F99C2894CC8> @"ENTITY:4611686018427389222" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <4766.666504 28.918100 11281.403320> @"{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et" prefab={C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et position=<4766.67,28.9181,11281.4> [session=1791412316-1]
#77 t=38.6s M0 SPAWN MEMBER group=4 force=plane-recon-38649.4 actor=SCR_ChimeraCharacter<0x00007F99C2894E90> @"ENTITY:4611686018427389258" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <4767.170410 28.918171 11281.360352> @"{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et" prefab={C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et position=<4767.17,28.9182,11281.4> [session=1791412316-1]
#78 t=38.6s M0 PLANE TAKEOFF <4766.76, 28.4438, 11279.9> [session=1791412316-1]
#79 t=38.7s M0 PLANE STATUS runway takeoff position=<4766.76,27.8272,11279.9> AGL=-0.0165443 speed=0.00186602 angles=<4.93175,-0.120159,-0.00673387> controls=0.00720956/0.000202016 destination=<4941.07,28.4438,13272.2> [session=1791412316-1]
#119 t=42.2s M0 CONTACT LOCAL group=4 force=plane-recon-38649.4 observed=<4760,28.6562,11650> home= dedicated=1; native combat active, radio report due [session=1791412316-1]
#221 t=53.8s M0 PLANE STATUS runway takeoff position=<4783.17,28.674,11561.4> AGL=0.192327 speed=42.768 angles=<3.77029,5.94469,-0.0689589> controls=0.894433/0.00379004 destination=<4941.07,28.4438,13272.2> [session=1791412316-1]
#240 t=58.1s M0 PLANE AIRBORNE <4794.4, 43.2791, 11759.4> [session=1791412316-1]
#279 t=68.8s M0 PLANE STATUS patrolling island sectors position=<4824.24,97.4685,12259.4> AGL=79.781 speed=46.8807 angles=<5.34122,7.56765,1.49151> controls=0.584527/-0.00570578 destination=<4941.07,28.4438,13272.2> [session=1791412316-1]
#549 t=83.9s M0 PLANE STATUS patrolling island sectors position=<4948.81,134.575,12963.2> AGL=134.575 speed=49.1348 angles=<29.152,5.93972,25.0311> controls=0.554283/-0.00331134 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#847 t=98.9s M0 PLANE STATUS patrolling island sectors position=<5618.31,155.417,13221.2> AGL=155.417 speed=52.6916 angles=<99.6889,4.50395,25.0748> controls=0.589865/0.00394486 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#909 t=114s M0 PLANE STATUS patrolling island sectors position=<6136.08,161.148,12657.5> AGL=161.148 speed=53.5493 angles=<159.317,4.14514,12.0736> controls=0.678907/-0.0125706 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#932 t=129s M0 PLANE STATUS patrolling island sectors position=<6252.17,168.942,11865.8> AGL=168.942 speed=53.2697 angles=<176.766,3.88841,1.66265> controls=0.641377/-0.00370029 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#965 t=144s M0 PLANE STATUS patrolling island sectors position=<6278.48,172.59,11065> AGL=172.59 speed=53.384 angles=<179.073,3.88622,0.9084> controls=0.627004/-0.00776765 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#997 t=159s M0 PLANE STATUS patrolling island sectors position=<6288.28,175.265,10261.5> AGL=175.265 speed=53.6216 angles=<179.012,3.63031,0.777801> controls=0.701692/-0.0119572 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#1062 t=174.1s M0 PLANE STATUS patrolling island sectors position=<6294.43,205.529,9476.46> AGL=205.529 speed=50.5125 angles=<-178.885,7.85692,-0.476852> controls=0.765912/-0.00440861 destination=<6309.31,183.177,7121.96> [session=1791412316-1]
#1074 t=178.2s M0 PLANE LOST aircraft destroyed or removed [session=1791412316-1]
#1365 t=262.7s M0 PLANE SPAWN wave=2 position=<4752,27.7117,11836.9> heading=175 [session=1791412316-1]
#1392 t=265.9s M0 REGISTER group=43 force=plane-recon-265926 faction=USSR position=<4767,27.2117,11836.9> members=2 home= dedicated=1; policy=maximum skill/regular aim with ten percent less dispersion/alert recognition [session=1791412316-1]
#1393 t=265.9s M0 SPAWN MEMBER group=43 force=plane-recon-265926 actor=SCR_ChimeraCharacter<0x00007F99C28A1CB0> @"ENTITY:4611686018427402522" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <4752.359375 28.209419 11835.352539> @"{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et" prefab={C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et position=<4752.36,28.2094,11835.4> [session=1791412316-1]
#1394 t=265.9s M0 SPAWN MEMBER group=43 force=plane-recon-265926 actor=SCR_ChimeraCharacter<0x00007F99C28A1E78> @"ENTITY:4611686018427402558" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <4751.855469 28.210222 11835.308594> @"{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et" prefab={C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et position=<4751.86,28.2102,11835.3> [session=1791412316-1]
#1395 t=265.9s M0 PLANE TAKEOFF <4752, 27.7117, 11836.9> [session=1791412316-1]
#1396 t=266s M0 PLANE STATUS runway takeoff position=<4752,27.0924,11836.8> AGL=-0.0194111 speed=0.00988521 angles=<175.002,0.870845,-0.088475> controls=-0.0522507/0.00265425 destination=<4926.31,27.7117,9844.46> [session=1791412316-1]
#1518 t=274.1s M0 CONTACT LOCAL group=43 force=plane-recon-265926 observed=<4751.92,28.7074,11671.4> home= dedicated=1; native combat active, radio report due [session=1791412316-1]
#1634 t=281s M0 PLANE STATUS runway takeoff position=<4777.16,28.4513,11559.5> AGL=-0.0486565 speed=44.1337 angles=<173.776,5.51099,0.0404763> controls=0.945046/-0.0024035 destination=<4926.31,27.7117,9844.46> [session=1791412316-1]
@@ -0,0 +1,59 @@
from pathlib import Path
import os,sys,json,shutil,subprocess,time,signal
ROOT=Path('/home/jakub/devel/escapistsrereintroduced');sys.path.insert(0,str(ROOT/'tools'))
from external_addons import policy,prepare_profile
from source_manifest import addon_manifest
from dedicated_native import PROBE
base=Path('/tmp/erri-plane-native');base.mkdir(exist_ok=True)
run=base/sys.argv[1];run.mkdir();source=run/'source';source.mkdir()
for rel in addon_manifest(ROOT):
dest=source/Path(rel).relative_to('addons/core');dest.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(ROOT/rel,dest)
shutil.copy2('/tmp/erri-takeover-pair-source32/resourceDatabase.rdb',source/'resourceDatabase.rdb')
if run.name.endswith('-unfixed'): (source/'Scripts/Game/ERR/00_Core/ERR_ItemStationLifecycle.c').unlink()
shutil.copy2('/tmp/err-plane-diag.c',source/'Scripts/Game/ERR/00_Core/ERR_ZErrorsProbe.c')
p=source/'Scripts/Game/ERR/10_AI/ERR_PlaneRecon.c'
s=p.read_text().replace('if (!Clear(start, forward)) return false;', 'if (!Clear(start, forward)) { PrintFormat("ERR PLANE BLOCKED start=%1 heading=%2", start, Heading); return false; }')
p.write_text(s)
addons=run/'addons';addons.mkdir();steam=Path.home()/'.local/share/Steam'
# Private compile-only profile: use the currently installed dependency projects.
import re
installed=steam/'steamapps/compatdata/1874880/pfx/drive_c/users/steamuser/Documents/My Games/ArmaReforger/addons'
required={'595F2BF2F44836FB','629B2BA37EFFD577','5E524E4FEECCA92B','65930CB4CD0237B2'}
projects={}
for project in installed.glob('*/addon.gproj'):
text=project.read_text();match=re.search(r'GUID "([A-Fa-f0-9]+)"',text)
if match: projects[match[1].upper()]=(project,re.findall(r'"([A-Fa-f0-9]{16})"',text.split('Dependencies',1)[-1]) if 'Dependencies' in text else [])
pending=list(required);seen=set()
while pending:
guid=pending.pop()
if guid in seen or guid=='58D0FB3206B6F859':continue
seen.add(guid);project,deps=projects[guid]
(addons/('Dependency_'+guid)).symlink_to(project.parent,target_is_directory=True)
pending.extend(deps)
for folder in Path('/tmp/err-cessna-download/addons/addons').glob('*'):
if folder.is_dir(): (addons/folder.name).symlink_to(folder,target_is_directory=True)
(addons/'ERR_Core').symlink_to(source,target_is_directory=True)
profile=run/'profile/profile';profile.mkdir(parents=True)
(run/'network.py').write_text(PROBE)
runtime=Path('/tmp/erri-takeover-dedicated-runtime')
engine=['/tmp/runtime/ArmaReforgerServer','-server','{C1E20667DCE324ED}Missions/ERR_Everon.conf','-addonsDir',str(addons),'-addons','2528466DE220D91C,69BAEE0D439966FE,69A8A34027DA65C5','-profile',str(run/'profile'),'-noBackend','-noSound','-bindIP','127.0.0.1','-bindPort','2001','-maxFPS','30','-logconsole','-noSplash','-noThrow','-disableCrashReporter']
cmd=['bwrap','--unshare-net','--unshare-pid','--unshare-ipc','--unshare-uts','--die-with-parent','--cap-drop','ALL','--ro-bind','/','/','--tmpfs','/tmp','--ro-bind',str(runtime),'/tmp/runtime','--ro-bind','/tmp/err-cessna-download','/tmp/err-cessna-download','--bind',str(run),str(run),'--proc','/proc','--dev','/dev','--chdir','/tmp/runtime','python',str(run/'network.py'),os.readlink('/proc/self/ns/net')]+engine
with (run/'stdout.log').open('w') as log:
p=subprocess.Popen(cmd,stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
reason='timeout';start=time.monotonic()
try:
while time.monotonic()-start<360:
files=sorted((run/'profile/logs').glob('logs_*/console.log'));text=files[-1].read_text(errors='replace') if files else ''
if 'ERR PLANE COMPLETE' in text:reason='complete';break
if "Can't compile" in text:reason='compile-failed';break
if p.poll() is not None:reason='exit';break
time.sleep(.3)
finally:
if p.poll() is None:
os.killpg(p.pid,signal.SIGTERM)
try:p.wait(timeout=8)
except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait()
(run/'result.json').write_text(json.dumps({'reason':reason,'exit':p.returncode}));print(reason)
print('\n'.join(line for line in text.splitlines() if 'PLANE' in line or 'SCRIPT (E)' in line))
@@ -0,0 +1,69 @@
modded class ArmaReforgerScripted
{
protected float m_ERRNextHQ, m_ERRNextPrint, m_ERRAirborneAt, m_ERRDestroyedAt;
protected bool m_ERRTargets, m_ERRKilled, m_ERRSeen, m_ERRDone;
protected Vehicle m_ERRFirst;
protected ref ERR_PlaneFlight m_ERRCaptured;
override void OnUpdate(BaseWorld world, float timeslice)
{
super.OnUpdate(world, timeslice);
ERR_HQ hq=ERR_HQ.Get(); ERR_GameMode mode=ERR_GameMode.Get();
if (!hq || !mode || !mode.Active() || m_ERRDone) return;
if (m_ERRCaptured && m_ERRCaptured.Captured)
{
PrintFormat("ERR PLANE CAPTURE restored=%1 alive=%2",m_ERRCaptured.ERR_RatesRestored(),ERR_Actors.Alive(m_ERRCaptured.Aircraft));
PrintFormat("ERR PLANE COMPLETE sighting=%1 capture=%2",m_ERRSeen,m_ERRCaptured.ERR_RatesRestored()); m_ERRDone=true; return;
}
float now=world.GetWorldTime();
if(now>=m_ERRNextHQ) { m_ERRNextHQ=now+1000; hq.Tick(now); hq.Journal().Flush(); }
if(now>=m_ERRNextPrint) { m_ERRNextPrint=now+5000; Print("ERR PLANE PROBE " + hq.PlaneRecon().Status()); }
ERR_PlaneFlight flight=hq.PlaneRecon().Current();
if(!flight || !flight.Aircraft) return;
if(!m_ERRTargets)
{
m_ERRTargets=true; m_ERRFirst=flight.Aircraft;
mode.Transition(ERR_Phase.RADIO_SEARCH);
SCR_AIGroup targetGroup=SCR_AIGroup.Cast(ERR_Actors.Spawn("{C31F210ABE078195}Prefabs/ERR/ReconCrew.et", ERR_Actors.Ground("4730 0 11650")));
mode.Own(targetGroup); targetGroup.SetFaction(mode.PlayerFaction()); targetGroup.SetPermanentLOD(0); targetGroup.ActivateAI();
targetGroup.GetGroupUtilityComponent().SetCombatMode(EAIGroupCombatMode.HOLD_FIRE);
for(int i=0;i<3;i++)
{
IEntity actor=ERR_Actors.Spawn("{C31F210ABE078199}Prefabs/ERR/ReconPilotWest.et", ERR_Actors.Ground(Vector(4730+i*15,0,11650)));
mode.Own(actor); ERR_Actors.SetFaction(actor,mode.PlayerFaction());
AIControlComponent control=AIControlComponent.Cast(actor.FindComponent(AIControlComponent)); control.ActivateAI();
AIAgent agent=control.GetControlAIAgent(); agent.SetPermanentLOD(0); agent.ActivateAI(); targetGroup.AddAgent(agent);
PrintFormat("ERR PLANE TARGET faction=%1 group=%2 alive=%3",SCR_FactionManager.SGetFaction(actor).GetFactionKey(),targetGroup,ERR_Actors.CanFight(actor));
DamageManagerComponent damage=DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent)); damage.EnableDamageHandling(false);
}
}
if(flight.Crew)
{
array<ref ERR_HQVisualContact> visible={}; ERR_HQObservation.Gather(flight.Crew.GetGroupUtilityComponent(),now,visible);
if(!visible.IsEmpty() && !m_ERRSeen) PrintFormat("ERR PLANE NATIVE VISIBLE count=%1 target=%2",visible.Count(),visible[0].Entity);
array<ref ERR_HQReport> reports={}; hq.SupportContacts(reports,now);
foreach(ERR_HQReport report:reports) if(report.Source==flight.Crew && !m_ERRSeen)
{ m_ERRSeen=true; PrintFormat("ERR PLANE PASS native crew sighting delivered to HQ target=%1 position=%2",report.Target,report.Position); }
}
if(flight.Airborne() && m_ERRAirborneAt==0) { m_ERRAirborneAt=now; Print("ERR PLANE PASS native airport takeoff"); }
if(!m_ERRKilled && m_ERRAirborneAt>0 && now-m_ERRAirborneAt>=120000)
{
SCR_VehicleDamageManagerComponent damage=SCR_VehicleDamageManagerComponent.Cast(flight.Aircraft.FindComponent(SCR_VehicleDamageManagerComponent));
PrintFormat("ERR PLANE PASS 120s patrol alive=%1 position=%2 speed=%3",ERR_Actors.Alive(flight.Aircraft),flight.Aircraft.GetOrigin(),flight.Aircraft.GetPhysics().GetVelocity().Length());
damage.SetHealthScaled(0); m_ERRKilled=true; m_ERRDestroyedAt=now; Print("ERR PLANE TEST aircraft destroyed");
}
if(m_ERRKilled && !m_ERRCaptured && flight.Aircraft!=m_ERRFirst && flight.Airborne())
{
PrintFormat("ERR PLANE PASS replacement took off after destruction elapsed=%1",now-m_ERRDestroyedAt);
m_ERRCaptured=flight; ERR_Actors.SetFaction(flight.Aircraft,mode.PlayerFaction());
}
}
}
modded class ERR_PlaneFlight
{
bool ERR_RatesRestored()
{
vector actual;
return ERR_CessnaBridge.Rates(Aircraft,m_InputRates,actual) && actual==m_InputRates;
}
}
@@ -0,0 +1,10 @@
00:31:46.667 SCRIPT : Module: Game; loaded 6761x files; 13587x classes; used 33237K of static memory; defines: "PLATFORM_LINUX,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE,ENABLE_BASE_DESTRUCTION,BUDGET_OPTIMIZATION_CHECKS,DEBUG,RESPAWN_TIMER_COMPONENT_DEBUG,DEBUG_CONFIGURABLE_DIALOGS,DISABLE_WEAPON_SWITCHING,SCRIPTED_AIM_MODIFIER_DEBUG,WCS_DEFINES_ARMAMENTS,WCS_DEFINES_SPACECORE"; CRC32: b06756de
00:32:53.102 SCRIPT : ERR PLANE PASS native crew sighting delivered to HQ target=SCR_ChimeraCharacter<0x00007F99C2894B00> @"ENTITY:4611686018427389187" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <4749.636230 28.533184 11642.238281> @"{C31F210ABE078199}Prefabs/ERR/ReconPilotWest.et" position=<4757.61,28.6562,11647.7>
00:33:00.557 SCRIPT : ERR PLANE PASS native airport takeoff
00:34:55.689 SCRIPT (E): Reintroduced [sites]: preparation failed: initial guard population incomplete or invalid: site=err-extra-camp-7 requested=2 physical=1 conscious=1 nativeComplete=0; limit=90s; no replacement requested
00:35:00.956 SCRIPT : ERR PLANE PASS 120s patrol alive=1 position=<6296.24,216.32,9273.92> speed=50.0559
00:35:00.958 SCRIPT : ERR PLANE TEST aircraft destroyed
00:36:26.222 SCRIPT (E): Reintroduced [sites]: preparation failed: initial guard population incomplete or invalid: site=err-extra-hospital-4 requested=1 physical=1 conscious=1 nativeComplete=1; limit=90s; no replacement requested
00:36:49.055 SCRIPT : ERR PLANE PASS replacement took off after destruction elapsed=108100
00:36:49.121 SCRIPT : ERR PLANE CAPTURE restored=1 alive=1
00:36:49.121 SCRIPT : ERR PLANE COMPLETE sighting=1 capture=1
@@ -0,0 +1,41 @@
{
"engine": "1.8.0.13",
"addons": {
"69BAEE0D439966FE": "1.0.0",
"69A8A34027DA65C5": "1.0.18"
},
"native_result": {
"reason": "complete",
"exit": -15
},
"absent_addons_compile": {
"reason": "compiled",
"exit": -15
},
"source_sha256": {
"addons/core/Scripts/Game/ERR/10_AI/ERR_CessnaBridge.c": "f1adb0f9b92f6ed94a8e9897b64e2fccba0f28552525a93f1ab893faa4fc5da2",
"addons/core/Scripts/Game/ERR/10_AI/ERR_PlaneFlight.c": "5f6bcceac0f296bd0ecd1a536f7e007d059f1e568c1b98dac3b18d0a4a83e8f3",
"addons/core/Scripts/Game/ERR/10_AI/ERR_PlaneRecon.c": "71b34170eecb281ca861dc42c33883d86ee70dea50ad9345e7016f2c3d2381e6",
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "edb64dc81e6a3b16e4ec31a260732616a7ae67334bd280a5eb9045002d8ef39d",
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "83b63c21574140208792aaf3d24e3d22b255a078871382122110bb48520d4541",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "6c438325060bf77dad9e333b38be0815817175e676becf8c2e4bfa5bf093b53e",
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "110488e1d23151a9d9b66525d9f4dc7132b38f6ffe4559d974926ae6d150d365",
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "7ccc85f2e0c39a266de60b5d3ae1d14ceb631b22716fbb0d36dfcac1101a8aeb",
"addons/core/UI/layouts/ERR/AdminMenu.layout": "63813b09be1630617d2b875e345c86c0dbdbb8bed4b5d1b3dfe39a3a8466b163"
},
"checks": [
"Native airport allocation, original PFC engine and actual ground takeoff",
"Native crew perception and source-identified HQ radio delivery",
"120 seconds of patrol; alive at 216 m altitude and 50.06 m/s",
"Destroyed through native damage manager; replacement took off after 108.1 s",
"Faction takeover retained the living plane and restored original flight input rates",
"Core compiles without both optional addons"
],
"limitations": [
"Headless dedicated-server fixture; no multiplayer client visual/audio validation",
"Sightings used three active opposing AI test actors, not connected human players",
"Takeover used a faction change, not an actual player boarding connection",
"Two optional site guard-preparation failures occurred in the busy escaped-phase fixture; this is not a clean full-mission result",
"No live server changes or Workshop publication"
]
}