Advance standalone admission, finite artillery and native validation

This commit is contained in:
2026-09-19 09:02:31 +02:00
parent af5146a317
commit 40a474934c
532 changed files with 56456 additions and 199 deletions
@@ -0,0 +1,15 @@
{
"cleanup-verification.json": "54e31b30fa5f8102a42d020b6a687799a063dd320ae5b0b30ae1efe64964b553",
"command.json": "20ab83f7e1ec457f3e4b7fad7f89c54c6ae7b649c63f142a552697b55c7bfcad",
"isolation-preflight.json": "bbf1e635e862532fbdd7d6210610b3906f4f1caad7c9ba08e67ecf84324dba7a",
"profile/logs/logs_2026-09-19_08-32-13/console.log": "44a061e2fa092e5a513a51341a54d6254b1d64d2909e0463071c4e348b3f15a0",
"profile/logs/logs_2026-09-19_08-32-13/error.log": "242f30914808638ddab976738b475e4e0c277c9e27a4b2bda46484f438049d0b",
"profile/logs/logs_2026-09-19_08-32-13/script.log": "81f3191e38f6a9932a77d05a22b746777d355938369b65d6cd17be450493b923",
"profile/profile/.save/settings/ReforgerEngineSettings.conf": "a36a9bbca20b2019099052c86f48fb00db7ec01ff7409cc81b6d102789ed50a9",
"profile/profile/.save/settings/ReforgerGameSettings.conf": "1656680640c178239490ffbf9b3ddae04d3ac0993cd84471c0d27b28b76abf13",
"result.json": "d4ca570adf8da3a0dc302f5f163e7f2278ba8f97826ed62154bd2f674c7881af",
"review.json": "5de14885c7e8a62cedd38c03a01ef0d566a1507de0439d42a6da721fd1123741",
"source-manifest-after.json": "d66a6a1a256aec91b752acb153dd1fac94d0950419e3a10ccecb74d50a914a15",
"source-manifest.json": "d66a6a1a256aec91b752acb153dd1fac94d0950419e3a10ccecb74d50a914a15",
"stdout.log": "acb9c1a7d09e057f988c139d97100ca9ac93c2475e83107aced4de869096e865"
}
@@ -0,0 +1,4 @@
{
"ownedSupervisorAbsent": true,
"remainingNativeServerExecutables": []
}
@@ -0,0 +1,111 @@
{
"command": [
"bwrap",
"--unshare-net",
"--unshare-pid",
"--unshare-ipc",
"--unshare-uts",
"--die-with-parent",
"--cap-drop",
"ALL",
"--clearenv",
"--ro-bind",
"/",
"/",
"--tmpfs",
"/home",
"--tmpfs",
"/tmp",
"--tmpfs",
"/run",
"--proc",
"/proc",
"--dev",
"/dev",
"--ro-bind",
"/tmp/erri-dedicated-runtime/server",
"/tmp/runtime",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header/source",
"/tmp/source",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header",
"/tmp/work",
"--setenv",
"HOME",
"/tmp/work/home",
"--setenv",
"TMPDIR",
"/tmp/work/tmp",
"--setenv",
"XDG_CONFIG_HOME",
"/tmp/work/home/.config",
"--setenv",
"XDG_DATA_HOME",
"/tmp/work/home/.local/share",
"--setenv",
"XDG_CACHE_HOME",
"/tmp/work/home/.cache",
"--setenv",
"PATH",
"/usr/bin:/bin",
"--setenv",
"LANG",
"C.UTF-8",
"--chdir",
"/tmp/runtime",
"/usr/bin/python3",
"-c",
"import json,os,socket,sys\nstate={\"netns\":os.readlink(\"/proc/self/ns/net\"),\"interfaces\":socket.if_nameindex(),\"routes\":open(\"/proc/net/route\").read(),\"ipv6Routes\":open(\"/proc/net/ipv6_route\").read()}\nprint(\"ERR ISOLATION \"+json.dumps(state),flush=True)\nassert state[\"netns\"] != sys.argv[1], \"network namespace was not isolated\"\nassert [name for _,name in state[\"interfaces\"]] == [\"lo\"], \"non-loopback interface present\"\nassert len(state[\"routes\"].splitlines()) == 1, \"IPv4 route present\"\nassert all(line.split()[-1] == \"lo\" for line in state[\"ipv6Routes\"].splitlines()), \"non-loopback IPv6 route present\"\nif len(sys.argv)>2: os.execv(sys.argv[2],sys.argv[2:])\n",
"net:[4026531833]",
"/tmp/runtime/ArmaReforgerServer",
"-addonsDir",
"/tmp/source/addons",
"-addons",
"2528466DE220D91C",
"-profile",
"/tmp/work/profile",
"-noBackend",
"-noSound",
"-noSplash",
"-noThrow",
"-bindIP",
"127.0.0.1",
"-bindPort",
"2001",
"-maxFPS",
"30",
"-logStats",
"5000",
"-server",
"{AD62322D5213C440}Missions/ERR_Everon_Base.conf"
],
"engine": [
"/tmp/runtime/ArmaReforgerServer",
"-addonsDir",
"/tmp/source/addons",
"-addons",
"2528466DE220D91C",
"-profile",
"/tmp/work/profile",
"-noBackend",
"-noSound",
"-noSplash",
"-noThrow",
"-bindIP",
"127.0.0.1",
"-bindPort",
"2001",
"-maxFPS",
"30",
"-logStats",
"5000",
"-server",
"{AD62322D5213C440}Missions/ERR_Everon_Base.conf"
],
"seconds": 90,
"binarySHA256": "91fdf333ec49c266d309be358aabab4244a93a2f9cfa11853a600e026104001f",
"serverLaunched": false,
"realPlayers": 0,
"multiplayerProven": false
}
@@ -0,0 +1,65 @@
{
"command": [
"bwrap",
"--unshare-net",
"--unshare-pid",
"--unshare-ipc",
"--unshare-uts",
"--die-with-parent",
"--cap-drop",
"ALL",
"--clearenv",
"--ro-bind",
"/",
"/",
"--tmpfs",
"/home",
"--tmpfs",
"/tmp",
"--tmpfs",
"/run",
"--proc",
"/proc",
"--dev",
"/dev",
"--ro-bind",
"/tmp/erri-dedicated-runtime/server",
"/tmp/runtime",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header/source",
"/tmp/source",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header",
"/tmp/work",
"--setenv",
"HOME",
"/tmp/work/home",
"--setenv",
"TMPDIR",
"/tmp/work/tmp",
"--setenv",
"XDG_CONFIG_HOME",
"/tmp/work/home/.config",
"--setenv",
"XDG_DATA_HOME",
"/tmp/work/home/.local/share",
"--setenv",
"XDG_CACHE_HOME",
"/tmp/work/home/.cache",
"--setenv",
"PATH",
"/usr/bin:/bin",
"--setenv",
"LANG",
"C.UTF-8",
"--chdir",
"/tmp/runtime",
"/usr/bin/python3",
"-c",
"import json,os,socket,sys\nstate={\"netns\":os.readlink(\"/proc/self/ns/net\"),\"interfaces\":socket.if_nameindex(),\"routes\":open(\"/proc/net/route\").read(),\"ipv6Routes\":open(\"/proc/net/ipv6_route\").read()}\nprint(\"ERR ISOLATION \"+json.dumps(state),flush=True)\nassert state[\"netns\"] != sys.argv[1], \"network namespace was not isolated\"\nassert [name for _,name in state[\"interfaces\"]] == [\"lo\"], \"non-loopback interface present\"\nassert len(state[\"routes\"].splitlines()) == 1, \"IPv4 route present\"\nassert all(line.split()[-1] == \"lo\" for line in state[\"ipv6Routes\"].splitlines()), \"non-loopback IPv6 route present\"\nif len(sys.argv)>2: os.execv(sys.argv[2],sys.argv[2:])\n",
"net:[4026531833]"
],
"exit": 0,
"stdout": "ERR ISOLATION {\"netns\": \"net:[4026534801]\", \"interfaces\": [[1, \"lo\"]], \"routes\": \"Iface\\tDestination\\tGateway \\tFlags\\tRefCnt\\tUse\\tMetric\\tMask\\t\\tMTU\\tWindow\\tIRTT \\n\", \"ipv6Routes\": \"00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo\\n00000000000000000000000000000001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000002 00000000 80200001 lo\\n00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo\\n\"}\n",
"stderr": ""
}
@@ -0,0 +1,346 @@
---------------------------------------------
Log /tmp/work/profile/logs/logs_2026-09-19_08-32-13/console.log started at 2026-09-19 08:32:13 (2026-09-19 06:32:13 UTC)
08:32:13.285 ENGINE : FileSystem: Adding relative directory '/tmp/work/profile/logs/logs_2026-09-19_08-32-13' to filesystem under name logs
08:32:13.285 ENGINE : FileSystem: Adding relative directory '/tmp/work/profile/profile' to filesystem under name profile
08:32:13.285 ENGINE : FileSystem: Current working directory: '/tmp/runtime/'
08:32:13.287 ENGINE : Initializing engine, version 192142
08:32:13.287 ENGINE : CLI Params: -addonsDir /tmp/source/addons -addons 2528466DE220D91C -profile /tmp/work/profile -noBackend -noSound -noSplash -noThrow -bindIP 127.0.0.1 -bindPort 2001 -maxFPS 30 -logStats 5000 -server {AD62322D5213C440}Missions/ERR_Everon_Base.conf
08:32:13.288 ENGINE : Addon dirs:
08:32:13.289 ENGINE : dir: '/tmp/source/addons'
08:32:13.289 ENGINE : dir: './addons'
08:32:13.289 ENGINE : dir: '/tmp/work/profile/addons'
08:32:13.289 ENGINE : Available addons:
08:32:13.289 ENGINE : gproj: '/tmp/source/addons/core/addon.gproj' guid: '2528466DE220D91C'
08:32:13.289 ENGINE : gproj: '/tmp/source/addons/ai/addon.gproj' guid: '5192138CB9D5B911'
08:32:13.289 ENGINE : gproj: '/tmp/source/addons/intel/addon.gproj' guid: 'D31039C7C53E348A'
08:32:13.289 ENGINE : gproj: '/tmp/source/addons/chat/addon.gproj' guid: 'FA804F411BDDF2C6'
08:32:13.289 ENGINE : gproj: '/tmp/source/addons/map/addon.gproj' guid: '9AAEE9041D79809E'
08:32:13.289 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859' (packed)
08:32:13.289 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C' (packed)
08:32:13.289 ENGINE : FileSystem: Adding relative directory '/tmp/source/addons/core' to filesystem under name ERR_Core
08:32:13.366 ENGINE : FileSystem: Adding package './addons/data/' (pak count: 6) to filesystem under name ArmaReforger
08:32:13.366 ENGINE : FileSystem: Adding package './addons/core/' (pak count: 1) to filesystem under name core
08:32:13.366 ENGINE : CPU vendor : AuthenticAMD
08:32:13.366 ENGINE : CPU type : 2
08:32:13.366 ENGINE : CPU name : AMD Ryzen 7 3800XT 8-Core Processor
08:32:13.366 ENGINE : CPU cache info : Unknown cache
08:32:13.366 ENGINE : CPU count logical : 16
08:32:13.366 ENGINE : CPU count physical : 8
08:32:13.366 ENGINE : CPU features : mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcnt aesni pclmulqdq osxsave avx sha avx2
08:32:13.366 RESOURCES : ResourceDB: loading cache (id=0 name=ERR_Core path=/tmp/source/addons/core/resourceDatabase.rdb)
08:32:13.366 RESOURCES : ResourceDB: loading cache (id=1 name=ArmaReforger path=./addons/data/resourceDatabase.rdb)
08:32:13.483 RESOURCES : ResourceDB: loading cache (id=2 name=core path=./addons/core/resourceDatabase.rdb)
08:32:13.484 RESOURCES : ResourceDB: loading cache (id=3 name=profile path=/tmp/work/profile/profile/resourceDatabase.rdb)
08:32:13.484 RESOURCES : ResourceDB: loading cache (id=4 name=logs path=/tmp/work/profile/logs/logs_2026-09-19_08-32-13/resourceDatabase.rdb)
08:32:13.632 ENGINE : GameProject load
08:32:13.632 ENGINE : Loaded addons:
08:32:13.632 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C'
08:32:13.632 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859'
08:32:13.632 ENGINE : gproj: '/tmp/source/addons/core/addon.gproj' guid: '2528466DE220D91C'
08:32:13.633 ENGINE : Loading custom engine user config '$profile:.save/settings/ReforgerEngineSettings.conf'
08:32:13.633 ENGINE : No Enfusion settings file loaded. Continuing with defaults
08:32:13.633 RENDER : Basic screen setup:
08:32:13.633 RENDER : Back buffer width x height: 0x0
08:32:13.633 RENDER : Back buffer format : TEXFMT_UNKNOWN (0)
08:32:13.633 RENDER : MSAA : none
08:32:13.633 RENDER : GPU_DUMMY (0xFFFF) (Enfusion dummy render) with 1 GPU detected, VRAM 128MB (fast 128MB), shared 128MB, driver version Unknown version
08:32:13.633 RENDER : Detected output devices:
08:32:13.633 RENDER : * 1 device/s connected to Dummy:
08:32:13.633 RENDER : Dummy output (Dummy device for our dummy render.), 1920x1080 (offset 0x0), 60Hz
08:32:13.633 RENDER : Concurrent frames limit 2
08:32:13.633 ENGINE : Job system settings: coreCount=16, shortJobContextCount=16, shortJobThreadCount=15, longJobThreadCount=7
08:32:13.645 PROFILING : Settings changed took: 0.028000 ms
08:32:13.647 ENGINE : Initializing inputs.
08:32:13.654 NETWORK : Initializing networking.
08:32:13.654 NETWORK : Using new GameRplScheduler.
08:32:13.655 SCRIPT : SCRIPT : Initializing scripts
08:32:13.655 SCRIPT : SCRIPT : ScriptProjectManager init
08:32:13.655 PROFILING : ScriptProjectManager init took: 0.008000 ms
08:32:13.672 PROFILING : Initializing scripts took: 16.979000 ms
08:32:13.672 BACKEND : Backend Services are disabled.
08:32:13.672 ENGINE : Enfusion engine successfully created.
08:32:13.674 GUI : Using default language (en_us)
08:32:13.674 GUI : Loading 'en_us' localization file.
08:32:13.674 INIT : INIT : Loading StringTable
08:32:13.698 PROFILING : Loading StringTable took: 23.889000 ms
08:32:13.698 SCRIPT : SCRIPT : Compiling GameLib scripts
08:32:13.727 SCRIPT : Module: GameLib; loaded 466x files; 608x classes; used 654K of static memory; defines: "PLATFORM_LINUX,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: d66caacb
08:32:13.727 PROFILING : Compiling GameLib scripts took: 29.382000 ms
08:32:13.727 SCRIPT : SCRIPT : Compiling Game scripts
08:32:14.505 SCRIPT : Compiling Game scripts
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,785": 'GetPlayerPlatformKind' is obsolete
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,786": 'GetPlayerPlatformId' is obsolete
08:32:14.728 SCRIPT (W): @"Scripts/Game/ERR/ERR_SiteService.c,191": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.739 SCRIPT (W): @"Scripts/Game/Workshop/SCR_AddonManager.c,876": 'GetRefCount' is obsolete: Will be removed
08:32:14.765 SCRIPT (W): @"Scripts/Game/Campaign/SCR_PlayerProfileManagerComponent.c,142": 'PlayerData' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,159": 'GetDSSession' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,162": 'RoomID' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,197": 'GetDSSession' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,201": 'RoomID' is obsolete
08:32:14.885 SCRIPT (W): @"Scripts/Game/ERR/ERR_CasualtyGroundSupport.c,21": 'GetBoneIndex' is obsolete: Use GetAnimation().GetBoneIndex() instead
08:32:14.929 SCRIPT (W): @"Scripts/Game/ERR/ERR_SpawnLogic.c,64": 'GetPlayerIdentityId' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,481": 'GetStorage' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,483": 'GetOnlineWritePrivilege' is obsolete
08:32:14.943 SCRIPT (W): @"Scripts/Game/Utilities/SCR_PlayerIdentityUtils.c,20": 'GetPlayerIdentityId' is obsolete
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,45": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,56": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,643": 'GetNotifyCount' is obsolete: Will be substitued by Notification Api.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,645": 'GetNotifyItem' is obsolete: Will be substitued by Notification Api.
08:32:15.036 SCRIPT (W): @"Scripts/Game/DataCollection/PlayerData/SCR_PlayerData.c,210": 'PlayerData' is obsolete
08:32:15.140 SCRIPT : Module: Game; loaded 5732x files; 11115x classes; used 25833K 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"; CRC32: 2ef250fb
08:32:15.155 PROFILING : Compiling Game scripts took: 1428.098000 ms
08:32:15.155 INIT : Creating game instance(ArmaReforgerScripted), version 1.8.0.13 built 2026-08-21 14:30:18 UTC.
08:32:15.175 ENGINE : Game successfully created.
08:32:15.259 PLATFORM : Save data from container 'settings' have been loaded
08:32:15.358 PLATFORM : Save data from container 'sessions' have been loaded
08:32:15.358 PLATFORM : System language differs from the saved one - using new language {new: 'en_us'; old: ''}
08:32:15.358 PLATFORM : Save data transaction to 'settings' started.
08:32:15.359 NETWORK : Starting local multiplayer server using command line args.
08:32:15.458 DEFAULT : [SaveGameManager] Starting new playthrough nr.0 '' for mission '{AD62322D5213C440}Missions/ERR_Everon_Base.conf'.
08:32:15.458 WORLD : WORLD : Entities load '$ERR_Core:Worlds/ERR_Everon.ent'
08:32:16.058 WORLD : Entities load '$ERR_Core:Worlds/ERR_Everon.ent'
08:32:16.058 WORLD : Subscene load @"{853E92315D1D9EFE}worlds/Eden/Eden.ent"
08:32:16.058 RESOURCES : GetResourceObject @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:16.058 WORLD : Entity prefab load @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:16.058 RESOURCES (E): Wrong GUID/name for resource @"{45ECF6B1797D3CD9}system/wbdata/PreviewWindow/TransparentMat.emat" in property "AssignedMaterial"
08:32:16.206 PROFILING : Entities load took: 748.131000 ms
08:32:16.207 WORLD : WORLD : Game::LoadEntities
08:32:16.207 WORLD : WORLD : Initializing world systems @"{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf"
08:32:16.208 NETWORK : Enabled lag compensation, 29 frames with 100 FPS and 280 ms rewind limits.
08:32:16.208 WORLD : WORLD : CreateEntities
08:32:16.208 WORLD : WORLD : CreateEntities
08:32:16.208 WORLD : WORLD : NotifyBeforeEntitiesCreated
08:32:16.209 RESOURCES : Loaded mission headers from 7 addon(s)!
08:32:16.209 PROFILING : NotifyBeforeEntitiesCreated took: 0.922000 ms
08:32:16.209 WORLD : WORLD : Wait for preloading data
08:32:19.448 WORLD : Game::LoadEntities
08:32:19.448 WORLD : CreateEntities
08:32:19.448 WORLD : CreateEntities
08:32:19.448 WORLD : Wait for preloading data
08:32:19.448 RESOURCES : GetResourceObject @"{58E62C5D17281925}Prefabs/Particles/Blasts/Blast_small_Invisible_Trigger.et"
08:32:19.448 WORLD : Entity prefab load @"{58E62C5D17281925}Prefabs/Particles/Blasts/Blast_small_Invisible_Trigger.et"
08:32:19.448 RESOURCES (E): Wrong GUID/name for resource @"{FF35BE9795BA3797}system/wbdata/Gizmo3D/sphere.xob" in property "Object"
08:32:19.514 PROFILING : Wait for preloading data took: 3304.813000 ms
08:32:19.577 ENTITY : Create entity @"ENTITY:2" ('Eden', GenericTerrainEntity) at <0.000000 0.000000 0.000000> @"{5AD924374E8C7AF6}Prefabs/World/Game/Eden/GenericTerrain_Eden.et"
08:32:19.577 PROFILING : PROFILING : Terrain load
08:32:20.724 PROFILING : Terrain load took: 1147.054000 ms
08:32:23.175 ENTITY : Create entity @"ENTITY:610406" ('StaticModelEntity','Assets/Structures/Infrastructure/Towers/TransmitterTower_01/TransmitterTower_01_small.xob') at <1931.796021 81.777000 5138.725098> @"{6A004A8F0571D456}Prefabs/Structures/Infrastructure/Towers/TransmitterTower_01/TransmitterTower_01_small.et"
08:32:23.175 ENTITY : CreateComponent 'ScriptedRadioComponent'
08:32:23.175 DEFAULT (W): World doesn't contain RadioManagerEntity to support any BaseRadioComponent.
08:32:25.294 ENTITY : Create entity @"ENTITY:1104061" ('StaticModelEntity') at <8831.291016 95.934265 2673.487061>
08:32:25.294 ENTITY : EntityPrefabUse @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:25.294 RESOURCES : CreateComponentData @"{904345715F67BBAC}Assets/Structures/Cultural/Calvaries/CalvaryLarge_01/CalvaryLarge_01.xob"
08:32:25.294 MATERIAL : Material load @"{45ECF6B1797D3CD9}system/wbdata/PreviewWindow/TransparentMat.emat"
08:32:25.294 MATERIAL (E): Material file not found
08:32:25.294 MATERIAL (E): Cannot load material @"system/wbdata/PreviewWindow/TransparentMat.emat", creating default one (class MatPBRBasic)
08:32:27.847 WORLD : WORLD : NotifyBeforeEntitiesInitialized
08:32:27.847 PROFILING : NotifyBeforeEntitiesInitialized took: 0.028000 ms
08:32:27.847 WORLD : InitEntities 'world'
08:32:27.847 ENTITY : Init entity @"ENTITY:3" ('SCR_MapEntity1', SCR_MapEntity) at <6400.000000 0.000000 6400.000000> @"{E1B88C66BF6CA1F9}Prefabs/World/Game/Eden/MapEntity_Everon.et"
08:32:27.847 SCRIPT (W): SCR_MapEntity: Cannot get the size from terrain. Using default.
08:32:28.358 ENTITY : Init entity @"ENTITY:2305843009213693953" ('Rereintroduced', ERR_GameMode) at <1076.468018 51.000999 1325.246948> @"{978E045E53EF36C8}Prefabs/ERR/GameMode.et"
08:32:28.358 SCRIPT (W): SCR_PerceivedFactionManagerComponent trying to set fall back faction 'CIV' but this faction could not be found so it is null instead.
08:32:28.359 WORLD : WORLD : NotifyEntitiesInitialized
08:32:28.359 TERRAIN : TERRAIN : Initializing road networks...
08:32:28.360 PROFILING : Initializing road networks... took: 1.812000 ms
08:32:28.360 DEFAULT : DEFAULT : WorldVolumesCollection
08:32:28.415 PROFILING : WorldVolumesCollection took: 54.141000 ms
08:32:28.415 INIT : INIT : SoundWorldInit
08:32:28.422 PROFILING : SoundWorldInit took: 7.362000 ms
08:32:28.422 PROFILING : NotifyEntitiesInitialized took: 63.416000 ms
08:32:28.422 PROFILING : CreateEntities took: 12213.648000 ms
08:32:28.422 PROFILING : CreateEntities took: 12213.656000 ms
08:32:28.422 WORLD : WORLD : EOnActivate
08:32:28.451 PROFILING : EOnActivate took: 28.588000 ms
08:32:28.451 PROFILING : Game::LoadEntities took: 12243.502000 ms
08:32:28.539 NETWORK : Starting RPL server, listening on address 0.0.0.0:2001, fastValidation=false
08:32:29.005 DEFAULT : Entered online game state.
08:32:29.005 PROFILING : Settings changed took: 0.411000 ms
08:32:29.015 WORLD : Frame start
08:32:29.015 SCRIPT : ScenarioFramework: Available tasks are empty, no new tasks will be generated.
08:32:29.023 WORLD : UpdateEntities
08:32:29.023 WORLD : Frame
08:32:29.023 SCRIPT : SCR_BaseGameMode::OnGameStateChanged = GAME
08:32:30.376 SCRIPT : Rereintroduced [sites]: cache clearance position=<6086,211.538,7160> clear=1
08:32:30.379 SCRIPT : Rereintroduced [sites]: authored everon-prison-1 at <6090,211.444,7160>
08:32:30.379 SCRIPT : Rereintroduced [sites]: cache clearance position=<6150,203.288,7050> clear=1
08:32:30.382 SCRIPT : Rereintroduced [sites]: authored everon-supply-1 at <6150,203.288,7050>
08:32:30.383 SCRIPT : Rereintroduced [sites]: authored everon-radio-1 at <6500,159.756,7200>
08:32:30.401 SCRIPT : Rereintroduced [sites]: authored everon-extraction-1 at <7000,65.2562,7500>
08:32:30.401 SCRIPT : Rereintroduced [sites]: cache clearance position=<5960,220.256,7220> clear=1
08:32:30.402 SCRIPT : Rereintroduced [sites]: transport parking=<5960,220.256,7212> radius=4 terrainRange=0.8125 obstructed=0 clear=1
08:32:30.418 SCRIPT : Rereintroduced [sites]: authored everon-supply-2 at <5960,220.256,7220>
08:32:30.419 SCRIPT : Rereintroduced [sites]: cache clearance position=<6340,175.788,7400> clear=1
08:32:30.419 SCRIPT : Rereintroduced [sites]: authored everon-medical-1 at <6340,175.788,7400>
08:32:30.420 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.6,7300> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.913,7296> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6736,140.975,7300> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6744,140.288,7300> clear=1
08:32:30.422 SCRIPT : Rereintroduced [sites]: authored everon-outpost-1 at <6740,140.6,7300>
08:32:30.422 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=0 origin=<7012,63.725,7500> up=1
08:32:30.422 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0 angularSpeed=0
08:32:30.422 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=0 engine=0 origin=<0,0,0> up=1 entityDifference=10267.5
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012,64.0216,7502.25>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7012,63.7216,7502.25> terrainY=63.2926 tireTerrainGap=0.428944
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7012,64.0216,7502.25> radius=0.3 bottom=<7012,63.7216,7502.25> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.72,64.4897,7497.97>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.72,64.0397,7497.97> terrainY=64.1655 tireTerrainGap=-0.125717
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7009.72,64.4897,7497.97> radius=0.45 bottom=<7009.72,64.0397,7497.97> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.28,64.4898,7497.97>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.28,64.0398,7497.97> terrainY=63.8096 tireTerrainGap=0.230156
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7014.28,64.4898,7497.97> radius=0.45 bottom=<7014.28,64.0398,7497.97> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.442 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.07,63.5457,7499.69> up=0.995704
08:32:31.442 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.345002 angularSpeed=0.059733
08:32:31.442 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.04,63.6117,7501.97>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.04,63.3117,7501.97> terrainY=63.3164 tireTerrainGap=-0.00473785
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7012.04,63.6117,7501.97> radius=0.3 bottom=<7012.04,63.3117,7501.97> fraction=0.433053 normal=<-0,0.990257,0.139255> self=0 dynamic=0 supported=1 gap=-0.00472641
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.88,64.5942,7497.69>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.88,64.1442,7497.69> terrainY=64.1567 tireTerrainGap=-0.0125656
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7009.88,64.5942,7497.69> radius=0.45 bottom=<7009.88,64.1442,7497.69> fraction=0.397644 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=-0.0125198
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.42,64.2597,7497.75>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.42,63.8097,7497.75> terrainY=63.8177 tireTerrainGap=-0.00805283
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7014.42,64.2597,7497.75> radius=0.45 bottom=<7014.42,63.8097,7497.75> fraction=0.417778 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00808716
08:32:31.442 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.508 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.09,63.5355,7499.71> up=0.994317
08:32:32.508 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.102028 angularSpeed=0.0585238
08:32:32.508 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.05,63.6213,7501.99>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.05,63.3213,7501.99> terrainY=63.3145 tireTerrainGap=0.00682831
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7012.05,63.6213,7501.99> radius=0.3 bottom=<7012.05,63.3213,7501.99> fraction=0.485987 normal=<-0,0.990257,0.139255> self=0 dynamic=0 supported=1 gap=0.00691605
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.93,64.6035,7497.7>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.93,64.1535,7497.7> terrainY=64.1488 tireTerrainGap=0.00473022
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7009.93,64.6035,7497.7> radius=0.45 bottom=<7009.93,64.1535,7497.7> fraction=0.476164 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00476074
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.47,64.2666,7497.79>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.47,63.8166,7497.79> terrainY=63.8149 tireTerrainGap=0.00174332
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7014.47,64.2666,7497.79> radius=0.45 bottom=<7014.47,63.8166,7497.79> fraction=0.4625 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=0.00175095
08:32:32.508 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:32.508 SCRIPT : Rereintroduced [extraction placement]: native supported aircraft stable for one second, fuel present, exactly one initial wake
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.576 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.12,63.531,7499.75> up=0.994244
08:32:33.576 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.0510799 angularSpeed=0.0476384
08:32:33.576 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.07,63.6153,7502.02>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.07,63.3153,7502.02> terrainY=63.3111 tireTerrainGap=0.00417709
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7012.07,63.6153,7502.02> radius=0.3 bottom=<7012.07,63.3153,7502.02> fraction=0.473567 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00418472
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5924,7497.72>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1424,7497.72> terrainY=64.1428 tireTerrainGap=-0.00038147
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5924,7497.72> radius=0.45 bottom=<7009.97,64.1424,7497.72> fraction=0.453169 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=-0.000297546
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.258,7497.83>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.808,7497.83> terrainY=63.8124 tireTerrainGap=-0.00437546
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.258,7497.83> radius=0.45 bottom=<7014.51,63.808,7497.83> fraction=0.434444 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00442123
08:32:33.576 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.010 WORLD : UpdateEntities
08:32:34.010 WORLD : Frame
08:32:34.010 DEFAULT : FPS: 29.8, frame time (avg: 33.6 ms, min: 3.3 ms, max: 89.1 ms, mean: 33.3 ms, median: 33.3 ms), Mem: 996027 kB, Player: 0, AI: 29, AIChar: 22, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 698, Static: 57591, Disabled: 30 | New: 0, Del: 0, Bump: 16)
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.642 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.13,63.5286,7499.76> up=0.994199
08:32:34.642 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=0 speed=0 angularSpeed=0
08:32:34.642 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.08,63.6119,7502.03>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.08,63.3119,7502.03> terrainY=63.3102 tireTerrainGap=0.00168228
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7012.08,63.6119,7502.03> radius=0.3 bottom=<7012.08,63.3119,7502.03> fraction=0.462159 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00167465
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5928,7497.74>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1428,7497.74> terrainY=64.1412 tireTerrainGap=0.00151825
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5928,7497.74> radius=0.45 bottom=<7009.97,64.1428,7497.74> fraction=0.461582 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00154877
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.2594,7497.84>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.8094,7497.84> terrainY=63.8118 tireTerrainGap=-0.0024147
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.2594,7497.84> radius=0.45 bottom=<7014.51,63.8094,7497.84> fraction=0.443333 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00246811
08:32:34.642 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.708 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.13,63.5286,7499.76> up=0.994199
08:32:35.708 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=0 speed=0 angularSpeed=0
08:32:35.708 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:35.708 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.08,63.6119,7502.03>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.08,63.3119,7502.03> terrainY=63.3102 tireTerrainGap=0.00168228
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7012.08,63.6119,7502.03> radius=0.3 bottom=<7012.08,63.3119,7502.03> fraction=0.462159 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00167465
08:32:35.709 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5928,7497.74>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1428,7497.74> terrainY=64.1412 tireTerrainGap=0.00151825
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5928,7497.74> radius=0.45 bottom=<7009.97,64.1428,7497.74> fraction=0.461582 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00154877
08:32:35.709 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.2594,7497.84>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.8094,7497.84> terrainY=63.8118 tireTerrainGap=-0.0024147
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.2594,7497.84> radius=0.45 bottom=<7014.51,63.8094,7497.84> fraction=0.443333 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00246811
08:32:35.709 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:35.976 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.976 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.976 SCRIPT : Rereintroduced [sites]: 7 sites and 117 physical stock items ready
08:32:35.976 SCRIPT : Rereintroduced [environment]: date=authored weather=authored
08:32:35.977 SCRIPT : Rereintroduced [time]: started at 14:00 with 1x progression
08:32:35.977 SCRIPT : Rereintroduced [mission]: phase 0 -> 1
08:32:39.010 WORLD : UpdateEntities
08:32:39.010 WORLD : Frame
08:32:39.010 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 6.5 ms, max: 65.6 ms, mean: 33.3 ms, median: 33.3 ms), Mem: 1001182 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:32:44.043 WORLD : UpdateEntities
08:32:44.043 WORLD : Frame
08:32:44.043 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 29.2 ms, max: 38.2 ms, mean: 33.3 ms, median: 33.5 ms), Mem: 1001296 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:32:49.043 WORLD : UpdateEntities
08:32:49.043 WORLD : Frame
08:32:49.043 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.3 ms, max: 34.3 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001371 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:32:54.043 WORLD : UpdateEntities
08:32:54.043 WORLD : Frame
08:32:54.043 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 30.6 ms, max: 35.6 ms, mean: 33.3 ms, median: 33.3 ms), Mem: 1001500 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:32:59.043 WORLD : UpdateEntities
08:32:59.043 WORLD : Frame
08:32:59.043 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.4 ms, max: 34.5 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001492 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:04.076 WORLD : UpdateEntities
08:33:04.076 WORLD : Frame
08:33:04.076 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.0 ms, max: 34.9 ms, mean: 33.3 ms, median: 33.3 ms), Mem: 1001452 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:09.076 WORLD : UpdateEntities
08:33:09.076 WORLD : Frame
08:33:09.076 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.1 ms, max: 34.4 ms, mean: 33.3 ms, median: 33.5 ms), Mem: 1001493 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:14.076 WORLD : UpdateEntities
08:33:14.076 WORLD : Frame
08:33:14.076 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.0 ms, max: 34.5 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001501 kB, Player: 0, AI: 46, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 790, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:19.109 WORLD : UpdateEntities
08:33:19.109 WORLD : Frame
08:33:19.109 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.3 ms, max: 34.4 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001522 kB, Player: 0, AI: 47, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 791, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:24.109 WORLD : UpdateEntities
08:33:24.109 WORLD : Frame
08:33:24.109 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 31.6 ms, max: 35.2 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001558 kB, Player: 0, AI: 47, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 791, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:29.143 WORLD : UpdateEntities
08:33:29.143 WORLD : Frame
08:33:29.143 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 31.8 ms, max: 34.8 ms, mean: 33.3 ms, median: 33.5 ms), Mem: 1001460 kB, Player: 0, AI: 47, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 791, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:34.176 WORLD : UpdateEntities
08:33:34.176 WORLD : Frame
08:33:34.176 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.4 ms, max: 34.3 ms, mean: 33.3 ms, median: 33.4 ms), Mem: 1001558 kB, Player: 0, AI: 47, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 791, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
08:33:39.176 WORLD : UpdateEntities
08:33:39.176 WORLD : Frame
08:33:39.176 DEFAULT : FPS: 30.0, frame time (avg: 33.3 ms, min: 32.3 ms, max: 34.5 ms, mean: 33.3 ms, median: 33.5 ms), Mem: 1001527 kB, Player: 0, AI: 47, AIChar: 36, Veh: 0 (2), Proj (S: 0, M: 0, G: 0 | 0), Streaming(Dynam: 791, Static: 57591, Disabled: 31 | New: 0, Del: 0, Bump: 16)
@@ -0,0 +1,49 @@
---------------------------------------------
Log /tmp/work/profile/logs/logs_2026-09-19_08-32-13/error.log started at 2026-09-19 08:32:14 (2026-09-19 06:32:14 UTC)
08:32:14.505 SCRIPT : Compiling Game scripts
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,785": 'GetPlayerPlatformKind' is obsolete
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,786": 'GetPlayerPlatformId' is obsolete
08:32:14.728 SCRIPT (W): @"Scripts/Game/ERR/ERR_SiteService.c,191": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.739 SCRIPT (W): @"Scripts/Game/Workshop/SCR_AddonManager.c,876": 'GetRefCount' is obsolete: Will be removed
08:32:14.765 SCRIPT (W): @"Scripts/Game/Campaign/SCR_PlayerProfileManagerComponent.c,142": 'PlayerData' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,159": 'GetDSSession' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,162": 'RoomID' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,197": 'GetDSSession' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,201": 'RoomID' is obsolete
08:32:14.885 SCRIPT (W): @"Scripts/Game/ERR/ERR_CasualtyGroundSupport.c,21": 'GetBoneIndex' is obsolete: Use GetAnimation().GetBoneIndex() instead
08:32:14.929 SCRIPT (W): @"Scripts/Game/ERR/ERR_SpawnLogic.c,64": 'GetPlayerIdentityId' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,481": 'GetStorage' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,483": 'GetOnlineWritePrivilege' is obsolete
08:32:14.943 SCRIPT (W): @"Scripts/Game/Utilities/SCR_PlayerIdentityUtils.c,20": 'GetPlayerIdentityId' is obsolete
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,45": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,56": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,643": 'GetNotifyCount' is obsolete: Will be substitued by Notification Api.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,645": 'GetNotifyItem' is obsolete: Will be substitued by Notification Api.
08:32:15.036 SCRIPT (W): @"Scripts/Game/DataCollection/PlayerData/SCR_PlayerData.c,210": 'PlayerData' is obsolete
08:32:16.058 WORLD : Entities load '$ERR_Core:Worlds/ERR_Everon.ent'
08:32:16.058 WORLD : Subscene load @"{853E92315D1D9EFE}worlds/Eden/Eden.ent"
08:32:16.058 RESOURCES : GetResourceObject @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:16.058 WORLD : Entity prefab load @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:16.058 RESOURCES (E): Wrong GUID/name for resource @"{45ECF6B1797D3CD9}system/wbdata/PreviewWindow/TransparentMat.emat" in property "AssignedMaterial"
08:32:19.448 WORLD : Game::LoadEntities
08:32:19.448 WORLD : CreateEntities
08:32:19.448 WORLD : CreateEntities
08:32:19.448 WORLD : Wait for preloading data
08:32:19.448 RESOURCES : GetResourceObject @"{58E62C5D17281925}Prefabs/Particles/Blasts/Blast_small_Invisible_Trigger.et"
08:32:19.448 WORLD : Entity prefab load @"{58E62C5D17281925}Prefabs/Particles/Blasts/Blast_small_Invisible_Trigger.et"
08:32:19.448 RESOURCES (E): Wrong GUID/name for resource @"{FF35BE9795BA3797}system/wbdata/Gizmo3D/sphere.xob" in property "Object"
08:32:23.175 ENTITY : Create entity @"ENTITY:610406" ('StaticModelEntity','Assets/Structures/Infrastructure/Towers/TransmitterTower_01/TransmitterTower_01_small.xob') at <1931.796021 81.777000 5138.725098> @"{6A004A8F0571D456}Prefabs/Structures/Infrastructure/Towers/TransmitterTower_01/TransmitterTower_01_small.et"
08:32:23.175 ENTITY : CreateComponent 'ScriptedRadioComponent'
08:32:23.175 DEFAULT (W): World doesn't contain RadioManagerEntity to support any BaseRadioComponent.
08:32:25.294 ENTITY : Create entity @"ENTITY:1104061" ('StaticModelEntity') at <8831.291016 95.934265 2673.487061>
08:32:25.294 ENTITY : EntityPrefabUse @"{C8FAB83670BCF7C3}Prefabs/Structures/Cultural/Calvaries/CalvaryLarge_01.et"
08:32:25.294 RESOURCES : CreateComponentData @"{904345715F67BBAC}Assets/Structures/Cultural/Calvaries/CalvaryLarge_01/CalvaryLarge_01.xob"
08:32:25.294 MATERIAL : Material load @"{45ECF6B1797D3CD9}system/wbdata/PreviewWindow/TransparentMat.emat"
08:32:25.294 MATERIAL (E): Material file not found
08:32:25.294 MATERIAL (E): Cannot load material @"system/wbdata/PreviewWindow/TransparentMat.emat", creating default one (class MatPBRBasic)
08:32:27.847 WORLD : InitEntities 'world'
08:32:27.847 ENTITY : Init entity @"ENTITY:3" ('SCR_MapEntity1', SCR_MapEntity) at <6400.000000 0.000000 6400.000000> @"{E1B88C66BF6CA1F9}Prefabs/World/Game/Eden/MapEntity_Everon.et"
08:32:27.847 SCRIPT (W): SCR_MapEntity: Cannot get the size from terrain. Using default.
08:32:28.358 ENTITY : Init entity @"ENTITY:2305843009213693953" ('Rereintroduced', ERR_GameMode) at <1076.468018 51.000999 1325.246948> @"{978E045E53EF36C8}Prefabs/ERR/GameMode.et"
08:32:28.358 SCRIPT (W): SCR_PerceivedFactionManagerComponent trying to set fall back faction 'CIV' but this faction could not be found so it is null instead.
@@ -0,0 +1,173 @@
---------------------------------------------
Log /tmp/work/profile/logs/logs_2026-09-19_08-32-13/script.log started at 2026-09-19 08:32:13 (2026-09-19 06:32:13 UTC)
08:32:13.655 SCRIPT : SCRIPT : Initializing scripts
08:32:13.655 SCRIPT : SCRIPT : ScriptProjectManager init
08:32:13.698 SCRIPT : SCRIPT : Compiling GameLib scripts
08:32:13.727 SCRIPT : Module: GameLib; loaded 466x files; 608x classes; used 654K of static memory; defines: "PLATFORM_LINUX,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: d66caacb
08:32:13.727 SCRIPT : SCRIPT : Compiling Game scripts
08:32:14.505 SCRIPT : Compiling Game scripts
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,785": 'GetPlayerPlatformKind' is obsolete
08:32:14.505 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,786": 'GetPlayerPlatformId' is obsolete
08:32:14.728 SCRIPT (W): @"Scripts/Game/ERR/ERR_SiteService.c,191": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.739 SCRIPT (W): @"Scripts/Game/Workshop/SCR_AddonManager.c,876": 'GetRefCount' is obsolete: Will be removed
08:32:14.765 SCRIPT (W): @"Scripts/Game/Campaign/SCR_PlayerProfileManagerComponent.c,142": 'PlayerData' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,159": 'GetDSSession' is obsolete
08:32:14.856 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,162": 'RoomID' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,197": 'GetDSSession' is obsolete
08:32:14.857 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,201": 'RoomID' is obsolete
08:32:14.885 SCRIPT (W): @"Scripts/Game/ERR/ERR_CasualtyGroundSupport.c,21": 'GetBoneIndex' is obsolete: Use GetAnimation().GetBoneIndex() instead
08:32:14.929 SCRIPT (W): @"Scripts/Game/ERR/ERR_SpawnLogic.c,64": 'GetPlayerIdentityId' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,481": 'GetStorage' is obsolete
08:32:14.941 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,483": 'GetOnlineWritePrivilege' is obsolete
08:32:14.943 SCRIPT (W): @"Scripts/Game/Utilities/SCR_PlayerIdentityUtils.c,20": 'GetPlayerIdentityId' is obsolete
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,45": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.978 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,56": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,643": 'GetNotifyCount' is obsolete: Will be substitued by Notification Api.
08:32:14.979 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,645": 'GetNotifyItem' is obsolete: Will be substitued by Notification Api.
08:32:15.036 SCRIPT (W): @"Scripts/Game/DataCollection/PlayerData/SCR_PlayerData.c,210": 'PlayerData' is obsolete
08:32:15.140 SCRIPT : Module: Game; loaded 5732x files; 11115x classes; used 25833K 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"; CRC32: 2ef250fb
08:32:27.847 SCRIPT (W): SCR_MapEntity: Cannot get the size from terrain. Using default.
08:32:28.358 SCRIPT (W): SCR_PerceivedFactionManagerComponent trying to set fall back faction 'CIV' but this faction could not be found so it is null instead.
08:32:29.015 SCRIPT : ScenarioFramework: Available tasks are empty, no new tasks will be generated.
08:32:29.023 SCRIPT : SCR_BaseGameMode::OnGameStateChanged = GAME
08:32:30.376 SCRIPT : Rereintroduced [sites]: cache clearance position=<6086,211.538,7160> clear=1
08:32:30.379 SCRIPT : Rereintroduced [sites]: authored everon-prison-1 at <6090,211.444,7160>
08:32:30.379 SCRIPT : Rereintroduced [sites]: cache clearance position=<6150,203.288,7050> clear=1
08:32:30.382 SCRIPT : Rereintroduced [sites]: authored everon-supply-1 at <6150,203.288,7050>
08:32:30.383 SCRIPT : Rereintroduced [sites]: authored everon-radio-1 at <6500,159.756,7200>
08:32:30.401 SCRIPT : Rereintroduced [sites]: authored everon-extraction-1 at <7000,65.2562,7500>
08:32:30.401 SCRIPT : Rereintroduced [sites]: cache clearance position=<5960,220.256,7220> clear=1
08:32:30.402 SCRIPT : Rereintroduced [sites]: transport parking=<5960,220.256,7212> radius=4 terrainRange=0.8125 obstructed=0 clear=1
08:32:30.418 SCRIPT : Rereintroduced [sites]: authored everon-supply-2 at <5960,220.256,7220>
08:32:30.419 SCRIPT : Rereintroduced [sites]: cache clearance position=<6340,175.788,7400> clear=1
08:32:30.419 SCRIPT : Rereintroduced [sites]: authored everon-medical-1 at <6340,175.788,7400>
08:32:30.420 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.6,7300> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.913,7296> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6736,140.975,7300> clear=1
08:32:30.421 SCRIPT : Rereintroduced [sites]: cache clearance position=<6744,140.288,7300> clear=1
08:32:30.422 SCRIPT : Rereintroduced [sites]: authored everon-outpost-1 at <6740,140.6,7300>
08:32:30.422 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=0 origin=<7012,63.725,7500> up=1
08:32:30.422 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0 angularSpeed=0
08:32:30.422 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=0 engine=0 origin=<0,0,0> up=1 entityDifference=10267.5
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012,64.0216,7502.25>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7012,63.7216,7502.25> terrainY=63.2926 tireTerrainGap=0.428944
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7012,64.0216,7502.25> radius=0.3 bottom=<7012,63.7216,7502.25> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.72,64.4897,7497.97>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.72,64.0397,7497.97> terrainY=64.1655 tireTerrainGap=-0.125717
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7009.72,64.4897,7497.97> radius=0.45 bottom=<7009.72,64.0397,7497.97> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.28,64.4898,7497.97>
08:32:30.422 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.28,64.0398,7497.97> terrainY=63.8096 tireTerrainGap=0.230156
08:32:30.422 SCRIPT : ERR GEAR SUPPORT: center=<7014.28,64.4898,7497.97> radius=0.45 bottom=<7014.28,64.0398,7497.97> fraction=1 normal=<0,0,0> self=0 dynamic=0 supported=0 gap=0.119999
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:30.422 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=0 conscious=0 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.175 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.442 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.07,63.5457,7499.69> up=0.995704
08:32:31.442 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.345002 angularSpeed=0.059733
08:32:31.442 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.04,63.6117,7501.97>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.04,63.3117,7501.97> terrainY=63.3164 tireTerrainGap=-0.00473785
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7012.04,63.6117,7501.97> radius=0.3 bottom=<7012.04,63.3117,7501.97> fraction=0.433053 normal=<-0,0.990257,0.139255> self=0 dynamic=0 supported=1 gap=-0.00472641
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.88,64.5942,7497.69>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.88,64.1442,7497.69> terrainY=64.1567 tireTerrainGap=-0.0125656
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7009.88,64.5942,7497.69> radius=0.45 bottom=<7009.88,64.1442,7497.69> fraction=0.397644 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=-0.0125198
08:32:31.442 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.42,64.2597,7497.75>
08:32:31.442 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.42,63.8097,7497.75> terrainY=63.8177 tireTerrainGap=-0.00805283
08:32:31.442 SCRIPT : ERR GEAR SUPPORT: center=<7014.42,64.2597,7497.75> radius=0.45 bottom=<7014.42,63.8097,7497.75> fraction=0.417778 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00808716
08:32:31.442 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:31.709 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=1 conscious=1 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.242 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.508 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.09,63.5355,7499.71> up=0.994317
08:32:32.508 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.102028 angularSpeed=0.0585238
08:32:32.508 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.05,63.6213,7501.99>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.05,63.3213,7501.99> terrainY=63.3145 tireTerrainGap=0.00682831
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7012.05,63.6213,7501.99> radius=0.3 bottom=<7012.05,63.3213,7501.99> fraction=0.485987 normal=<-0,0.990257,0.139255> self=0 dynamic=0 supported=1 gap=0.00691605
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.93,64.6035,7497.7>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.93,64.1535,7497.7> terrainY=64.1488 tireTerrainGap=0.00473022
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7009.93,64.6035,7497.7> radius=0.45 bottom=<7009.93,64.1535,7497.7> fraction=0.476164 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00476074
08:32:32.508 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.47,64.2666,7497.79>
08:32:32.508 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.47,63.8166,7497.79> terrainY=63.8149 tireTerrainGap=0.00174332
08:32:32.508 SCRIPT : ERR GEAR SUPPORT: center=<7014.47,64.2666,7497.79> radius=0.45 bottom=<7014.47,63.8166,7497.79> fraction=0.4625 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=0.00175095
08:32:32.508 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:32.508 SCRIPT : Rereintroduced [extraction placement]: native supported aircraft stable for one second, fuel present, exactly one initial wake
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=2 conscious=2 nativeComplete=0
08:32:32.775 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.309 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.576 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.12,63.531,7499.75> up=0.994244
08:32:33.576 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=1 speed=0.0510799 angularSpeed=0.0476384
08:32:33.576 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.07,63.6153,7502.02>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.07,63.3153,7502.02> terrainY=63.3111 tireTerrainGap=0.00417709
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7012.07,63.6153,7502.02> radius=0.3 bottom=<7012.07,63.3153,7502.02> fraction=0.473567 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00418472
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5924,7497.72>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1424,7497.72> terrainY=64.1428 tireTerrainGap=-0.00038147
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5924,7497.72> radius=0.45 bottom=<7009.97,64.1424,7497.72> fraction=0.453169 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=-0.000297546
08:32:33.576 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.258,7497.83>
08:32:33.576 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.808,7497.83> terrainY=63.8124 tireTerrainGap=-0.00437546
08:32:33.576 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.258,7497.83> radius=0.45 bottom=<7014.51,63.808,7497.83> fraction=0.434444 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00442123
08:32:33.576 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=3 conscious=3 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:33.842 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.376 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=4 conscious=4 nativeComplete=0
08:32:34.642 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.13,63.5286,7499.76> up=0.994199
08:32:34.642 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=0 speed=0 angularSpeed=0
08:32:34.642 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.08,63.6119,7502.03>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.08,63.3119,7502.03> terrainY=63.3102 tireTerrainGap=0.00168228
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7012.08,63.6119,7502.03> radius=0.3 bottom=<7012.08,63.3119,7502.03> fraction=0.462159 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00167465
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5928,7497.74>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1428,7497.74> terrainY=64.1412 tireTerrainGap=0.00151825
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5928,7497.74> radius=0.45 bottom=<7009.97,64.1428,7497.74> fraction=0.461582 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00154877
08:32:34.642 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.2594,7497.84>
08:32:34.642 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.8094,7497.84> terrainY=63.8118 tireTerrainGap=-0.0024147
08:32:34.642 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.2594,7497.84> radius=0.45 bottom=<7014.51,63.8094,7497.84> fraction=0.443333 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00246811
08:32:34.642 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:34.909 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=5 conscious=5 nativeComplete=0
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.442 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.708 SCRIPT : ERR EXTRACTION PLACEMENT: wakes=1 alive=1 ready=1 origin=<7012.13,63.5286,7499.76> up=0.994199
08:32:35.708 SCRIPT : ERR EXTRACTION PHYSICS: dynamic=1 awake=0 speed=0 angularSpeed=0
08:32:35.708 SCRIPT : ERR EXTRACTION NATIVE: valid=1 contact=1 engine=0 origin=<0,0,0> up=1 entityDifference=10267.4
08:32:35.708 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_F node=-1704401612 center=<7012.08,63.6119,7502.03>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7012.08,63.3119,7502.03> terrainY=63.3102 tireTerrainGap=0.00168228
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7012.08,63.6119,7502.03> radius=0.3 bottom=<7012.08,63.3119,7502.03> fraction=0.462159 normal=<0,0.996962,0.0778877> self=0 dynamic=0 supported=1 gap=0.00167465
08:32:35.709 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bL node=-410678372 center=<7009.97,64.5928,7497.74>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7009.97,64.1428,7497.74> terrainY=64.1412 tireTerrainGap=0.00151825
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7009.97,64.5928,7497.74> radius=0.45 bottom=<7009.97,64.1428,7497.74> fraction=0.461582 normal=<0.139105,0.989191,0.0463683> self=0 dynamic=0 supported=1 gap=0.00154877
08:32:35.709 SCRIPT : ERR GEAR PIVOT: bone=v_wheel_bR node=-410678366 center=<7014.51,64.2594,7497.84>
08:32:35.709 SCRIPT : ERR GEAR TERRAIN: bottom=<7014.51,63.8094,7497.84> terrainY=63.8118 tireTerrainGap=-0.0024147
08:32:35.709 SCRIPT : ERR GEAR SUPPORT: center=<7014.51,64.2594,7497.84> radius=0.45 bottom=<7014.51,63.8094,7497.84> fraction=0.443333 normal=<0.015606,0.998782,0.0468179> self=0 dynamic=0 supported=1 gap=-0.00246811
08:32:35.709 SCRIPT : ERR EXTRACTION FUEL: manager=1 hasFuel=1
08:32:35.976 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.976 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=6 conscious=6 nativeComplete=1
08:32:35.976 SCRIPT : Rereintroduced [sites]: 7 sites and 117 physical stock items ready
08:32:35.976 SCRIPT : Rereintroduced [environment]: date=authored weather=authored
08:32:35.977 SCRIPT : Rereintroduced [time]: started at 14:00 with 1x progression
08:32:35.977 SCRIPT : Rereintroduced [mission]: phase 0 -> 1
@@ -0,0 +1,96 @@
EngineUserSettings {
GameProjectUserSettings GameProjectUserSettings {
}
GraphicsQualitySettings GraphicsQualitySettings {
}
GrassMaterialSettings GrassMaterialSettings {
}
InputDeviceUserSettings InputDeviceUserSettings {
GamepadProfile InputProfileGamepad "{6A66680D49B27FD4}" {
LeftThumbHorizontal InputProfileKey "{6A66680D49B27FD3}" {
Transition CurveCubicSplineFloat "{6A66680D49B27FD2}" {
}
}
LeftThumbVertical InputProfileKey "{6A66680D49B27FD1}" {
Transition CurveCubicSplineFloat "{6A66680D49B3A9D2}" {
}
}
RightThumbHorizontal InputProfileKey "{6A66680D49B3A9D3}" {
Transition CurveCubicSplineFloat "{6A66680D49B3DB15}" {
}
}
RightThumbVertical InputProfileKey "{6A66680D49B3274B}" {
Transition CurveCubicSplineFloat "{6A66680D49ACB6DD}" {
}
}
LeftTrigger InputProfileKey "{6A66680D49AC34C2}" {
Transition CurveCubicSplineFloat "{6A66680D49AC2D4F}" {
}
}
RightTrigger InputProfileKey "{6A66680D49AC2DB0}" {
Transition CurveCubicSplineFloat "{6A66680D49AC696F}" {
}
}
}
JoystickProfile InputProfileJoystick "{6A66680D49AD8C01}" {
Axis00 InputProfileKey "{6A66680D49ADDFE7}" {
Transition CurveCubicSplineFloat "{6A66680D49ADDFE6}" {
}
}
Axis01 InputProfileKey "{6A66680D49AD0E94}" {
Transition CurveCubicSplineFloat "{6A66680D49AD6C11}" {
}
}
Axis02 InputProfileKey "{6A66680D49AEB567}" {
Transition CurveCubicSplineFloat "{6A66680D49AE8459}" {
}
}
Axis03 InputProfileKey "{6A66680D49AED11D}" {
Transition CurveCubicSplineFloat "{6A66680D49AE15EA}" {
}
}
Axis04 InputProfileKey "{6A66680D49AE15E9}" {
Transition CurveCubicSplineFloat "{6A66680D49AE4DC2}" {
}
}
Axis05 InputProfileKey "{6A66680D49AF9DFD}" {
Transition CurveCubicSplineFloat "{6A66680D49AFC7C3}" {
}
}
Axis06 InputProfileKey "{6A66680D49AF1B25}" {
Transition CurveCubicSplineFloat "{6A66680D49AF6CCB}" {
}
}
Axis07 InputProfileKey "{6A66680D49AF4E2B}" {
Transition CurveCubicSplineFloat "{6A66680D49A8B72B}" {
}
}
Axis08 InputProfileKey "{6A66680D49A8AB2F}" {
Transition CurveCubicSplineFloat "{6A66680D49A8AB2E}" {
}
}
Axis09 InputProfileKey "{6A66680D49A88A2C}" {
Transition CurveCubicSplineFloat "{6A66680D49A80A0F}" {
}
}
}
}
MaterialSystemUserSettings MaterialSystemUserSettings {
}
PostprocessUserSettings PostprocessUserSettings {
}
ResourceManagerUserSettings ResourceManagerUserSettings {
}
TerrainGenMaterialSettings TerrainGenMaterialSettings {
}
UserInterfaceSettings UserInterfaceSettings {
LanguageCode "en_us"
SystemLanguageCode "en_us"
}
VideoUserSettings VideoUserSettings {
WindowPosX -640
WindowPosY -360
}
WaterPoolMaterialSettings WaterPoolMaterialSettings {
}
}
@@ -0,0 +1,116 @@
{
"command": [
"bwrap",
"--unshare-net",
"--unshare-pid",
"--unshare-ipc",
"--unshare-uts",
"--die-with-parent",
"--cap-drop",
"ALL",
"--clearenv",
"--ro-bind",
"/",
"/",
"--tmpfs",
"/home",
"--tmpfs",
"/tmp",
"--tmpfs",
"/run",
"--proc",
"/proc",
"--dev",
"/dev",
"--ro-bind",
"/tmp/erri-dedicated-runtime/server",
"/tmp/runtime",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header/source",
"/tmp/source",
"--bind",
"/tmp/erri-dedicated-native-build/attempt-02-header",
"/tmp/work",
"--setenv",
"HOME",
"/tmp/work/home",
"--setenv",
"TMPDIR",
"/tmp/work/tmp",
"--setenv",
"XDG_CONFIG_HOME",
"/tmp/work/home/.config",
"--setenv",
"XDG_DATA_HOME",
"/tmp/work/home/.local/share",
"--setenv",
"XDG_CACHE_HOME",
"/tmp/work/home/.cache",
"--setenv",
"PATH",
"/usr/bin:/bin",
"--setenv",
"LANG",
"C.UTF-8",
"--chdir",
"/tmp/runtime",
"/usr/bin/python3",
"-c",
"import json,os,socket,sys\nstate={\"netns\":os.readlink(\"/proc/self/ns/net\"),\"interfaces\":socket.if_nameindex(),\"routes\":open(\"/proc/net/route\").read(),\"ipv6Routes\":open(\"/proc/net/ipv6_route\").read()}\nprint(\"ERR ISOLATION \"+json.dumps(state),flush=True)\nassert state[\"netns\"] != sys.argv[1], \"network namespace was not isolated\"\nassert [name for _,name in state[\"interfaces\"]] == [\"lo\"], \"non-loopback interface present\"\nassert len(state[\"routes\"].splitlines()) == 1, \"IPv4 route present\"\nassert all(line.split()[-1] == \"lo\" for line in state[\"ipv6Routes\"].splitlines()), \"non-loopback IPv6 route present\"\nif len(sys.argv)>2: os.execv(sys.argv[2],sys.argv[2:])\n",
"net:[4026531833]",
"/tmp/runtime/ArmaReforgerServer",
"-addonsDir",
"/tmp/source/addons",
"-addons",
"2528466DE220D91C",
"-profile",
"/tmp/work/profile",
"-noBackend",
"-noSound",
"-noSplash",
"-noThrow",
"-bindIP",
"127.0.0.1",
"-bindPort",
"2001",
"-maxFPS",
"30",
"-logStats",
"5000",
"-server",
"{AD62322D5213C440}Missions/ERR_Everon_Base.conf"
],
"engine": [
"/tmp/runtime/ArmaReforgerServer",
"-addonsDir",
"/tmp/source/addons",
"-addons",
"2528466DE220D91C",
"-profile",
"/tmp/work/profile",
"-noBackend",
"-noSound",
"-noSplash",
"-noThrow",
"-bindIP",
"127.0.0.1",
"-bindPort",
"2001",
"-maxFPS",
"30",
"-logStats",
"5000",
"-server",
"{AD62322D5213C440}Missions/ERR_Everon_Base.conf"
],
"seconds": 90,
"binarySHA256": "91fdf333ec49c266d309be358aabab4244a93a2f9cfa11853a600e026104001f",
"serverLaunched": true,
"realPlayers": 0,
"multiplayerProven": false,
"supervisorPid": 2151422,
"startedUTC": "2026-09-19T06:32:13Z",
"timeout": true,
"exit": -15,
"finishedUTC": "2026-09-19T06:33:43Z"
}
@@ -0,0 +1,23 @@
{
"scriptErrors": [],
"nativeErrors": [
"08:32:16.058 RESOURCES (E): Wrong GUID/name for resource @\"{45ECF6B1797D3CD9}system/wbdata/PreviewWindow/TransparentMat.emat\" in property \"AssignedMaterial\"",
"08:32:19.448 RESOURCES (E): Wrong GUID/name for resource @\"{FF35BE9795BA3797}system/wbdata/Gizmo3D/sphere.xob\" in property \"Object\"",
"08:32:25.294 MATERIAL (E): Material file not found",
"08:32:25.294 MATERIAL (E): Cannot load material @\"system/wbdata/PreviewWindow/TransparentMat.emat\", creating default one (class MatPBRBasic)"
],
"evidence": [
"08:32:13.672 BACKEND : Backend Services are disabled.",
"08:32:15.175 ENGINE : Game successfully created.",
"08:32:15.458 DEFAULT : [SaveGameManager] Starting new playthrough nr.0 '' for mission '{AD62322D5213C440}Missions/ERR_Everon_Base.conf'.",
"08:32:16.207 WORLD : WORLD : Initializing world systems @\"{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf\"",
"08:32:28.539 NETWORK : Starting RPL server, listening on address 0.0.0.0:2001, fastValidation=false",
"08:32:35.977 SCRIPT : Rereintroduced [mission]: phase 0 -> 1"
],
"limits": [
"No real players or authentication; no multiplayer/performance acceptance",
"90-second supervisor termination, not graceful mission teardown",
"Native installed-asset resource errors preserved; no all-clean claim",
"No direct RplSession.Mode script instrumentation in this unchanged-source run"
]
}
@@ -0,0 +1,279 @@
{
".gitattributes": "86cd7c797b8cac2699f5959add72303d5474f34fb0d141c36e6d8d095f7bc718",
".gitignore": "1647a8de89a13712bdb3678396c3d09b268e90e99b17bd56a1462eef7efd00d1",
"README.md": "557ecb725cb83911cba20c285624bc2f7cd527932407f87844f824e12821524d",
"addons/ai/Prefabs/ERR/MortarCrew.et": "05d3e7353ff9fe5523218a1487b31b7b742b0be8adbcb060c7099978cf008bce",
"addons/ai/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
"addons/ai/Scripts/Game/ERR/ERR_HQ.c": "ceafd6740ed277748744ce56ac0f0bb3a8521fcc060dafb2cdb99896aedf405a",
"addons/ai/Scripts/Game/ERR/ERR_HQJournal.c": "b3e402cfe92d415f37f666045afb062e6e11670ba03a0ca6f2d9fd4fc3520ac1",
"addons/ai/Scripts/Game/ERR/ERR_HQNetwork.c": "92ff2caca52e94c2cc9642dfc8509ce6e9349b257012bade8650bace9231128c",
"addons/ai/Scripts/Game/ERR/ERR_HQObservation.c": "36c978ec5f052213ac1236e1398d85063efbfd7ef60fe04f1fc11447fefe1d68",
"addons/ai/Scripts/Game/ERR/ERR_HQReport.c": "c4d16ccb571db4d9444c0a8d2be7318845d25ff90238b6d304e96a9ea19f1a08",
"addons/ai/Scripts/Game/ERR/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
"addons/ai/Scripts/Game/ERR/ERR_MortarBattery.c": "20a5b1975c2b185afd1b9b476f19730bae24064fab4d0e6538fc44bc49818b21",
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "b843484cd73340a6f865f06ce16b5405b26b9d460a89e8598234c6f27332890b",
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
"addons/ai/Scripts/Game/ERR/ERR_MortarReadiness.c": "1a7282d9bd53dcd115d53c9b460ca62d3218931a74635cc516eac1a13b7d9347",
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
"addons/ai/Scripts/Game/ERR/ERR_MortarSupplyTransfer.c": "34f7eaa01dc68e97aae8c1177b7f8fd6c15d5a41c6dc86de377f00b3613a8e77",
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "60b05d729ee961196b3e3d27bb7942d7aacdf1e42a38f7d63ec2499eea3ed2eb",
"addons/ai/Scripts/Game/ERR/ERR_NativeMortarFiringProbe.c": "d66e57ada46678eb0a6dfa6ff818b656f6132c4eed28881abafafa1e44f8cd2c",
"addons/ai/Scripts/Game/ERR/ERR_NativePatrolHQProbe.c": "4c04aa3e1b6b000747da8e2a919a6501107880fd041134c019f516665bb6f758",
"addons/ai/Scripts/Game/ERR/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
"addons/ai/Scripts/Game/ERR/ERR_SupportScenario.c": "71757018ec9716c4dc24f62a292a214919d3fd5daed3c16e03e56abd208e9f03",
"addons/ai/addon.gproj": "5f559db8f526700db11e6ae763f5245f19b7006fc68c56e4c09fb6f940bdf2a1",
"addons/ai/resourceDatabase.rdb": "129c2d601531447ffd1864982af3f9fec03ed64db23623d44e29115c0c1998c2",
"addons/chat/Missions/ERR_Everon.conf": "76f3ac0d21b585654beac7ddd68e3c8cbdd66dbfe909b17b04838fa813a7c29b",
"addons/chat/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
"addons/chat/Scripts/Game/ERR/ERR_AdminCommands.c": "d7b4ed95fc32767911936cb0fcc60763233f2c31afd34a6a0fa998b39cec9f5c",
"addons/chat/Scripts/Game/ERR/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
"addons/chat/Scripts/Game/ERR/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
"addons/chat/Scripts/Game/ERR/ERR_NativeSmoke.c": "0fe7825e6c2feea1bac766a5d8c904124f577aea3ff07d21b1d440c89d3a47b7",
"addons/chat/Scripts/Game/ERRChat/ERR_OrdinaryScenarioLaunchChat.c": "dda715c9691d366e35fa2ad5e390dee1971651f137a5a9f9aeb23dcbe53ec87e",
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
"addons/chat/resourceDatabase.rdb": "d9a737a8d09f9fced6b1e7fe108e477c0fc9877ad044f3c5be0aaa7c60b0056e",
"addons/core/Configs/ERR/EveronSites.conf": "ade92cc8d2b14a84ac378bbbb52608b351dca65d359dd7a315d64a145fa4b46f",
"addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
"addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
"addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
"addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
"addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
"addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
"addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
"addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
"addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
"addons/core/Missions/ERR_Everon_Base.conf": "1e6a0e9a756d15495201f71121626890f01efe6b00154c561672d4ec157960bd",
"addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
"addons/core/Prefabs/ERR/Extraction.et": "1aa286ef253c5410f09fa641e4be91a7be8ec834487a7fbb74cfb45cab60ee1e",
"addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
"addons/core/Prefabs/ERR/FactionManager.et": "425f916b890019c537f6b2f72b1af9e7be54b0a476320da969e1f313a7ac5ea5",
"addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
"addons/core/Prefabs/ERR/FieldCover.et": "20f8095e69dbfe3db74ff19078e528ea75405362b335e03560ccd61f8df2e7f3",
"addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
"addons/core/Prefabs/ERR/GameMode.et": "385c97a5b8067091d92aa60c2d4fcf02002cf606b95523866ead65c96b8c0029",
"addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
"addons/core/Prefabs/ERR/ObjectiveDocument.et": "2e72270bf186654af12d2c3ff9bf940690b03fb17fca44f873c1fde5d11384c0",
"addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
"addons/core/Prefabs/ERR/Patrol.et": "c5685a8bc311cc5563fb3334beec9408d3d7a1069152fddeeb7df4f1b7f9e6ce",
"addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
"addons/core/Prefabs/ERR/Prison.et": "1503db1441d8cd7a4f0b45c27ba9623b9fa39f0f81016e180bd2aa1379e1f42a",
"addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
"addons/core/Prefabs/ERR/PrisonDoor.et": "fc66be9d36f1f01084de59f1b0a1e8817f9e46547ead33d4fafaac0107446c40",
"addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
"addons/core/Prefabs/ERR/PrisonWall.et": "8009d19365ae72a4749d7ad4fa04662575b06c65c6bf06507d380d57258b5eed",
"addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
"addons/core/Prefabs/ERR/Prisoner.et": "198b5badabb12f218f86df7eb4dc268fd830769dc3de7eef6362cfaee4d6fc8d",
"addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
"addons/core/Prefabs/ERR/Radio.et": "b4b5cfe125b39019855816c9a1c508ca4d65d435b5546fdaa6c1fa3c8c9b1165",
"addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
"addons/core/Prefabs/ERR/SpectatorCamera.et": "b5b87d5b7b707f3745741aebe7c923067c8a74f8fbb2a4711834bab03bb5a812",
"addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
"addons/core/Prefabs/ERR/SupplyCache.et": "bccf7afbaae97cfcdd78dd6dbbf4be5b2c045d348f50fe4581962e556c0044d7",
"addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
"addons/core/Prefabs/ERR/SupplySite.et": "dc5decce5cabf39b6116e8794ec3960cb1e35761854fdbe69740da118787ded4",
"addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
"addons/core/Scripts/Game/ERR/ERR_Actions.c": "adf93245e6d78c59b9839599d157a0d2b2b93ea93b3d1ae52e2904dd6c288266",
"addons/core/Scripts/Game/ERR/ERR_Actors.c": "b3c5aabb05f7cf35167bc09b5db51a4ffd89a46658805d6eedbfb80eee30273d",
"addons/core/Scripts/Game/ERR/ERR_AdminService.c": "9985747d5ddaeb91bf27937836a6c369f8dcb353263b77a49212ec28c10ba4eb",
"addons/core/Scripts/Game/ERR/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c": "df787bc40099512656e622c6c511d18caea2ff7a88d2c113e0d6940a551ad566",
"addons/core/Scripts/Game/ERR/ERR_DiscoveryMap.c": "80fda5976c3d7a74ee3a481a0d5f365d5e59553046ebe84d0c84117829a32aaf",
"addons/core/Scripts/Game/ERR/ERR_DiscoveryService.c": "65cc0c23da131f986c3c90a8e4d294522e1d0681bec709b618daecb6e0d393c0",
"addons/core/Scripts/Game/ERR/ERR_DocumentComponent.c": "17bb76b80ebd3357e46d553c44674f602c7bd6901c92aec53ac8214194aa4ff2",
"addons/core/Scripts/Game/ERR/ERR_EnvironmentService.c": "867e9f47adfb7a9819a8b58498688ff86127282cb89cf2529ae81f73e529e1c5",
"addons/core/Scripts/Game/ERR/ERR_EscapeGameOverScreenInfo.c": "b1e1afb7795cb77c0bad94c85abf705b26b9dc2a9400905d80eafd56bdd009d3",
"addons/core/Scripts/Game/ERR/ERR_ExtractionPlacement.c": "c30222ca25cc0e91dec4077e6b82b37a9edafcf2cbebd0be5b6bd8656b53adfe",
"addons/core/Scripts/Game/ERR/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "043ac9ab7f3163f3285038ed008be782030714607d8e59e25593cfe95dd023b2",
"addons/core/Scripts/Game/ERR/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
"addons/core/Scripts/Game/ERR/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
"addons/core/Scripts/Game/ERR/ERR_LoadCasualtyAction.c": "5d868fb065a1a0fea7d5abfc81d1d8be96823815535f2ffd0dc4ff60d8eae794",
"addons/core/Scripts/Game/ERR/ERR_LocalAdmission.c": "b0e824c6880cbf9b1f368dc7ada9907bde78b22b948d419b6c861323f32258be",
"addons/core/Scripts/Game/ERR/ERR_Location.c": "d2035f56ded35743312ec6ca91a67f8623a466c91255e1893c570edf0954ff24",
"addons/core/Scripts/Game/ERR/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
"addons/core/Scripts/Game/ERR/ERR_NativeAdminSettingsProbe.c": "6a4df33a2b0e6b6aeed944c6895961e658d4f0db9aed9b8433a43a451fa35cae",
"addons/core/Scripts/Game/ERR/ERR_NativeBaseSmoke.c": "84e0a2d73bc12160cd0a95138085eb7647fa26b2326f790a95cb53748009fdd3",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
"addons/core/Scripts/Game/ERR/ERR_NativeContractsProbe.c": "d1556df885171cf967e96eef5d8981a2e9ee4e3938b7d32fdd0426f647bbabc0",
"addons/core/Scripts/Game/ERR/ERR_NativeDefinitionProbe.c": "c07048341396443ddf5307e340e2087254d65f0bddf8f7d93e6b6bd7f03ca360",
"addons/core/Scripts/Game/ERR/ERR_NativeEnvironmentProbe.c": "8b1d110717aa5f07bfb8fe633847eab519109e3a8a4100970a487be05c053418",
"addons/core/Scripts/Game/ERR/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
"addons/core/Scripts/Game/ERR/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
"addons/core/Scripts/Game/ERR/ERR_NativeFactionCatalogProbe.c": "ee11486cf77da9070506ccc0cfd6e94240c5387c8be455bf864934a8fef65f78",
"addons/core/Scripts/Game/ERR/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
"addons/core/Scripts/Game/ERR/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
"addons/core/Scripts/Game/ERR/ERR_NativeMedicalProbe.c": "43fa51ffbcf9dd0cd8e905a1135bcf0756651da3af34677f3c92e7d264ed70b6",
"addons/core/Scripts/Game/ERR/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
"addons/core/Scripts/Game/ERR/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
"addons/core/Scripts/Game/ERR/ERR_NativePatrolProbe.c": "02bd9fdf5454db7dd4c82240efe0d947bf8d6488ace42809c3aef6505cb6266d",
"addons/core/Scripts/Game/ERR/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
"addons/core/Scripts/Game/ERR/ERR_NativeRadioDefenceProbe.c": "cad54f0b43cefd72df74697dfc7e93725ff0acac6d311e963ce4f817428c272c",
"addons/core/Scripts/Game/ERR/ERR_NativeRecoveryProbe.c": "4de6868cd3e76afb80cf0ae5dac1e35d2c417838f640c2f18aa3343217eea2f2",
"addons/core/Scripts/Game/ERR/ERR_NativeResultProbe.c": "b9a117eef2d5f65fbd792041a2b3e59e38e201bda8e0df8c503e1a1242cfc415",
"addons/core/Scripts/Game/ERR/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
"addons/core/Scripts/Game/ERR/ERR_NativeStationTeardownDiagnostic.c": "a363c2383e66311415fd29124f26f3b0c6cb866648d86673afac29fca22a994a",
"addons/core/Scripts/Game/ERR/ERR_NativeTimeProbe.c": "c93d049785971e51246fcc07cf24804270a752a655505f2c38e48c80df5255ae",
"addons/core/Scripts/Game/ERR/ERR_NativeTransportProbe.c": "63ec0c5ce698114daa6314b2a6e3c3e98e76094117c477f9d0d072260686d193",
"addons/core/Scripts/Game/ERR/ERR_NativeTransportSurvey.c": "3e94493bf54d15be2bceb106ad18873e14e6755af09c05f07db7fb26fb7adff5",
"addons/core/Scripts/Game/ERR/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
"addons/core/Scripts/Game/ERR/ERR_ObjectiveText.c": "815fa44350798229784efffe0d4ec16d3382dd62df149215e49d527cc2961553",
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
"addons/core/Scripts/Game/ERR/ERR_OrdinaryScenarioLaunch.c": "e2803ff9198e6213bfcbaefad64a35ae3ffe06846c410cf6da6de7653adbf28d",
"addons/core/Scripts/Game/ERR/ERR_PlayerAdminCommands.c": "a084d7dc097dfcde3d6cd9c2e326b9e2f8f2a519f77b30c4f56ab7a1429aa721",
"addons/core/Scripts/Game/ERR/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
"addons/core/Scripts/Game/ERR/ERR_PlayerGuide.c": "2c9c365b88651f8b12618443638bf52c04e497221592bd483c33447e30468f36",
"addons/core/Scripts/Game/ERR/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
"addons/core/Scripts/Game/ERR/ERR_RadioDefenceService.c": "5d347cf1a3b021074d560aad8db774828b797e685b63ddff3d28f55781e33ea8",
"addons/core/Scripts/Game/ERR/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
"addons/core/Scripts/Game/ERR/ERR_RecoveryService.c": "ba9ffb93679012c20a665636ef6b201cbe7d8d14fdf53e8cd3eb12ac7248943f",
"addons/core/Scripts/Game/ERR/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
"addons/core/Scripts/Game/ERR/ERR_ScenarioComponent.c": "abba03af68323d5715ba1e2497fc66f3c706e6a6a983c3a386228abdfddeec89",
"addons/core/Scripts/Game/ERR/ERR_Settings.c": "b9390548936b386e0211d487c1b76b65410fdd2e339cd8ecd9585ef4f4ffed31",
"addons/core/Scripts/Game/ERR/ERR_SiteDefinition.c": "b422feeaca90084ea2bee5cde94dc9c6fcae542749b55d95f7226f922a6a68ac",
"addons/core/Scripts/Game/ERR/ERR_SiteDiscoveryRules.c": "50f7b3ff4f32bde37ce5ae2be7f598fc4dd8cc08f45914f6e3260d31c84baef2",
"addons/core/Scripts/Game/ERR/ERR_SiteService.c": "6bc9a0b5aed326822807f05e17459d0fc2da10b709e8168972b4e40fd09f87cb",
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "bbbf35110259cacdac63779604ce22149d1a2198ec4c4cf43f7f3bf57e3241e8",
"addons/core/Scripts/Game/ERR/ERR_SpawnPlacement.c": "55323dcb330c23d49dc8fa3fde86a3ae3958c0b6563d6c3cd0960da88333f93d",
"addons/core/Scripts/Game/ERR/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
"addons/core/Scripts/Game/ERR/ERR_TimeService.c": "d9f481b7da01e08d2c982a948c18ba6bde76889d7cc9d26d510708f4ba479453",
"addons/core/Scripts/GameLib/ERR/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
"addons/core/Scripts/WorkbenchGame/ERR/ERR_ValidateBaseWorldPlugin.c": "7f44aa64ea7b4f8b3640a37a4b781c43bf6adb80e4a3a702d9491131698056f6",
"addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
"addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
"addons/core/Worlds/ERR_Everon_Layers/default.layer": "17105538007199bfc419aa04a64debaf2da0a7b77a1dc3ba983e92bf747c862e",
"addons/core/addon.gproj": "231274e6b62302f32c65f9ff31de2ce8a9e51e1c8d12c87deeec82ae1f40de46",
"addons/core/resourceDatabase.rdb": "5765206693e176009ad2d37e0d46141ff57fec2348ea6331ed9511433eb001cb",
"addons/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
"addons/intel/resourceDatabase.rdb": "062996b9102e99d19eb680bed04880b0e087d9f8789681c0f3ff8ab6772339ba",
"addons/map/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
"addons/map/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
"addons/map/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
"addons/map/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
"addons/map/Scripts/Game/ERR/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
"addons/map/Scripts/Game/ERRMap/ERRM_SharedMapComponent.c": "fc1a0c7df4fc96da446d7542a45a10fbec1eda1e543ba2f0581cb772277a47c5",
"addons/map/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "49a2da4181b94d42174f58c7f9b6bf2207116c99427d61ff1c212092ac7db4d2",
"addons/map/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
"addons/map/addon.gproj": "1b371e5e01ea9fa46e76570fecb8aaa3a9298e34cba7ccca8a6bdb5ca86eb46a",
"addons/map/resourceDatabase.rdb": "fe2d3eea469f3a69dcdb8567a7bb8119dcc03f940b423ad0babfc3b84e5cb0da",
"docs/acceptance.json": "283f08dc1658d214d3551d8b22f3a1d179fbb95f9d85cfbe63015adffc3b365d",
"docs/addons.json": "be6097ca5fb6ccb8c17bf4c05849e3e75225473162cdffef18a1cad13d056186",
"docs/admin-discovery-setting.md": "a140f09cd1f27635824a9fa27e88e99259fc0030ff3228dd1376e2e949edbc1c",
"docs/architecture.md": "6d7b52d5456b8fcd396421a7d8ed04be01c9111dabf38fa3e42b5db5fe4dce72",
"docs/base-gameplay-gaps.md": "8fb9ce4bf3d36507fdcd03af9681657c473bdf1f1d188380e7e4a83d47b10625",
"docs/base-replacement.md": "e99b648932b784e2993d086d6f56176fda5d853f53a4363cbf4754774cd8afec",
"docs/casualty-ground-source-sha256.json": "90ffa7d0c61e3823922ca9d4773e3d12fd5e9a1760a35c3b29fd12a53642f83a",
"docs/casualty-ground-support.md": "bf5bdf19f9dfa0fb83dfdb9a9933e5cf6a63be3918f74953759a639f85f121e4",
"docs/casualty-incapacitation.md": "2811fa294de0348fbdf8e78b0c66bc31a59dd8f1e43fe16af8da87cb7e789820",
"docs/casualty-loading.md": "9970b46ae4b9d0247e6bfad8378bba33c237f16cb49a4f53da49706291872b18",
"docs/casualty-remove-source-sha256.json": "4799a5843315fe5b5b2e933e8068a8b4bae6d924a49438eccb7f68ffc8e12be9",
"docs/configuration.md": "654657c3c6a515d101e4f43dba74a2146358a8ead56aa5444cac4aec48177bf5",
"docs/current-status.md": "b1003d1b7c0167304b694b50e31b851cdf763f986885c593a3426f369ae2dfa9",
"docs/dependency-audit.json": "d5e6cbcdc59c0a25e5748c590d6a195da9c97e8296119e07185f4c360bdfc4ae",
"docs/environment-restart-fixture.md": "1c1bd3872a67c5a59c12c1293d075d52fe0b563fcd5e9e10a1ce1850c7efcea9",
"docs/environment.md": "eff60684482ca8332e6ac4909850b6acd1048a5518ac70ae121dd16afb1a4409",
"docs/extraction.md": "215c96cbc004b3817a70ee40f30b181a72e78123e69e16a3585ed4d8d566837d",
"docs/faction-catalog-source-hashes.json": "46060bf2bfe6c39517e3140acb004f9b129c26695a7ee890b4aae571b3f0da76",
"docs/finite-mortar-operations.md": "e3d230810bd42a02afc798639ea36f08fe0dcc45d73d14457cf37e7791d499f3",
"docs/ground-transport.md": "4ef0b23e1e752b807344100948e7d0f880448158292f96309dcec5de9583a1a0",
"docs/guard-cancellation-fix.md": "41f8bd169de714df4df4a61189d47a37f9be2f1b1554edc99c29d8a1fa4aaf19",
"docs/guard-cancellation-source-hashes.json": "a1bf169c021931cdcba835d52e420df44e5dd2ef351257f0be10f63c8727afd4",
"docs/guard-source-hashes.json": "874845def1458901d61adeb090a464bbee7c7b18816406ae3780ff48fe855266",
"docs/initial-extraction-placement-source-sha256.json": "a44a32cedc54a70f635bf5840e7b29d35850a2212fcf64b1fd36ca096f10fffa",
"docs/initial-extraction-placement.md": "643b50d231dd9ceb49b81fd8f061cd114a9618fd1ad5a6f88724c0199a5a304c",
"docs/initial-guard-readiness.md": "5f2b45f3744f1f0316f198225a34e25d93eb4795bb05d6cfded8de1f1a116c18",
"docs/inventory-identity.md": "02092960cf937b175c5a190b426b84e0383104fa71f324c8b3a0ceb4fbe01164",
"docs/local-singleplayer-admission.md": "79943060c67330bd0b386733306653b59b1cb92c0924ff3bb0ffd3b582bec70a",
"docs/medical-kit-teardown-ownership.md": "2116a4062425f6fba029142ea0239264d313ec52f69ec7f88ee7b250a90814bf",
"docs/migration-provenance.json": "3f0ab1e9d1314265a7cdea3535a9e81af441c1b7a5c9c925e84aa824a1730663",
"docs/migration.md": "42514af2fbef0663d05f3353a26f3b2fcd4f7359634652d23fda53a8e7bfcd0f",
"docs/mission-faction-catalogs.md": "2ce3e49404d103a4c372ab0386de3bcf831bee87d95b1092372345a3d32ef8d2",
"docs/mission-time.md": "29d9a18c7acef0587764becbd04c2c63684644a05c7b3b2fe77defe1881ae7a0",
"docs/mortar-transactions-source-sha256.json": "dabad1cbc6eb3dd6f66b3e9ece574edcabff94adceeb2494b1adb2147608dbc0",
"docs/native-casualty-remove.md": "d55f54fba75e6cd1b9c30b489db17d58aa708afed792d1eafcf33d6d43c55e76",
"docs/native-errors.md": "f0cbc674803f5254db0c823bce2df437cad121756e19f6c658087d5d2fddb349",
"docs/native-followup-snapshot.json": "6b686ee641830edbc223cfcee4d6a198fcfa36ce8531bb16855fa9cbe9f5cbd2",
"docs/native-guard-cancellation.md": "880b545b8451a86f16ef47e0a378d081c8fecb1175bf9a8a122bf853ff9b816c",
"docs/native-initial-snapshot.json": "1ba571aa6da7c72d3db3eaaac54f5399820603ac33d7b21b87946eee3aa4eaf3",
"docs/native-medical-fixture.md": "3c915a74afbcac1dfa45f0c1e9d8d4801f33704cac9ce1b66355121805ecfbb1",
"docs/native-mortar-firing.md": "5fd4a5a4059ea6f8a3fa353b16c8f507316689daa60a883387c20114c4c16892",
"docs/objective-widget-lifecycle.md": "3ec0ee8c74b2a3117356477a16125a077dfbf010050e53280a00769b710958a0",
"docs/ordinary-diagnostic-splash.md": "6e07a87a03df81dd5c9d6c0f9602b26e08ec7fd7cf941b91f2b8007bd9d33e6a",
"docs/ordinary-game-startup.md": "6a95a55aa5fbccbe9a54fd7c695929d392f30bf2ce0c9f509304cfc4b627e14e",
"docs/ordinary-identity-diagnostics.md": "6d5017ff1bf27a276208cc42d567ab2c9f0e8936bf7dca3156c649f67eca359b",
"docs/ordinary-launch-callback-fix.md": "b74b8d0d011f25c367ea07b37e1a5ef488a2b378542ddca63ff9e981e649b874",
"docs/ordinary-splash-source-hashes.json": "b2e277e3487c2b790bce741527555bb74f6b9820b9e5626950ab709533d9fa97",
"docs/original-feature-coverage.json": "27cc7d2934abb3d307a4cfc0fb1f10ac53611bef64dcca99aa939f68c842e98a",
"docs/original-feature-coverage.md": "2807936a75db548342e4f89c01795395038270a6793aafe15c6069c82537c30a",
"docs/original-resource-inventory.json": "bc52a981c42f933134e637a027d08a0924abb19784782731590b7ef0b0e2e73f",
"docs/performance-comparison.md": "8065fae91ef0ef572b06f9aba079bd9f6ab96b25fa8c63e7a4a30b34f77765a0",
"docs/player-lifecycle.md": "903302c21da86668d6a3ff78a11d5eb2a5c36c30062f65a2039df717c195a140",
"docs/prisoner-loadout.md": "0b27f5fce4af457bea7133e461dbc37d8fa73fe126c8c3de90d723b358af389a",
"docs/radio-defence.md": "845078af4648e21781357b263916ce351e38489e4f49ebf17fb0bc75d7a859ff",
"docs/radio-document-loss.md": "44ce397e471b2fa5d8b773379f475e2c4cb93b33b936a76919e64e15251c2b9d",
"docs/radio-feedback.md": "3aaaecb318e2f737321bd08f9deb9323af153f2ae9ed196b55104c0616dd2be8",
"docs/recovery.md": "a91e170b0ea164f50db64acc1f19b78a6dce9392736f194a9192e85c68a71a88",
"docs/release-qualification.md": "7bdf42f51fe3a4c1d6187d0e6f5248ac9a68ce16873281909bd96e1cea6c406b",
"docs/runtime-testing.md": "2db2fc790785633e701e503e087a8a9de8633a11ed8f1b4f9f22972506005524",
"docs/site-authoring.md": "7a2e66e75ca3fdab43bd730f16e864c31909ab42fe060b00715caa13b8352ce7",
"docs/site-patrols.md": "5956f70a5ebea4167819a43c2a15f8b6d6460bc724b000f989d5ad5265d48d56",
"docs/validation.md": "48206348ef58afe52daf5dc8dca4aa65beaf00086aabfc995c808b5b0e8233fa",
"docs/vanilla-resources.json": "a18dbb7683641c439418091530219fd3d4de65b14e8a139577411c2a020a9903",
"tests/helicopter_availability_regression.py": "b8eabe0646467d6b55b7bc08c75121185410d3460c2c951f70737a5decbbfefe",
"tests/hq_network_regression.py": "3b077e1c527029d60432cbe2e0373c3a4a55ed4e80d6be59e639de8bc9411188",
"tests/mortar_salvo_regression.py": "6624f57ac28aabadd3ae2ba96b802910ffe739786d9aca0ad1caea68ad08eb5b",
"tests/policy_harness.py": "e861c30037b3e456f0c8ef1c02e9fe1417b601ffb15d2037974715008865e4be",
"tests/test_admin_setting_policy.py": "8d8ce49f4079d930c06bf23be410eb610e30082e3177a9f88bd6a0dfbf54189d",
"tests/test_casualty_ground_policy.py": "6b6fb5dccfef32eb46f7e5fee11d28acd3068c25837d2f1474491fd139be9316",
"tests/test_casualty_incapacitation.py": "fdeee4ae5b0e383c592ecbcd132b108ed6e92cb0e1f4767da02f95bfa33b7a4a",
"tests/test_casualty_loading_policy.py": "3a85d86dd1b19aa616fafb5d3a38f5374d5bb14d176844210150ef95df62033a",
"tests/test_casualty_remove_probe.py": "61578d8ca863d5e5be32dab2661fdd410e8441eaf1a9ae3b5123906eb3d57a68",
"tests/test_casualty_reservation_death.py": "dd5abb0ca2e7ec289f6933c406517515475d34ffeea95d732c329b42080773b7",
"tests/test_diagnostic_no_splash.py": "a9f54ced5864953c8031208d519c2dec9d604a70ad65bc738b51c6656a8aab22",
"tests/test_environment_policy.py": "4f844728d47ab3ad66c8a06f37833e0325f00bd04c0803d7dcf0eed14d8935c3",
"tests/test_environment_restart_runner.py": "05bc09bc45db70ba4a635b65b0a96aa38437ba50c98640b47ed8d0683c3a5f71",
"tests/test_extraction_placement_policy.py": "4cef86ff87338bc2e0bf66683c78050f3ba49d940d0c221a89333f4cb61a2442",
"tests/test_faction_catalog_scope.py": "c8fab92575f2621f47ed8685243338aa9ea717bb809c2ef9e8e0884af9df263b",
"tests/test_guard_cancellation_policy.py": "4a0671c62a5d875c0839d7cd9bdb0703cc28172ae6a3b483e041ec299b02efb1",
"tests/test_headless_game_runner.py": "29f045b65dbcb53f06359daa1ed7e981351517f9b08d0287da828eb1f8b4212a",
"tests/test_initial_guard_policy.py": "11354597457a240ec0427481ec0626cb952fbf06995a2955c24e81a5054edb5f",
"tests/test_inventory_enumeration_policy.py": "1a13ab9d7fdce46589a30ba005d65bada02a5a997f3fdb4dff025aec5514f802",
"tests/test_local_admission.py": "8ef122042a6c0c2258b1269e78606443546760ffdba6177c4f68f73769006e57",
"tests/test_mission_rules.py": "1561f50ea52a38227503ea3b5b2394a9303f82d9cea00268fbbe8fe83deb4b5b",
"tests/test_mortar_transactions.py": "3a17d444c1083336b52cb329fabaa1b9de7105cbe048e12b2d430600cc5bbcd1",
"tests/test_native_mortar_probe.py": "327f4c5ac1be24397c6c88c6b77d8889ae84d3b66c26caaeb400c1b2f373de5c",
"tests/test_performance_comparison.py": "5f932de9e9898acdd379f26c777a35c884269522dbf8c41991a7a25bf61c369a",
"tests/test_player_admission_policy.py": "9298c7f5f4b1da466ed044326e87f1b3ed6c7dc6fc65e8915ec08086fbc501e3",
"tests/test_prison_placement_policy.py": "269d8875e4a634bb0049acea644795ce6e58f335363d8e86ae1dae934d2ae28e",
"tests/test_radio_defence_policy.py": "9fd3c348d69c8c4e61c1135bb7e5df1b2b0ef07a2a5ad4faff1611d7b8e98097",
"tests/test_radio_feedback_policy.py": "d91c39d8291a16cfa5bb5fc5c7365a7421a7ce9f855a0b0250b76c2cb7cd1369",
"tests/test_recovery_policy.py": "e50879d0e2728f8ede3b67015d05bad5e34590dfdf315575b799adab1e23e186",
"tests/test_release_check.py": "8b6e755ed922ad129ba01c228989610a31f3a79841dc7cdddd4ddbd0e510971b",
"tests/test_settings_migration.py": "59fe9cd5f4564a6747a9a00fa422453830c6f94f6f1ba785d0592ef6feefe158",
"tests/test_site_discovery_policy.py": "79ccc06b74c05210428d602b4e22de1579523b163d5ab9ed2d52a29bed484896",
"tests/test_time_policy.py": "32c468c0a8852b7dfb873a93da80295434530131629eaca365a9c4aa9398c63a",
"tools/archive_native.py": "a302bd080275b72fbc47fa8108a98fb2689a377cbeb3cfe6e73596726bdab0bb",
"tools/check.py": "7460a22cf17fc9562fce73862c1b0791c830f2a8f25878626457618801599702",
"tools/compare_performance.py": "568acfee2525b8924f3e7a39784e8641f76d63bb3703dcce8251ab9ac9bb1854",
"tools/desktop/kwin-right-monitor.js": "8f0cf9ad290edf02e5f623cf1b0e36e2b266153ff81a022233c4cf67818b9499",
"tools/headless_game.py": "18ea1259e7f35121a7628edddecf5683ad49a1199f90f45ecdd7adbd120ca589",
"tools/headless_workbench.py": "7599cca63d7cad61201d7597ccb6776e3f8c681d1d7566b8d8261b35e3d8de69",
"tools/import_settings.py": "d9c250b52b6d29be3a80c3404f048b65a0b9b99e93b5213d5ce2be7d90a37324",
"tools/native_command.py": "4828826aa70b5ac31ab77157e658a8a3998de2829cdf782b8eee5b8c566d0385",
"tools/native_provenance.py": "d4777f1f6ffed6993f7009ee2af41b100e8e0138d60ebfdcc5404ff2128f8e2a",
"tools/native_report.py": "bb75ef5fe551f45776d441f15a49ccad4daf19abca505187f9b2d30102538658",
"tools/reference_guard.py": "545b67111927d73bf2020f291528ea6f2f687a994b3e37bf567f239c32c8cd78",
"tools/release_check.py": "65df1bff33638a583905ba5f6c583a095b9f7e38186b6f29d70b72a61525589e",
"tools/source_manifest.py": "c1a985348bad16f3b5b69ef7e545b6341eca298d8ae08111b8340b31535cc199"
}
@@ -0,0 +1,279 @@
{
".gitattributes": "86cd7c797b8cac2699f5959add72303d5474f34fb0d141c36e6d8d095f7bc718",
".gitignore": "1647a8de89a13712bdb3678396c3d09b268e90e99b17bd56a1462eef7efd00d1",
"README.md": "557ecb725cb83911cba20c285624bc2f7cd527932407f87844f824e12821524d",
"addons/ai/Prefabs/ERR/MortarCrew.et": "05d3e7353ff9fe5523218a1487b31b7b742b0be8adbcb060c7099978cf008bce",
"addons/ai/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
"addons/ai/Scripts/Game/ERR/ERR_HQ.c": "ceafd6740ed277748744ce56ac0f0bb3a8521fcc060dafb2cdb99896aedf405a",
"addons/ai/Scripts/Game/ERR/ERR_HQJournal.c": "b3e402cfe92d415f37f666045afb062e6e11670ba03a0ca6f2d9fd4fc3520ac1",
"addons/ai/Scripts/Game/ERR/ERR_HQNetwork.c": "92ff2caca52e94c2cc9642dfc8509ce6e9349b257012bade8650bace9231128c",
"addons/ai/Scripts/Game/ERR/ERR_HQObservation.c": "36c978ec5f052213ac1236e1398d85063efbfd7ef60fe04f1fc11447fefe1d68",
"addons/ai/Scripts/Game/ERR/ERR_HQReport.c": "c4d16ccb571db4d9444c0a8d2be7318845d25ff90238b6d304e96a9ea19f1a08",
"addons/ai/Scripts/Game/ERR/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
"addons/ai/Scripts/Game/ERR/ERR_MortarBattery.c": "20a5b1975c2b185afd1b9b476f19730bae24064fab4d0e6538fc44bc49818b21",
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "b843484cd73340a6f865f06ce16b5405b26b9d460a89e8598234c6f27332890b",
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
"addons/ai/Scripts/Game/ERR/ERR_MortarReadiness.c": "1a7282d9bd53dcd115d53c9b460ca62d3218931a74635cc516eac1a13b7d9347",
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
"addons/ai/Scripts/Game/ERR/ERR_MortarSupplyTransfer.c": "34f7eaa01dc68e97aae8c1177b7f8fd6c15d5a41c6dc86de377f00b3613a8e77",
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "60b05d729ee961196b3e3d27bb7942d7aacdf1e42a38f7d63ec2499eea3ed2eb",
"addons/ai/Scripts/Game/ERR/ERR_NativeMortarFiringProbe.c": "d66e57ada46678eb0a6dfa6ff818b656f6132c4eed28881abafafa1e44f8cd2c",
"addons/ai/Scripts/Game/ERR/ERR_NativePatrolHQProbe.c": "4c04aa3e1b6b000747da8e2a919a6501107880fd041134c019f516665bb6f758",
"addons/ai/Scripts/Game/ERR/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
"addons/ai/Scripts/Game/ERR/ERR_SupportScenario.c": "71757018ec9716c4dc24f62a292a214919d3fd5daed3c16e03e56abd208e9f03",
"addons/ai/addon.gproj": "5f559db8f526700db11e6ae763f5245f19b7006fc68c56e4c09fb6f940bdf2a1",
"addons/ai/resourceDatabase.rdb": "129c2d601531447ffd1864982af3f9fec03ed64db23623d44e29115c0c1998c2",
"addons/chat/Missions/ERR_Everon.conf": "76f3ac0d21b585654beac7ddd68e3c8cbdd66dbfe909b17b04838fa813a7c29b",
"addons/chat/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
"addons/chat/Scripts/Game/ERR/ERR_AdminCommands.c": "d7b4ed95fc32767911936cb0fcc60763233f2c31afd34a6a0fa998b39cec9f5c",
"addons/chat/Scripts/Game/ERR/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
"addons/chat/Scripts/Game/ERR/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
"addons/chat/Scripts/Game/ERR/ERR_NativeSmoke.c": "0fe7825e6c2feea1bac766a5d8c904124f577aea3ff07d21b1d440c89d3a47b7",
"addons/chat/Scripts/Game/ERRChat/ERR_OrdinaryScenarioLaunchChat.c": "dda715c9691d366e35fa2ad5e390dee1971651f137a5a9f9aeb23dcbe53ec87e",
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
"addons/chat/resourceDatabase.rdb": "d9a737a8d09f9fced6b1e7fe108e477c0fc9877ad044f3c5be0aaa7c60b0056e",
"addons/core/Configs/ERR/EveronSites.conf": "ade92cc8d2b14a84ac378bbbb52608b351dca65d359dd7a315d64a145fa4b46f",
"addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
"addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
"addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
"addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
"addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
"addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
"addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
"addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
"addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
"addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
"addons/core/Missions/ERR_Everon_Base.conf": "1e6a0e9a756d15495201f71121626890f01efe6b00154c561672d4ec157960bd",
"addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
"addons/core/Prefabs/ERR/Extraction.et": "1aa286ef253c5410f09fa641e4be91a7be8ec834487a7fbb74cfb45cab60ee1e",
"addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
"addons/core/Prefabs/ERR/FactionManager.et": "425f916b890019c537f6b2f72b1af9e7be54b0a476320da969e1f313a7ac5ea5",
"addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
"addons/core/Prefabs/ERR/FieldCover.et": "20f8095e69dbfe3db74ff19078e528ea75405362b335e03560ccd61f8df2e7f3",
"addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
"addons/core/Prefabs/ERR/GameMode.et": "385c97a5b8067091d92aa60c2d4fcf02002cf606b95523866ead65c96b8c0029",
"addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
"addons/core/Prefabs/ERR/ObjectiveDocument.et": "2e72270bf186654af12d2c3ff9bf940690b03fb17fca44f873c1fde5d11384c0",
"addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
"addons/core/Prefabs/ERR/Patrol.et": "c5685a8bc311cc5563fb3334beec9408d3d7a1069152fddeeb7df4f1b7f9e6ce",
"addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
"addons/core/Prefabs/ERR/Prison.et": "1503db1441d8cd7a4f0b45c27ba9623b9fa39f0f81016e180bd2aa1379e1f42a",
"addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
"addons/core/Prefabs/ERR/PrisonDoor.et": "fc66be9d36f1f01084de59f1b0a1e8817f9e46547ead33d4fafaac0107446c40",
"addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
"addons/core/Prefabs/ERR/PrisonWall.et": "8009d19365ae72a4749d7ad4fa04662575b06c65c6bf06507d380d57258b5eed",
"addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
"addons/core/Prefabs/ERR/Prisoner.et": "198b5badabb12f218f86df7eb4dc268fd830769dc3de7eef6362cfaee4d6fc8d",
"addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
"addons/core/Prefabs/ERR/Radio.et": "b4b5cfe125b39019855816c9a1c508ca4d65d435b5546fdaa6c1fa3c8c9b1165",
"addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
"addons/core/Prefabs/ERR/SpectatorCamera.et": "b5b87d5b7b707f3745741aebe7c923067c8a74f8fbb2a4711834bab03bb5a812",
"addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
"addons/core/Prefabs/ERR/SupplyCache.et": "bccf7afbaae97cfcdd78dd6dbbf4be5b2c045d348f50fe4581962e556c0044d7",
"addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
"addons/core/Prefabs/ERR/SupplySite.et": "dc5decce5cabf39b6116e8794ec3960cb1e35761854fdbe69740da118787ded4",
"addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
"addons/core/Scripts/Game/ERR/ERR_Actions.c": "adf93245e6d78c59b9839599d157a0d2b2b93ea93b3d1ae52e2904dd6c288266",
"addons/core/Scripts/Game/ERR/ERR_Actors.c": "b3c5aabb05f7cf35167bc09b5db51a4ffd89a46658805d6eedbfb80eee30273d",
"addons/core/Scripts/Game/ERR/ERR_AdminService.c": "9985747d5ddaeb91bf27937836a6c369f8dcb353263b77a49212ec28c10ba4eb",
"addons/core/Scripts/Game/ERR/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c": "df787bc40099512656e622c6c511d18caea2ff7a88d2c113e0d6940a551ad566",
"addons/core/Scripts/Game/ERR/ERR_DiscoveryMap.c": "80fda5976c3d7a74ee3a481a0d5f365d5e59553046ebe84d0c84117829a32aaf",
"addons/core/Scripts/Game/ERR/ERR_DiscoveryService.c": "65cc0c23da131f986c3c90a8e4d294522e1d0681bec709b618daecb6e0d393c0",
"addons/core/Scripts/Game/ERR/ERR_DocumentComponent.c": "17bb76b80ebd3357e46d553c44674f602c7bd6901c92aec53ac8214194aa4ff2",
"addons/core/Scripts/Game/ERR/ERR_EnvironmentService.c": "867e9f47adfb7a9819a8b58498688ff86127282cb89cf2529ae81f73e529e1c5",
"addons/core/Scripts/Game/ERR/ERR_EscapeGameOverScreenInfo.c": "b1e1afb7795cb77c0bad94c85abf705b26b9dc2a9400905d80eafd56bdd009d3",
"addons/core/Scripts/Game/ERR/ERR_ExtractionPlacement.c": "c30222ca25cc0e91dec4077e6b82b37a9edafcf2cbebd0be5b6bd8656b53adfe",
"addons/core/Scripts/Game/ERR/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "043ac9ab7f3163f3285038ed008be782030714607d8e59e25593cfe95dd023b2",
"addons/core/Scripts/Game/ERR/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
"addons/core/Scripts/Game/ERR/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
"addons/core/Scripts/Game/ERR/ERR_LoadCasualtyAction.c": "5d868fb065a1a0fea7d5abfc81d1d8be96823815535f2ffd0dc4ff60d8eae794",
"addons/core/Scripts/Game/ERR/ERR_LocalAdmission.c": "b0e824c6880cbf9b1f368dc7ada9907bde78b22b948d419b6c861323f32258be",
"addons/core/Scripts/Game/ERR/ERR_Location.c": "d2035f56ded35743312ec6ca91a67f8623a466c91255e1893c570edf0954ff24",
"addons/core/Scripts/Game/ERR/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
"addons/core/Scripts/Game/ERR/ERR_NativeAdminSettingsProbe.c": "6a4df33a2b0e6b6aeed944c6895961e658d4f0db9aed9b8433a43a451fa35cae",
"addons/core/Scripts/Game/ERR/ERR_NativeBaseSmoke.c": "84e0a2d73bc12160cd0a95138085eb7647fa26b2326f790a95cb53748009fdd3",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
"addons/core/Scripts/Game/ERR/ERR_NativeContractsProbe.c": "d1556df885171cf967e96eef5d8981a2e9ee4e3938b7d32fdd0426f647bbabc0",
"addons/core/Scripts/Game/ERR/ERR_NativeDefinitionProbe.c": "c07048341396443ddf5307e340e2087254d65f0bddf8f7d93e6b6bd7f03ca360",
"addons/core/Scripts/Game/ERR/ERR_NativeEnvironmentProbe.c": "8b1d110717aa5f07bfb8fe633847eab519109e3a8a4100970a487be05c053418",
"addons/core/Scripts/Game/ERR/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
"addons/core/Scripts/Game/ERR/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
"addons/core/Scripts/Game/ERR/ERR_NativeFactionCatalogProbe.c": "ee11486cf77da9070506ccc0cfd6e94240c5387c8be455bf864934a8fef65f78",
"addons/core/Scripts/Game/ERR/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
"addons/core/Scripts/Game/ERR/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
"addons/core/Scripts/Game/ERR/ERR_NativeMedicalProbe.c": "43fa51ffbcf9dd0cd8e905a1135bcf0756651da3af34677f3c92e7d264ed70b6",
"addons/core/Scripts/Game/ERR/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
"addons/core/Scripts/Game/ERR/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
"addons/core/Scripts/Game/ERR/ERR_NativePatrolProbe.c": "02bd9fdf5454db7dd4c82240efe0d947bf8d6488ace42809c3aef6505cb6266d",
"addons/core/Scripts/Game/ERR/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
"addons/core/Scripts/Game/ERR/ERR_NativeRadioDefenceProbe.c": "cad54f0b43cefd72df74697dfc7e93725ff0acac6d311e963ce4f817428c272c",
"addons/core/Scripts/Game/ERR/ERR_NativeRecoveryProbe.c": "4de6868cd3e76afb80cf0ae5dac1e35d2c417838f640c2f18aa3343217eea2f2",
"addons/core/Scripts/Game/ERR/ERR_NativeResultProbe.c": "b9a117eef2d5f65fbd792041a2b3e59e38e201bda8e0df8c503e1a1242cfc415",
"addons/core/Scripts/Game/ERR/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
"addons/core/Scripts/Game/ERR/ERR_NativeStationTeardownDiagnostic.c": "a363c2383e66311415fd29124f26f3b0c6cb866648d86673afac29fca22a994a",
"addons/core/Scripts/Game/ERR/ERR_NativeTimeProbe.c": "c93d049785971e51246fcc07cf24804270a752a655505f2c38e48c80df5255ae",
"addons/core/Scripts/Game/ERR/ERR_NativeTransportProbe.c": "63ec0c5ce698114daa6314b2a6e3c3e98e76094117c477f9d0d072260686d193",
"addons/core/Scripts/Game/ERR/ERR_NativeTransportSurvey.c": "3e94493bf54d15be2bceb106ad18873e14e6755af09c05f07db7fb26fb7adff5",
"addons/core/Scripts/Game/ERR/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
"addons/core/Scripts/Game/ERR/ERR_ObjectiveText.c": "815fa44350798229784efffe0d4ec16d3382dd62df149215e49d527cc2961553",
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
"addons/core/Scripts/Game/ERR/ERR_OrdinaryScenarioLaunch.c": "e2803ff9198e6213bfcbaefad64a35ae3ffe06846c410cf6da6de7653adbf28d",
"addons/core/Scripts/Game/ERR/ERR_PlayerAdminCommands.c": "a084d7dc097dfcde3d6cd9c2e326b9e2f8f2a519f77b30c4f56ab7a1429aa721",
"addons/core/Scripts/Game/ERR/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
"addons/core/Scripts/Game/ERR/ERR_PlayerGuide.c": "2c9c365b88651f8b12618443638bf52c04e497221592bd483c33447e30468f36",
"addons/core/Scripts/Game/ERR/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
"addons/core/Scripts/Game/ERR/ERR_RadioDefenceService.c": "5d347cf1a3b021074d560aad8db774828b797e685b63ddff3d28f55781e33ea8",
"addons/core/Scripts/Game/ERR/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
"addons/core/Scripts/Game/ERR/ERR_RecoveryService.c": "ba9ffb93679012c20a665636ef6b201cbe7d8d14fdf53e8cd3eb12ac7248943f",
"addons/core/Scripts/Game/ERR/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
"addons/core/Scripts/Game/ERR/ERR_ScenarioComponent.c": "abba03af68323d5715ba1e2497fc66f3c706e6a6a983c3a386228abdfddeec89",
"addons/core/Scripts/Game/ERR/ERR_Settings.c": "b9390548936b386e0211d487c1b76b65410fdd2e339cd8ecd9585ef4f4ffed31",
"addons/core/Scripts/Game/ERR/ERR_SiteDefinition.c": "b422feeaca90084ea2bee5cde94dc9c6fcae542749b55d95f7226f922a6a68ac",
"addons/core/Scripts/Game/ERR/ERR_SiteDiscoveryRules.c": "50f7b3ff4f32bde37ce5ae2be7f598fc4dd8cc08f45914f6e3260d31c84baef2",
"addons/core/Scripts/Game/ERR/ERR_SiteService.c": "6bc9a0b5aed326822807f05e17459d0fc2da10b709e8168972b4e40fd09f87cb",
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "bbbf35110259cacdac63779604ce22149d1a2198ec4c4cf43f7f3bf57e3241e8",
"addons/core/Scripts/Game/ERR/ERR_SpawnPlacement.c": "55323dcb330c23d49dc8fa3fde86a3ae3958c0b6563d6c3cd0960da88333f93d",
"addons/core/Scripts/Game/ERR/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
"addons/core/Scripts/Game/ERR/ERR_TimeService.c": "d9f481b7da01e08d2c982a948c18ba6bde76889d7cc9d26d510708f4ba479453",
"addons/core/Scripts/GameLib/ERR/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
"addons/core/Scripts/WorkbenchGame/ERR/ERR_ValidateBaseWorldPlugin.c": "7f44aa64ea7b4f8b3640a37a4b781c43bf6adb80e4a3a702d9491131698056f6",
"addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
"addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
"addons/core/Worlds/ERR_Everon_Layers/default.layer": "17105538007199bfc419aa04a64debaf2da0a7b77a1dc3ba983e92bf747c862e",
"addons/core/addon.gproj": "231274e6b62302f32c65f9ff31de2ce8a9e51e1c8d12c87deeec82ae1f40de46",
"addons/core/resourceDatabase.rdb": "5765206693e176009ad2d37e0d46141ff57fec2348ea6331ed9511433eb001cb",
"addons/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
"addons/intel/resourceDatabase.rdb": "062996b9102e99d19eb680bed04880b0e087d9f8789681c0f3ff8ab6772339ba",
"addons/map/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
"addons/map/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
"addons/map/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
"addons/map/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
"addons/map/Scripts/Game/ERR/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
"addons/map/Scripts/Game/ERRMap/ERRM_SharedMapComponent.c": "fc1a0c7df4fc96da446d7542a45a10fbec1eda1e543ba2f0581cb772277a47c5",
"addons/map/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "49a2da4181b94d42174f58c7f9b6bf2207116c99427d61ff1c212092ac7db4d2",
"addons/map/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
"addons/map/addon.gproj": "1b371e5e01ea9fa46e76570fecb8aaa3a9298e34cba7ccca8a6bdb5ca86eb46a",
"addons/map/resourceDatabase.rdb": "fe2d3eea469f3a69dcdb8567a7bb8119dcc03f940b423ad0babfc3b84e5cb0da",
"docs/acceptance.json": "283f08dc1658d214d3551d8b22f3a1d179fbb95f9d85cfbe63015adffc3b365d",
"docs/addons.json": "be6097ca5fb6ccb8c17bf4c05849e3e75225473162cdffef18a1cad13d056186",
"docs/admin-discovery-setting.md": "a140f09cd1f27635824a9fa27e88e99259fc0030ff3228dd1376e2e949edbc1c",
"docs/architecture.md": "6d7b52d5456b8fcd396421a7d8ed04be01c9111dabf38fa3e42b5db5fe4dce72",
"docs/base-gameplay-gaps.md": "8fb9ce4bf3d36507fdcd03af9681657c473bdf1f1d188380e7e4a83d47b10625",
"docs/base-replacement.md": "e99b648932b784e2993d086d6f56176fda5d853f53a4363cbf4754774cd8afec",
"docs/casualty-ground-source-sha256.json": "90ffa7d0c61e3823922ca9d4773e3d12fd5e9a1760a35c3b29fd12a53642f83a",
"docs/casualty-ground-support.md": "bf5bdf19f9dfa0fb83dfdb9a9933e5cf6a63be3918f74953759a639f85f121e4",
"docs/casualty-incapacitation.md": "2811fa294de0348fbdf8e78b0c66bc31a59dd8f1e43fe16af8da87cb7e789820",
"docs/casualty-loading.md": "9970b46ae4b9d0247e6bfad8378bba33c237f16cb49a4f53da49706291872b18",
"docs/casualty-remove-source-sha256.json": "4799a5843315fe5b5b2e933e8068a8b4bae6d924a49438eccb7f68ffc8e12be9",
"docs/configuration.md": "654657c3c6a515d101e4f43dba74a2146358a8ead56aa5444cac4aec48177bf5",
"docs/current-status.md": "b1003d1b7c0167304b694b50e31b851cdf763f986885c593a3426f369ae2dfa9",
"docs/dependency-audit.json": "d5e6cbcdc59c0a25e5748c590d6a195da9c97e8296119e07185f4c360bdfc4ae",
"docs/environment-restart-fixture.md": "1c1bd3872a67c5a59c12c1293d075d52fe0b563fcd5e9e10a1ce1850c7efcea9",
"docs/environment.md": "eff60684482ca8332e6ac4909850b6acd1048a5518ac70ae121dd16afb1a4409",
"docs/extraction.md": "215c96cbc004b3817a70ee40f30b181a72e78123e69e16a3585ed4d8d566837d",
"docs/faction-catalog-source-hashes.json": "46060bf2bfe6c39517e3140acb004f9b129c26695a7ee890b4aae571b3f0da76",
"docs/finite-mortar-operations.md": "e3d230810bd42a02afc798639ea36f08fe0dcc45d73d14457cf37e7791d499f3",
"docs/ground-transport.md": "4ef0b23e1e752b807344100948e7d0f880448158292f96309dcec5de9583a1a0",
"docs/guard-cancellation-fix.md": "41f8bd169de714df4df4a61189d47a37f9be2f1b1554edc99c29d8a1fa4aaf19",
"docs/guard-cancellation-source-hashes.json": "a1bf169c021931cdcba835d52e420df44e5dd2ef351257f0be10f63c8727afd4",
"docs/guard-source-hashes.json": "874845def1458901d61adeb090a464bbee7c7b18816406ae3780ff48fe855266",
"docs/initial-extraction-placement-source-sha256.json": "a44a32cedc54a70f635bf5840e7b29d35850a2212fcf64b1fd36ca096f10fffa",
"docs/initial-extraction-placement.md": "643b50d231dd9ceb49b81fd8f061cd114a9618fd1ad5a6f88724c0199a5a304c",
"docs/initial-guard-readiness.md": "5f2b45f3744f1f0316f198225a34e25d93eb4795bb05d6cfded8de1f1a116c18",
"docs/inventory-identity.md": "02092960cf937b175c5a190b426b84e0383104fa71f324c8b3a0ceb4fbe01164",
"docs/local-singleplayer-admission.md": "79943060c67330bd0b386733306653b59b1cb92c0924ff3bb0ffd3b582bec70a",
"docs/medical-kit-teardown-ownership.md": "2116a4062425f6fba029142ea0239264d313ec52f69ec7f88ee7b250a90814bf",
"docs/migration-provenance.json": "3f0ab1e9d1314265a7cdea3535a9e81af441c1b7a5c9c925e84aa824a1730663",
"docs/migration.md": "42514af2fbef0663d05f3353a26f3b2fcd4f7359634652d23fda53a8e7bfcd0f",
"docs/mission-faction-catalogs.md": "2ce3e49404d103a4c372ab0386de3bcf831bee87d95b1092372345a3d32ef8d2",
"docs/mission-time.md": "29d9a18c7acef0587764becbd04c2c63684644a05c7b3b2fe77defe1881ae7a0",
"docs/mortar-transactions-source-sha256.json": "dabad1cbc6eb3dd6f66b3e9ece574edcabff94adceeb2494b1adb2147608dbc0",
"docs/native-casualty-remove.md": "d55f54fba75e6cd1b9c30b489db17d58aa708afed792d1eafcf33d6d43c55e76",
"docs/native-errors.md": "f0cbc674803f5254db0c823bce2df437cad121756e19f6c658087d5d2fddb349",
"docs/native-followup-snapshot.json": "6b686ee641830edbc223cfcee4d6a198fcfa36ce8531bb16855fa9cbe9f5cbd2",
"docs/native-guard-cancellation.md": "880b545b8451a86f16ef47e0a378d081c8fecb1175bf9a8a122bf853ff9b816c",
"docs/native-initial-snapshot.json": "1ba571aa6da7c72d3db3eaaac54f5399820603ac33d7b21b87946eee3aa4eaf3",
"docs/native-medical-fixture.md": "3c915a74afbcac1dfa45f0c1e9d8d4801f33704cac9ce1b66355121805ecfbb1",
"docs/native-mortar-firing.md": "5fd4a5a4059ea6f8a3fa353b16c8f507316689daa60a883387c20114c4c16892",
"docs/objective-widget-lifecycle.md": "3ec0ee8c74b2a3117356477a16125a077dfbf010050e53280a00769b710958a0",
"docs/ordinary-diagnostic-splash.md": "6e07a87a03df81dd5c9d6c0f9602b26e08ec7fd7cf941b91f2b8007bd9d33e6a",
"docs/ordinary-game-startup.md": "6a95a55aa5fbccbe9a54fd7c695929d392f30bf2ce0c9f509304cfc4b627e14e",
"docs/ordinary-identity-diagnostics.md": "6d5017ff1bf27a276208cc42d567ab2c9f0e8936bf7dca3156c649f67eca359b",
"docs/ordinary-launch-callback-fix.md": "b74b8d0d011f25c367ea07b37e1a5ef488a2b378542ddca63ff9e981e649b874",
"docs/ordinary-splash-source-hashes.json": "b2e277e3487c2b790bce741527555bb74f6b9820b9e5626950ab709533d9fa97",
"docs/original-feature-coverage.json": "27cc7d2934abb3d307a4cfc0fb1f10ac53611bef64dcca99aa939f68c842e98a",
"docs/original-feature-coverage.md": "2807936a75db548342e4f89c01795395038270a6793aafe15c6069c82537c30a",
"docs/original-resource-inventory.json": "bc52a981c42f933134e637a027d08a0924abb19784782731590b7ef0b0e2e73f",
"docs/performance-comparison.md": "8065fae91ef0ef572b06f9aba079bd9f6ab96b25fa8c63e7a4a30b34f77765a0",
"docs/player-lifecycle.md": "903302c21da86668d6a3ff78a11d5eb2a5c36c30062f65a2039df717c195a140",
"docs/prisoner-loadout.md": "0b27f5fce4af457bea7133e461dbc37d8fa73fe126c8c3de90d723b358af389a",
"docs/radio-defence.md": "845078af4648e21781357b263916ce351e38489e4f49ebf17fb0bc75d7a859ff",
"docs/radio-document-loss.md": "44ce397e471b2fa5d8b773379f475e2c4cb93b33b936a76919e64e15251c2b9d",
"docs/radio-feedback.md": "3aaaecb318e2f737321bd08f9deb9323af153f2ae9ed196b55104c0616dd2be8",
"docs/recovery.md": "a91e170b0ea164f50db64acc1f19b78a6dce9392736f194a9192e85c68a71a88",
"docs/release-qualification.md": "7bdf42f51fe3a4c1d6187d0e6f5248ac9a68ce16873281909bd96e1cea6c406b",
"docs/runtime-testing.md": "2db2fc790785633e701e503e087a8a9de8633a11ed8f1b4f9f22972506005524",
"docs/site-authoring.md": "7a2e66e75ca3fdab43bd730f16e864c31909ab42fe060b00715caa13b8352ce7",
"docs/site-patrols.md": "5956f70a5ebea4167819a43c2a15f8b6d6460bc724b000f989d5ad5265d48d56",
"docs/validation.md": "48206348ef58afe52daf5dc8dca4aa65beaf00086aabfc995c808b5b0e8233fa",
"docs/vanilla-resources.json": "a18dbb7683641c439418091530219fd3d4de65b14e8a139577411c2a020a9903",
"tests/helicopter_availability_regression.py": "b8eabe0646467d6b55b7bc08c75121185410d3460c2c951f70737a5decbbfefe",
"tests/hq_network_regression.py": "3b077e1c527029d60432cbe2e0373c3a4a55ed4e80d6be59e639de8bc9411188",
"tests/mortar_salvo_regression.py": "6624f57ac28aabadd3ae2ba96b802910ffe739786d9aca0ad1caea68ad08eb5b",
"tests/policy_harness.py": "e861c30037b3e456f0c8ef1c02e9fe1417b601ffb15d2037974715008865e4be",
"tests/test_admin_setting_policy.py": "8d8ce49f4079d930c06bf23be410eb610e30082e3177a9f88bd6a0dfbf54189d",
"tests/test_casualty_ground_policy.py": "6b6fb5dccfef32eb46f7e5fee11d28acd3068c25837d2f1474491fd139be9316",
"tests/test_casualty_incapacitation.py": "fdeee4ae5b0e383c592ecbcd132b108ed6e92cb0e1f4767da02f95bfa33b7a4a",
"tests/test_casualty_loading_policy.py": "3a85d86dd1b19aa616fafb5d3a38f5374d5bb14d176844210150ef95df62033a",
"tests/test_casualty_remove_probe.py": "61578d8ca863d5e5be32dab2661fdd410e8441eaf1a9ae3b5123906eb3d57a68",
"tests/test_casualty_reservation_death.py": "dd5abb0ca2e7ec289f6933c406517515475d34ffeea95d732c329b42080773b7",
"tests/test_diagnostic_no_splash.py": "a9f54ced5864953c8031208d519c2dec9d604a70ad65bc738b51c6656a8aab22",
"tests/test_environment_policy.py": "4f844728d47ab3ad66c8a06f37833e0325f00bd04c0803d7dcf0eed14d8935c3",
"tests/test_environment_restart_runner.py": "05bc09bc45db70ba4a635b65b0a96aa38437ba50c98640b47ed8d0683c3a5f71",
"tests/test_extraction_placement_policy.py": "4cef86ff87338bc2e0bf66683c78050f3ba49d940d0c221a89333f4cb61a2442",
"tests/test_faction_catalog_scope.py": "c8fab92575f2621f47ed8685243338aa9ea717bb809c2ef9e8e0884af9df263b",
"tests/test_guard_cancellation_policy.py": "4a0671c62a5d875c0839d7cd9bdb0703cc28172ae6a3b483e041ec299b02efb1",
"tests/test_headless_game_runner.py": "29f045b65dbcb53f06359daa1ed7e981351517f9b08d0287da828eb1f8b4212a",
"tests/test_initial_guard_policy.py": "11354597457a240ec0427481ec0626cb952fbf06995a2955c24e81a5054edb5f",
"tests/test_inventory_enumeration_policy.py": "1a13ab9d7fdce46589a30ba005d65bada02a5a997f3fdb4dff025aec5514f802",
"tests/test_local_admission.py": "8ef122042a6c0c2258b1269e78606443546760ffdba6177c4f68f73769006e57",
"tests/test_mission_rules.py": "1561f50ea52a38227503ea3b5b2394a9303f82d9cea00268fbbe8fe83deb4b5b",
"tests/test_mortar_transactions.py": "3a17d444c1083336b52cb329fabaa1b9de7105cbe048e12b2d430600cc5bbcd1",
"tests/test_native_mortar_probe.py": "327f4c5ac1be24397c6c88c6b77d8889ae84d3b66c26caaeb400c1b2f373de5c",
"tests/test_performance_comparison.py": "5f932de9e9898acdd379f26c777a35c884269522dbf8c41991a7a25bf61c369a",
"tests/test_player_admission_policy.py": "9298c7f5f4b1da466ed044326e87f1b3ed6c7dc6fc65e8915ec08086fbc501e3",
"tests/test_prison_placement_policy.py": "269d8875e4a634bb0049acea644795ce6e58f335363d8e86ae1dae934d2ae28e",
"tests/test_radio_defence_policy.py": "9fd3c348d69c8c4e61c1135bb7e5df1b2b0ef07a2a5ad4faff1611d7b8e98097",
"tests/test_radio_feedback_policy.py": "d91c39d8291a16cfa5bb5fc5c7365a7421a7ce9f855a0b0250b76c2cb7cd1369",
"tests/test_recovery_policy.py": "e50879d0e2728f8ede3b67015d05bad5e34590dfdf315575b799adab1e23e186",
"tests/test_release_check.py": "8b6e755ed922ad129ba01c228989610a31f3a79841dc7cdddd4ddbd0e510971b",
"tests/test_settings_migration.py": "59fe9cd5f4564a6747a9a00fa422453830c6f94f6f1ba785d0592ef6feefe158",
"tests/test_site_discovery_policy.py": "79ccc06b74c05210428d602b4e22de1579523b163d5ab9ed2d52a29bed484896",
"tests/test_time_policy.py": "32c468c0a8852b7dfb873a93da80295434530131629eaca365a9c4aa9398c63a",
"tools/archive_native.py": "a302bd080275b72fbc47fa8108a98fb2689a377cbeb3cfe6e73596726bdab0bb",
"tools/check.py": "7460a22cf17fc9562fce73862c1b0791c830f2a8f25878626457618801599702",
"tools/compare_performance.py": "568acfee2525b8924f3e7a39784e8641f76d63bb3703dcce8251ab9ac9bb1854",
"tools/desktop/kwin-right-monitor.js": "8f0cf9ad290edf02e5f623cf1b0e36e2b266153ff81a022233c4cf67818b9499",
"tools/headless_game.py": "18ea1259e7f35121a7628edddecf5683ad49a1199f90f45ecdd7adbd120ca589",
"tools/headless_workbench.py": "7599cca63d7cad61201d7597ccb6776e3f8c681d1d7566b8d8261b35e3d8de69",
"tools/import_settings.py": "d9c250b52b6d29be3a80c3404f048b65a0b9b99e93b5213d5ce2be7d90a37324",
"tools/native_command.py": "4828826aa70b5ac31ab77157e658a8a3998de2829cdf782b8eee5b8c566d0385",
"tools/native_provenance.py": "d4777f1f6ffed6993f7009ee2af41b100e8e0138d60ebfdcc5404ff2128f8e2a",
"tools/native_report.py": "bb75ef5fe551f45776d441f15a49ccad4daf19abca505187f9b2d30102538658",
"tools/reference_guard.py": "545b67111927d73bf2020f291528ea6f2f687a994b3e37bf567f239c32c8cd78",
"tools/release_check.py": "65df1bff33638a583905ba5f6c583a095b9f7e38186b6f29d70b72a61525589e",
"tools/source_manifest.py": "c1a985348bad16f3b5b69ef7e545b6341eca298d8ae08111b8340b31535cc199"
}
@@ -0,0 +1,2 @@
# Preserve native evidence bytes, including engine CRLF line endings.
docs/evidence/** -text -whitespace
@@ -0,0 +1,7 @@
resourceDatabase.rdb*
*.pak
*.log
__pycache__/
.build/
.local/
profiles/
@@ -0,0 +1,32 @@
# Escapists Rereintroduced
An independently authored replacement for the abandoned Escapists base mission, initially targeting vanilla Everon and up to twelve players. This is a separate repository and **not a completed or release-ready replacement**. The base rewrite is the primary deliverable; companion migration supports it.
The current base supplies prison spawning, two independent scavenging/clue routes, finite medical and outpost stock, an optional ground vehicle, physical radio documents, named discovery markers, native objectives, a separate radio-defence service, capacity-checked helicopter extraction, identity-based partial results, early helicopter-loss defeat, saved mission time/speed, defeat/restart, identity-based lives and local spectator following. Authored site definitions and an injected vanilla faction/asset catalog own the initial physical population. Core provides administration and startup diagnostics; the optional AI, Intel, Chat and Map addons extend its interfaces. HQ coordinates enemy responses through physical radios and available forces.
See [current development status](docs/current-status.md) for verified checkpoints and the prioritized remaining work. Ordinary-game startup and ground-to-helicopter casualty loading have retained native failures; manual gameplay, real multiplayer, complete physical HQ support, measured FPS improvement and release qualification remain unfinished. The [original responsibility inventory](docs/original-feature-coverage.md) is a scope map, not proof that every original behavior has been replaced.
## Projects and scenarios
Five Workbench projects live in `addons/core`, `addons/ai`, `addons/intel`, `addons/chat` and `addons/map`:
- Open `addons/core/addon.gproj` for the independent base scenario, `{AD62322D5213C440}Missions/ERR_Everon_Base.conf`.
- Open `addons/chat/addon.gproj` for full companion integration, `{C1E20667DCE324ED}Missions/ERR_Everon.conf`.
Both use the newly authored Everon child world. The only external addon dependency is vanilla Arma Reforger. All required successor resources are inside this repository. Vanilla assets are referenced, not redistributed; original restricted Escapists code, compositions, UI and audio are not included.
See [player lifecycle](docs/player-lifecycle.md), [manual gameplay gaps](docs/base-gameplay-gaps.md), [release qualification](docs/release-qualification.md), [performance comparison tooling](docs/performance-comparison.md), [configuration and commands](docs/configuration.md), [site authoring](docs/site-authoring.md), [architecture](docs/architecture.md) and [migration priorities](docs/base-replacement.md).
## Validation
Run source/resource isolation and production-policy regressions with Python 3 and a C++17 compiler:
```sh
python3 tools/check.py
```
For bounded hidden, muted local native tests, see [runtime testing](docs/runtime-testing.md). Recorded Workbench checkpoints include Core-only and companion-loaded escape/restart, finite stock and document-loss recovery, twelve physical prisoner/seat fixtures, real medical treatment, local result/objective widgets, patrol movement and HQ preemption/resumption. Clean environment/restart evidence exists after narrowing the vanilla vehicle catalogs; it does not qualify subsequent source changes.
These scripted local fixtures manipulate positions and selected native states. They do not establish ordinary-game startup, manual escape/piloting, real remote reconnects, twelve connected players or improved FPS. [Current status](docs/current-status.md) separates those gaps from demonstrated development behavior. [Validation evidence](docs/validation.md) preserves exact source checkpoints and failed iterations; `docs/acceptance.json` keeps unverified release requirements pending.
No release package has been published.
@@ -0,0 +1,8 @@
SCR_AIGroup : "{8DE0C0830FE0C33D}Prefabs/Groups/OPFOR/Group_USSR_Base.et" {
m_aUnitPrefabSlots {
"{86E565387A634103}Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et"
"{86E565387A634103}Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et"
"{86E565387A634103}Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et"
"{612F43A4D5AE765F}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et"
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{B84C05941C4C81B8}Prefabs/ERR/MortarCrew.et"
Configurations {
EntityTemplateResourceClass PC {}
EntityTemplateResourceClass HEADLESS {}
}
}
@@ -0,0 +1,339 @@
class ERR_HQUnit
{
int Id;
SCR_AIGroup Group;
SCR_AIGroupUtilityComponent Utility;
IEntity Radio;
float NextReport;
ref ERR_HQRoute Uplink;
ref ERR_HQReport PendingReport;
ref ERR_HQRoute Downlink;
ref ERR_HQReport PendingOrder;
ref ERR_HQReport Assignment;
AIWaypoint Waypoint;
bool ReservedForSupport;
bool Eligible(ERR_GameMode mode)
{
if (ReservedForSupport || !Group || !Utility || Group.GetPlayerCount(true) > 0 || Group.IsSlave() || Group.GetFaction() != mode.EnemyFaction()) return false;
array<AIAgent> agents = {};
Group.GetAgents(agents);
bool survivor;
foreach (AIAgent agent : agents)
{
if (!agent || !ERR_Actors.CanFight(agent.GetControlledEntity())) continue;
survivor = true;
if (CompartmentAccessComponent.GetVehicleIn(agent.GetControlledEntity())) return false;
}
return survivor;
}
void Release()
{
if (Waypoint)
{
if (Group) Group.RemoveWaypoint(Waypoint);
SCR_EntityHelper.DeleteEntityAndChildren(Waypoint);
}
Waypoint = null;
Assignment = null;
PendingOrder = null;
Downlink = null;
}
}
class ERR_HQ : ERR_CommandService
{
protected ERR_GameMode m_Mode;
protected ref ERR_MortarSystem m_Mortars;
protected ref array<ref ERR_HQUnit> m_Units = {};
protected ref array<ref ERR_HQReport> m_Contacts = {};
protected ref ERR_HQNetwork m_Network = new ERR_HQNetwork();
protected ref ERR_HQJournal m_Journal = new ERR_HQJournal();
protected int m_NextId;
protected float m_NextNetwork;
protected float m_NextAssignment;
void ERR_HQ(ERR_GameMode mode) { m_Mode = mode; m_Mortars = new ERR_MortarSystem(this); }
static ERR_HQ Get()
{
ERR_GameMode mode = ERR_GameMode.Get();
if (!mode) return null;
return ERR_HQ.Cast(mode.Command());
}
static bool MissionActive()
{
ERR_GameMode mode = ERR_GameMode.Get();
return mode && mode.Active();
}
static void Event(string kind, string message, int messageId = 0)
{
ERR_HQ hq = Get();
if (hq) hq.Journal().Write(kind, message, messageId);
}
ERR_MortarSystem Mortars() { return m_Mortars; }
bool PrepareSupport() { return m_Mortars.Prepare(); }
void ReserveGroup(SCR_AIGroup group)
{
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != group) continue;
unit.Release();
unit.ReservedForSupport = true;
}
}
void PhysicalForces(out array<IEntity> entities)
{
entities.Clear();
foreach (ERR_HQUnit unit : m_Units)
{
if (!unit.Group) continue;
array<AIAgent> agents = {};
unit.Group.GetAgents(agents);
foreach (AIAgent agent : agents)
{
if (!agent || !agent.GetControlledEntity()) continue;
IEntity actor = agent.GetControlledEntity();
if (!entities.Contains(actor)) entities.Insert(actor);
IEntity vehicle = CompartmentAccessComponent.GetVehicleIn(actor);
if (vehicle && !entities.Contains(vehicle)) entities.Insert(vehicle);
}
}
m_Mortars.AppendGuns(entities);
}
bool MortarConnected(SCR_AIGroup group)
{
foreach (ERR_HQUnit unit : m_Units)
if (unit.Group == group && unit.Radio) return m_Network.Route(unit.Radio) != null;
return false;
}
ERR_HQRoute Downlink(SCR_AIGroup group, string kind, string detail, int sourceId)
{
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != group || !unit.Radio) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio, true);
if (!route) return null;
route.MessageId = m_Journal.Message();
route.Payload = string.Format("%1 from report M%2; %3", kind, sourceId, detail);
m_Journal.Write("ORDER QUEUED", route.Payload, route.MessageId);
return route;
}
return null;
}
void SupportContacts(out array<ref ERR_HQReport> contacts, float now)
{
contacts.Clear();
foreach (ERR_HQReport contact : m_Contacts)
if (ERR_MortarPrediction.Fresh(contact, now)) contacts.Insert(contact.Snapshot());
}
ERR_HQJournal Journal() { return m_Journal; }
string Status()
{
return string.Format("HQ: %1 groups, %2 delivered contacts, %3 assignments", m_Units.Count(), m_Contacts.Count(), Assigned()) + "; " + m_Mortars.Status();
}
override void RegisterGroup(SCR_AIGroup group)
{
if (!Replication.IsServer() || !group || m_Units.Count() >= 128) return;
foreach (ERR_HQUnit known : m_Units) if (known.Group == group) return;
SCR_AIGroupUtilityComponent utility = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent));
if (!utility || group.GetFaction() != m_Mode.EnemyFaction()) return;
ERR_HQUnit unit = new ERR_HQUnit();
unit.Id = ++m_NextId;
unit.Group = group;
unit.Utility = utility;
int phase = unit.Id % 5;
unit.NextReport = GetGame().GetWorld().GetWorldTime() + phase * 1000;
m_Units.Insert(unit);
m_Journal.Write("REGISTER", string.Format("group %1", unit.Id));
}
override void UnregisterGroup(SCR_AIGroup group)
{
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != group) continue;
unit.Release();
unit.Group = null;
unit.Utility = null;
}
}
protected int Assigned()
{
int total;
foreach (ERR_HQUnit unit : m_Units) if (unit.Assignment || unit.PendingOrder) total++;
return total;
}
protected void IndexRadios()
{
m_Network.Clear();
foreach (ERR_HQUnit unit : m_Units)
{
unit.Radio = null;
if (!unit.Group || unit.Group.GetPlayerCount(true) > 0 || unit.Group.GetFaction() != m_Mode.EnemyFaction()) continue;
array<AIAgent> agents = {};
unit.Group.GetAgents(agents);
int best;
foreach (AIAgent agent : agents)
{
if (!agent) continue;
IEntity actor = agent.GetControlledEntity();
int capability = ERR_HQRadio.Capability(actor);
if (capability <= 0) continue;
m_Network.Add(actor, unit.Group, unit.Id, capability);
if (capability > best) { unit.Radio = actor; best = capability; }
}
}
m_Network.Build();
}
protected void Observe(ERR_HQUnit unit, float now)
{
if (!unit.Utility || !unit.Radio || unit.Uplink || now < unit.NextReport) return;
unit.NextReport = now + m_Mode.Settings().Get("reportIntervalSeconds") * 1000;
array<ref ERR_HQVisualContact> samples = {};
ERR_HQObservation.Gather(unit.Utility, now, samples);
if (samples.IsEmpty()) return;
ERR_HQVisualContact seen = samples[0];
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!route) return;
ERR_HQReport report = new ERR_HQReport();
report.MessageId = m_Journal.Message();
report.Target = seen.Entity;
report.Source = unit.Group;
report.Position = seen.Position;
report.ObservedAt = seen.ObservedAt;
ERR_HQObservation.Describe(report, samples, now);
route.MessageId = report.MessageId;
route.Payload = report.Description(now);
unit.PendingReport = report;
unit.Uplink = route;
m_Journal.Write("REPORT", route.Payload, report.MessageId);
}
protected void Accept(ERR_HQReport report, float now)
{
if (!report || !ERR_MissionRules.ContactFresh(report.ObservedAt, now)) return;
for (int i = 0; i < m_Contacts.Count(); i++)
{
ERR_HQReport previous = m_Contacts[i];
if (previous.Target != report.Target) continue;
if (previous.ObservedAt >= report.ObservedAt) return;
float seconds = (report.ObservedAt - previous.ObservedAt) / 1000;
if (seconds > 0 && seconds < 30 && vector.DistanceXZ(previous.Position, report.Position) < 500)
{
report.Velocity = (report.Position - previous.Position) / seconds;
report.HasVelocity = report.Velocity.Length() <= 100;
}
m_Contacts[i] = report.Snapshot();
return;
}
if (m_Contacts.Count() >= 64) m_Contacts.Remove(0);
m_Contacts.Insert(report.Snapshot());
}
protected void DeliverOrder(ERR_HQUnit unit, float now)
{
ERR_HQReport order = unit.PendingOrder;
if (!order || !ERR_MissionRules.ContactFresh(order.ObservedAt, now) || !unit.Eligible(m_Mode)) { unit.Release(); return; }
SCR_AIGroupPerception perception = unit.Utility.m_Perception;
if (perception && !perception.m_aTargets.IsEmpty()) { unit.Release(); return; }
int deliveryId;
if (unit.Downlink) deliveryId = unit.Downlink.MessageId;
unit.Release();
vector position = order.Position;
if (order.HasVelocity) position = ERR_HQReport.Predict(position, order.Velocity, (now - order.ObservedAt) / 1000);
AIWaypoint waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.SearchWaypoint(), ERR_Actors.Ground(position)));
if (!waypoint) { m_Journal.Write("ORDER FAILED", "waypoint spawn failed", order.MessageId); return; }
unit.Waypoint = waypoint;
unit.Assignment = order;
unit.Group.AddWaypointAt(waypoint, 0);
m_Journal.Write("ORDER DELIVERED", string.Format("group %1 from report M%2: %3", unit.Id, order.MessageId, order.Description(now)), deliveryId);
}
protected void Assign(float now)
{
int limit = m_Mode.Settings().Get("supportSquadLimit");
int radius = m_Mode.Settings().Get("responseRadiusMetres");
int assigned = Assigned();
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Assignment && (!ERR_MissionRules.ContactFresh(unit.Assignment.ObservedAt, now) || !unit.Eligible(m_Mode) || assigned > limit))
{
unit.Release(); assigned--;
}
if (unit.PendingOrder && (!ERR_MissionRules.ContactFresh(unit.PendingOrder.ObservedAt, now) || !unit.Eligible(m_Mode) || assigned > limit))
{
unit.Release(); assigned--;
}
}
foreach (ERR_HQReport report : m_Contacts)
{
if (!ERR_MissionRules.ContactFresh(report.ObservedAt, now)) continue;
foreach (ERR_HQUnit unit : m_Units)
{
if (assigned >= limit) return;
if (unit.Assignment || unit.PendingOrder || !unit.Eligible(m_Mode) || !unit.Radio) continue;
if (vector.DistanceXZ(unit.Group.GetOrigin(), report.Position) > radius) continue;
SCR_AIGroupPerception perception = unit.Utility.m_Perception;
if (perception && !perception.m_aTargets.IsEmpty()) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio, true);
if (!route) continue;
unit.PendingOrder = report.Snapshot();
unit.Downlink = route;
route.MessageId = m_Journal.Message();
route.Payload = "order from report M" + report.MessageId.ToString();
assigned++;
}
}
}
override void Tick(float now)
{
if (!Replication.IsServer()) return;
if (now >= m_NextNetwork) { IndexRadios(); m_NextNetwork = now + 5000; }
for (int i = m_Contacts.Count() - 1; i >= 0; i--)
if (!ERR_MissionRules.ContactFresh(m_Contacts[i].ObservedAt, now)) m_Contacts.Remove(i);
for (int i = m_Units.Count() - 1; i >= 0; i--)
{
ERR_HQUnit unit = m_Units[i];
if (unit.Uplink)
{
int delivered = unit.Uplink.Advance(now, m_Journal);
if (delivered == 1) Accept(unit.PendingReport, now);
if (delivered != 0) { unit.Uplink = null; unit.PendingReport = null; }
}
if (unit.Downlink)
{
int delivered = unit.Downlink.Advance(now, m_Journal);
if (delivered == 1) DeliverOrder(unit, now);
else if (delivered < 0) unit.Release();
}
if (!unit.Group && !unit.Uplink) { unit.Release(); m_Units.Remove(i); continue; }
Observe(unit, now);
}
if (now >= m_NextAssignment) { Assign(now); m_NextAssignment = now + 5000; }
m_Mortars.Tick(now);
m_Journal.Flush();
}
override void Stop()
{
m_Mortars.Stop();
foreach (ERR_HQUnit unit : m_Units) unit.Release();
m_Units.Clear();
m_Contacts.Clear();
m_Network.Clear();
m_Journal.Write("STOP", "HQ stopped; tactical orders released");
m_Journal.Flush();
}
}
modded class ERR_GameMode
{
protected override ERR_CommandService CreateCommandService() { return new ERR_HQ(this); }
}
@@ -0,0 +1,101 @@
// Server-owned audit stream. The file contains every event; chat reads a bounded
// recent-history window with explicit gap notices for clients that fall behind.
class ERR_HQJournal
{
protected ref array<string> m_Recent = {};
protected ref array<string> m_Pending = {};
protected int m_Sequence;
protected int m_Message;
protected static int s_Part;
protected static int s_Session;
protected string m_Session;
void ERR_HQJournal()
{
s_Session++;
m_Session = string.Format("%1-%2", System.GetUnixTime(), s_Session);
}
protected float m_RetryAt;
protected int m_Lost;
string Path()
{
if (s_Part == 0)
return "$logs:rereintroduced-hq.log";
return "$logs:rereintroduced-hq-" + s_Part.ToString() + ".log";
}
int Message()
{
return ++m_Message;
}
int Sequence()
{
return m_Sequence;
}
void Write(string kind, string message, int messageId = 0)
{
if (!Replication.IsServer())
return;
float seconds = GetGame().GetWorld().GetWorldTime() / 1000;
string line = string.Format("#%1 t=%2s M%3 %4 %5", ++m_Sequence, Math.Round(seconds * 10) / 10.0, messageId, kind, message) + " [session=" + m_Session + "]";
if (m_Recent.Count() >= 300)
m_Recent.Remove(0);
m_Recent.Insert(line);
if (m_Pending.Count() < 4096)
m_Pending.Insert(line);
else
m_Lost++;
}
void Read(int after, out array<string> lines, out int cursor, int limit = 8)
{
lines.Clear();
cursor = Math.Clamp(after, 0, m_Sequence);
int first = m_Sequence - m_Recent.Count();
if (cursor < first)
{
lines.Insert(string.Format("HQ log: %1 older entries are outside chat history; see %2", first - cursor, Path()));
cursor = first;
}
int characters;
for (int i = cursor - first; i < m_Recent.Count() && lines.Count() < Math.Clamp(limit, 1, 40); i++)
{
// Bound each menu RPC without skipping unread records. Chat still
// requests eight; the live menu can drain a busy journal faster.
if (characters + m_Recent[i].Length() > 16000 && !lines.IsEmpty())
break;
lines.Insert(m_Recent[i]);
characters += m_Recent[i].Length();
cursor++;
}
}
void Flush()
{
if (m_Pending.IsEmpty() || !Replication.IsServer())
return;
float now = GetGame().GetWorld().GetWorldTime();
if (now < m_RetryAt)
return;
FileHandle file = FileIO.OpenFile(Path(), FileMode.APPEND);
if (!file)
{
m_RetryAt = now + 30000;
PrintFormat("Escapists AI [HQ log]: cannot open %1; retry in 30s, chat history remains available", Path(), level: LogLevel.ERROR);
return;
}
foreach (string line : m_Pending)
file.WriteLine(line);
if (m_Lost > 0)
file.WriteLine(string.Format("HQ log: %1 entries lost while file was unavailable and buffer full", m_Lost));
bool rotate = file.GetLength() >= 5242880;
file.Close();
m_Pending.Clear();
m_Lost = 0;
if (rotate)
s_Part++;
}
}
@@ -0,0 +1,241 @@
// Radio propagation is simulated using actual living carriers and inventory.
// A manpack is the HQ uplink; short-range hops are limited to 500 m and three
// retransmissions. No virtual relay is fabricated when the network is broken.
class ERR_HQRadioNode
{
IEntity Carrier;
SCR_AIGroup Group;
int UnitId;
int Capability;
protected float m_CheckedAt = -1;
protected int m_LiveCapability;
bool Valid(bool manpack = false)
{
ERR_GameMode factions = ERR_GameMode.Get();
if (!Carrier || !Group || Group.GetPlayerCount(true) > 0 || !factions || Group.GetFaction() != factions.EnemyFaction() || ERR_Actors.Group(Carrier) != Group)
return false;
int required = 1;
if (manpack)
required = 2;
float now = GetGame().GetWorld().GetWorldTime();
if (m_CheckedAt < 0 || now < m_CheckedAt || now - m_CheckedAt >= 1000)
{
m_CheckedAt = now;
m_LiveCapability = ERR_HQRadio.Capability(Carrier);
}
return m_LiveCapability >= required;
}
string Label()
{
return "unit " + UnitId.ToString();
}
}
class ERR_HQRoute
{
ref array<ref ERR_HQRadioNode> Nodes = {};
bool Downlink;
int Cursor;
bool Sending;
float Due;
vector SentFrom;
float StartedAt = -1;
int MessageId;
string Payload;
bool Failed;
// -1 failed, 0 travelling, 1 delivered. Each hop really gates delivery.
int Advance(float now, ERR_HQJournal journal)
{
if (Failed)
return -1;
if (StartedAt < 0)
{
StartedAt = now;
if (Downlink)
Cursor = -1; // first leg is HQ to the manpack
}
if (now - StartedAt > 30000)
return Fail(journal, "route timed out");
int target = Cursor + 1;
if (Sending)
{
if (now < Due)
return 0;
if (target < Nodes.Count())
{
if (!Nodes[target].Valid(Downlink && target == 0))
return Fail(journal, "receiving carrier lost radio, died or changed ownership");
if (Cursor >= 0 && vector.DistanceXZ(SentFrom, Nodes[target].Carrier.GetOrigin()) > 500)
return Fail(journal, "receiver moved beyond the 500m link");
journal.Write("RECEIVE", Nodes[target].Label() + " received from " + SenderLabel(), MessageId);
}
else
journal.Write("RECEIVE", "HQ received from " + SenderLabel(), MessageId);
Cursor++;
Sending = false;
if ((!Downlink && Cursor >= Nodes.Count()) || (Downlink && Cursor == Nodes.Count() - 1))
return 1;
target = Cursor + 1;
}
if (Nodes.IsEmpty())
return Fail(journal, "no physical radio route");
if (Cursor >= 0 && !Nodes[Cursor].Valid(!Downlink && Cursor == Nodes.Count() - 1))
return Fail(journal, "transmitting carrier lost radio, died or changed ownership");
string recipient = "HQ";
string link = "long-range";
if (target < Nodes.Count())
{
if (!Nodes[target].Valid(Downlink && target == 0))
return Fail(journal, "next relay unavailable");
recipient = Nodes[target].Label();
if (Cursor >= 0)
{
SentFrom = Nodes[Cursor].Carrier.GetOrigin();
float distance = vector.DistanceXZ(SentFrom, Nodes[target].Carrier.GetOrigin());
if (distance > 500)
return Fail(journal, "next relay beyond 500m");
link = Math.Round(distance).ToString() + "m short-range";
}
}
journal.Write("TRANSMIT", SenderLabel() + " -> " + recipient + " (" + link + ")", MessageId);
Sending = true;
Due = now + 2000;
return 0;
}
protected string SenderLabel()
{
if (Cursor < 0)
return "HQ";
return Nodes[Cursor].Label();
}
protected int Fail(ERR_HQJournal journal, string reason)
{
Failed = true;
journal.Write("LOST", reason + "; " + Payload, MessageId);
return -1;
}
}
class ERR_HQNetwork
{
protected ref array<ref ERR_HQRadioNode> m_Nodes = {};
protected ref array<int> m_Parents = {};
protected ref array<int> m_Depths = {};
protected ref map<IEntity, int> m_Indices = new map<IEntity, int>();
protected ref map<string, ref array<int>> m_Cells = new map<string, ref array<int>>();
bool Overflow;
void Clear()
{
m_Nodes.Clear();
m_Parents.Clear();
m_Depths.Clear();
m_Indices.Clear();
m_Cells.Clear();
Overflow = false;
}
protected string Cell(int x, int z)
{
return string.Format("%1:%2", x, z);
}
void Add(IEntity carrier, SCR_AIGroup group, int unitId, int capability)
{
if (m_Indices.Contains(carrier))
return;
if (m_Nodes.Count() >= 2048)
{
Overflow = true;
return;
}
ERR_HQRadioNode node = new ERR_HQRadioNode();
node.Carrier = carrier;
node.Group = group;
node.UnitId = unitId;
node.Capability = capability;
int index = m_Nodes.Count();
m_Nodes.Insert(node);
m_Indices.Insert(carrier, index);
m_Parents.Insert(-2);
m_Depths.Insert(99);
vector position = carrier.GetOrigin();
string key = Cell(Math.Floor(position[0] / 500), Math.Floor(position[2] / 500));
array<int> cell = m_Cells.Get(key);
if (!cell)
{
cell = {};
m_Cells.Insert(key, cell);
}
cell.Insert(index);
}
void Build()
{
array<int> queue = {};
int checks;
for (int root = 0; root < m_Nodes.Count(); root++)
{
if (m_Nodes[root].Capability == 2)
{
m_Parents[root] = -1;
m_Depths[root] = 0;
queue.Insert(root);
}
}
for (int head = 0; head < queue.Count(); head++)
{
int from = queue[head];
if (m_Depths[from] >= 3)
continue;
vector position = m_Nodes[from].Carrier.GetOrigin();
int x = Math.Floor(position[0] / 500);
int z = Math.Floor(position[2] / 500);
for (int dx = -1; dx <= 1; dx++)
{
for (int dz = -1; dz <= 1; dz++)
{
array<int> neighbors = m_Cells.Get(Cell(x + dx, z + dz));
if (!neighbors)
continue;
foreach (int candidate : neighbors)
{
if (++checks > 100000)
{
Overflow = true;
return;
}
if (m_Parents[candidate] != -2 || vector.DistanceXZ(position, m_Nodes[candidate].Carrier.GetOrigin()) > 500)
continue;
m_Parents[candidate] = from;
m_Depths[candidate] = m_Depths[from] + 1;
queue.Insert(candidate);
}
}
}
}
}
ERR_HQRoute Route(IEntity caller, bool downlink = false)
{
int index;
if (!m_Indices.Find(caller, index) || m_Parents[index] == -2)
return null;
ERR_HQRoute route = new ERR_HQRoute();
route.Downlink = downlink;
while (index >= 0)
{
if (downlink)
route.Nodes.InsertAt(m_Nodes[index], 0);
else
route.Nodes.Insert(m_Nodes[index]);
index = m_Parents[index];
}
return route;
}
}
@@ -0,0 +1,199 @@
// These samples exist only at intake. HQ never revisits their entity loadouts.
class ERR_HQVisualContact
{
IEntity Entity;
vector Position;
float ObservedAt;
bool Escapist;
string Travel = "unknown";
string Weapon = "unknown";
}
class ERR_HQObservation
{
// Require current native line of sight before reading visible equipment.
static bool IsClearSighting(float age, float traceFraction, float exposure)
{
return age >= 0 && age <= 0.5 && traceFraction >= 1 && exposure > 0;
}
static bool CanIdentifyWeapon(float distance, float exposure)
{
return distance >= 0 && distance <= 150 && exposure >= 0.5;
}
static string WeaponCategory(EWeaponType type)
{
switch (type)
{
case EWeaponType.WT_HANDGUN: return "pistol";
case EWeaponType.WT_RIFLE: return "rifle";
case EWeaponType.WT_SNIPERRIFLE: return "sniper rifle";
case EWeaponType.WT_MACHINEGUN: return "machine gun";
case EWeaponType.WT_ROCKETLAUNCHER: return "rocket launcher";
case EWeaponType.WT_GRENADELAUNCHER: return "grenade launcher";
case EWeaponType.WT_FRAGGRENADE: return "grenade";
case EWeaponType.WT_SMOKEGRENADE: return "smoke grenade";
}
return "unidentified weapon";
}
static ERR_HQVisualContact Capture(BaseTarget target, float now)
{
if (!target || target.GetTargetCategory() != ETargetCategory.ENEMY || !IsClearSighting(target.GetTimeSinceSeen(), target.GetTraceFraction(), target.GetExposure()))
return null;
DamageManagerComponent damage = target.GetDamageManagerComponent();
if (damage && damage.IsDestroyed())
return null;
IEntity entity = target.GetTargetEntity();
if (!entity)
return null;
ERR_HQVisualContact seen = new ERR_HQVisualContact();
seen.Entity = entity;
seen.Position = target.GetLastSeenPosition();
seen.ObservedAt = now - target.GetTimeSinceSeen() * 1000;
SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(entity);
if (character)
{
if (GetGame().GetPlayerManager())
seen.Escapist = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(entity) > 0;
seen.Travel = "on foot";
if (CompartmentAccessComponent.GetVehicleIn(entity))
seen.Travel = "in vehicle";
// Read only the drawn weapon; never enumerate weapons or inventory.
if (CanIdentifyWeapon(target.GetDistance(), target.GetExposure()))
{
CharacterControllerComponent controller = CharacterControllerComponent.Cast(entity.FindComponent(CharacterControllerComponent));
if (controller)
{
IEntity heldItem = controller.GetCurrentItemInHands();
BaseWeaponComponent weapon;
if (heldItem)
weapon = BaseWeaponComponent.Cast(heldItem.FindComponent(BaseWeaponComponent));
seen.Weapon = "none drawn";
if (weapon)
seen.Weapon = WeaponCategory(weapon.GetWeaponType());
}
}
}
else if (Vehicle.Cast(entity))
{
seen.Travel = "vehicle";
if (target.GetUnitType() == EAIUnitType.UnitType_Aircraft)
seen.Travel = "aircraft";
}
return seen;
}
static void Gather(SCR_AIGroupUtilityComponent utility, float now, out array<ref ERR_HQVisualContact> samples)
{
samples.Clear();
if (!utility)
return;
array<BaseTarget> visible = {};
utility.ERR_HQGetVisualTargets(visible);
foreach (BaseTarget target : visible)
{
ERR_HQVisualContact seen = Capture(target, now);
if (!seen)
continue;
ERR_HQVisualContact existing;
foreach (ERR_HQVisualContact sample : samples)
{
if (sample.Entity == seen.Entity)
{
existing = sample;
break;
}
}
if (!existing)
{
if (samples.Count() < 64)
samples.Insert(seen);
}
else if (seen.ObservedAt > existing.ObservedAt || (seen.ObservedAt == existing.ObservedAt && existing.Weapon == "unknown" && seen.Weapon != "unknown"))
{
existing.Position = seen.Position;
existing.ObservedAt = seen.ObservedAt;
existing.Travel = seen.Travel;
existing.Weapon = seen.Weapon;
}
}
}
static void Describe(ERR_HQReport report, array<ref ERR_HQVisualContact> samples, float now)
{
// New observations must not silently inherit old equipment/travel details.
report.SeenEscapists = -1;
report.TravelMode = "unknown";
report.SeenWeapons = "unknown";
report.DetailsObservedAt = -1;
if (report.Distress)
return;
ERR_HQVisualContact anchor;
foreach (ERR_HQVisualContact sample : samples)
{
if (sample.Entity == report.Target && now - sample.ObservedAt >= 0 && now - sample.ObservedAt <= 500)
{
anchor = sample;
break;
}
}
if (!anchor)
return;
report.DetailsObservedAt = anchor.ObservedAt;
report.TravelMode = anchor.Travel;
report.SeenWeapons = anchor.Weapon;
array<IEntity> counted = {};
array<string> weapons = {};
string travel;
foreach (ERR_HQVisualContact sighting : samples)
{
if (!sighting.Escapist || !sighting.Entity || counted.Contains(sighting.Entity) || now - sighting.ObservedAt < 0 || now - sighting.ObservedAt > 500 || vector.DistanceXZ(anchor.Position, sighting.Position) > 100)
continue;
counted.Insert(sighting.Entity);
if (travel.IsEmpty())
travel = sighting.Travel;
else if (travel != sighting.Travel)
travel = "mixed travel";
if (sighting.Weapon != "unknown" && !weapons.Contains(sighting.Weapon) && weapons.Count() < 4)
weapons.Insert(sighting.Weapon);
}
if (counted.IsEmpty())
return; // A visible vehicle does not reveal its hidden occupants.
report.SeenEscapists = counted.Count();
// A vehicle anchor remains a vehicle report, even with people near it.
if (anchor.Escapist)
report.TravelMode = travel;
report.SeenWeapons = "unknown";
if (!weapons.IsEmpty())
{
report.SeenWeapons = weapons[0];
for (int i = 1; i < weapons.Count(); i++)
report.SeenWeapons += ", " + weapons[i];
}
}
}
modded class SCR_AIGroupUtilityComponent
{
void ERR_HQGetVisualTargets(out array<BaseTarget> targets)
{
targets.Clear();
foreach (SCR_AIInfoComponent info : m_aInfoComponents)
{
if (!info || !info.m_Perception)
continue;
AIAgent observer = AIAgent.Cast(info.GetOwner());
if (!observer || !ERR_Actors.CanFight(observer.GetControlledEntity()))
continue;
array<BaseTarget> own = {};
info.m_Perception.GetTargetsList(own, ETargetCategory.ENEMY);
foreach (BaseTarget target : own)
{
if (target && ERR_HQObservation.IsClearSighting(target.GetTimeSinceSeen(), target.GetTraceFraction(), target.GetExposure()))
targets.Insert(target);
}
}
}
}
@@ -0,0 +1,144 @@
// A radio's category is protected in the stock gadget component.
modded class SCR_RadioComponent
{
bool ERR_IsHQManpack()
{
return m_iRadioCategory == ERadioCategory.MANPACK;
}
}
class ERR_HQRadio
{
// 0: no radio, 1: basic radio, 2: manpack. Inventory is checked live.
static int Capability(IEntity character)
{
if (!ERR_Actors.CanFight(character))
return 0;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(character.FindComponent(InventoryStorageManagerComponent));
if (!inventory)
return 0;
array<IEntity> items = {};
inventory.GetItems(items);
int result;
foreach (IEntity item : items)
{
if (!item || !item.FindComponent(BaseRadioComponent))
continue;
result = 1;
SCR_RadioComponent gadget = SCR_RadioComponent.Cast(item.FindComponent(SCR_RadioComponent));
if (gadget && gadget.ERR_IsHQManpack())
return 2;
}
return result;
}
}
// HQ uses entity identity only for matching observations, never for its origin.
// Visible details are captured at intake and copied as scalar snapshots.
// Reports and orders contain immutable observed coordinates and timestamps.
class ERR_HQReport
{
int MessageId;
IEntity Target;
SCR_AIGroup Source;
vector Position;
vector Velocity;
float ObservedAt = -1;
float LastSent = -60000;
float PerceptionStamp = -1;
bool HasVelocity;
bool Engaged;
bool Distress;
int SeenEscapists = -1;
string TravelMode = "unknown";
string SeenWeapons = "unknown";
float DetailsObservedAt = -1;
ERR_HQReport Snapshot()
{
ERR_HQReport copy = new ERR_HQReport();
copy.MessageId = MessageId;
copy.Target = Target;
copy.Source = Source;
copy.Position = Position;
copy.Velocity = Velocity;
copy.ObservedAt = ObservedAt;
copy.Engaged = Engaged;
copy.Distress = Distress;
copy.HasVelocity = HasVelocity;
copy.SeenEscapists = SeenEscapists;
copy.TravelMode = TravelMode;
copy.SeenWeapons = SeenWeapons;
copy.DetailsObservedAt = DetailsObservedAt;
return copy;
}
string TravelDirection()
{
if (!HasVelocity)
return "unknown";
if (Velocity.Length() < 0.5)
return "stationary";
float x = Math.AbsFloat(Velocity[0]);
float z = Math.AbsFloat(Velocity[2]);
string northSouth = "N";
string eastWest = "E";
if (Velocity[2] < 0)
northSouth = "S";
if (Velocity[0] < 0)
eastWest = "W";
if (x < z * 0.414214)
return northSouth;
if (z < x * 0.414214)
return eastWest;
return northSouth + eastWest;
}
string Description(float now, bool brief = false)
{
if (Distress)
return string.Format("Distress at friendly X=%1 Z=%2; enemy details unknown (%3s ago)", Math.Round(Position[0]), Math.Round(Position[2]), Math.Round(Math.Max(0, now - ObservedAt) / 1000));
string count = "count unknown";
if (SeenEscapists >= 0)
count = "at least " + SeenEscapists.ToString() + " spotted nearby";
string motion = "speed/direction unknown";
if (HasVelocity)
{
float speed = Math.Round(Velocity.Length() * 10) / 10.0;
float azimuth = Math.Atan2(Velocity[0], Velocity[2]) * Math.RAD2DEG;
if (azimuth < 0)
azimuth += 360;
int heading = Math.Round(azimuth);
motion = string.Format("%1 km/h, azimuth %2 degrees (%3)", Math.Round(speed * 3.6), heading % 360, TravelDirection());
}
string details = count + "; " + TravelMode + "; " + motion + "; seen weapons: " + SeenWeapons;
if (brief)
return details;
string velocity = "unknown";
if (HasVelocity)
velocity = string.Format("[%1,%2] m/s", Math.Round(Velocity[0] * 10) / 10.0, Math.Round(Velocity[2] * 10) / 10.0);
return string.Format("X=%1 Z=%2: %3; vector X/Z=%4 (%5s ago)", Math.Round(Position[0]), Math.Round(Position[2]), details, velocity, Math.Round(Math.Max(0, now - ObservedAt) / 1000));
}
static vector Predict(vector position, vector velocity, float seconds)
{
vector offset = velocity * Math.Clamp(seconds, 0, 20);
offset[1] = 0;
if (offset.Length() > 300)
offset = offset.Normalized() * 300;
return position + offset;
}
int Priority(float now)
{
if (Distress)
return 0;
if (now - ObservedAt <= 15000)
{
if (Engaged)
return 3;
return 2;
}
return 1;
}
}
@@ -0,0 +1,31 @@
// An idle rotor or zero speed alone is normal during takeoff, landing and reload.
// Confirm prolonged grounding, but recognize actual loss of flight capability.
class ERR_HelicopterAvailability
{
protected float m_fGroundedSince = -1;
string Check(float now, float spawnedAt, bool destroyed, bool disabled, bool livingPilot, bool playerControlled, bool servicing, float height, float speed)
{
if (destroyed) return "destroyed";
if (now - spawnedAt < 20000)
{
m_fGroundedSince = -1;
return "";
}
if (disabled) return "engine, rotor or airframe disabled";
if (playerControlled)
{
m_fGroundedSince = -1;
return "";
}
if (!livingPilot) return "no living pilot";
if (servicing || height > 5 || speed > 2)
{
m_fGroundedSince = -1;
return "";
}
if (m_fGroundedSince < 0) m_fGroundedSince = now;
if (now - m_fGroundedSince >= 60000) return "grounded for 60 seconds";
return "";
}
}
@@ -0,0 +1,461 @@
// Migrated from the independently authored AI extension; successor-owned physical groups.
// Each site/phase has its own repeat limiter. Changed reasons and lifecycle
// events are immediate; only identical polling results are summarized.
class ERR_MortarTraceState
{
string LastReason;
float NextLog;
int Suppressed;
bool Due(string reason, float now)
{
if (reason != LastReason || now >= NextLog)
{
LastReason = reason;
NextLog = now + 30000;
return true;
}
Suppressed++;
return false;
}
}
class ERR_MortarBattery
{
static const ResourceName GUN = "{D1FFE458E8AC4BDB}Prefabs/Weapons/Mortars/2B14/Mortar_2B14.et";
static const ResourceName SHELL = "{98EC9C526AFBA282}Prefabs/Weapons/Ammo/Ammo_Shell_82mm_HE_O832DU.et";
static const ResourceName CREW = "{86E565387A634103}Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et";
static const ResourceName RADIO_OPERATOR = "{612F43A4D5AE765F}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et";
IEntity RadioOperator;
IEntity Gun;
SCR_AIGroup Group;
ref SCR_AIStaticArtilleryActivity Activity;
ref ERR_HQReport Report;
ref ERR_HQRoute RadioOrder;
ref ERR_HQReport PendingRadioReport;
ref ERR_HQReport PendingSupplyReport;
protected ref ERR_MortarReadiness m_Readiness;
protected ref ERR_MortarSupplyTransfer m_Transfer;
protected ref array<IEntity> m_AttemptedShells = {};
protected bool m_Stopped;
vector Position;
vector Impact;
vector AimOffset;
int AimedShot = -1;
float FlightTime;
float AimedAt = -1;
float AirspaceUntil;
vector AirspaceImpact;
float AirspaceRadius = 600;
float OrderedAt;
float NextOrder;
float SpawnedAt;
bool StartupActivated;
bool Released;
bool Rejected;
bool Claimed; // keeps the world slot occupied after the battery is destroyed
int SiteId;
int OrderId;
int RadioId;
int SourceId;
int OrderShots;
int TotalShots;
bool CommandOpen;
string LastFailure;
string SpawnFailure;
vector LastCandidate;
ref map<string, int> SearchCounts = new map<string, int>();
ref map<string, ref ERR_MortarTraceState> Traces = new map<string, ref ERR_MortarTraceState>();
void Audit(string kind, string detail)
{
ERR_HQ.Event("MORTAR " + kind, string.Format("site=%1 order=%2 radio=M%3 source=M%4 position=%5; %6", SiteId, OrderId, RadioId, SourceId, Position, detail), RadioId);
}
void Trace(string phase, string reason, string detail)
{
ERR_MortarTraceState state;
if (!Traces.Find(phase, state))
{
state = new ERR_MortarTraceState();
Traces.Insert(phase, state);
}
string previous = state.LastReason;
if (!state.Due(reason, GetGame().GetWorld().GetWorldTime()))
return;
Audit(phase, string.Format("reason=%1; %2; previous=%3 repeated polls omitted=%4", reason, detail, previous, state.Suppressed));
state.Suppressed = 0;
}
void FlushTraces()
{
foreach (string phase, ERR_MortarTraceState state : Traces)
{
if (state.Suppressed > 0)
Audit("REPEATS", string.Format("phase=%1 reason=%2 repeated polls omitted=%3", phase, state.LastReason, state.Suppressed));
}
Traces.Clear();
}
string OperationalReason()
{
if (m_Stopped) return "battery stopped";
if (!Gun) return "gun missing";
if (!SpawnFailure.IsEmpty()) return SpawnFailure;
if (!Group || !Group.GetGroupUtilityComponent()) return "crew group missing";
if (Group.GetFaction() != ERR_GameMode.Get().EnemyFaction()) return "crew changed faction";
if (Group.GetPlayerCount(true) > 0) return "player in crew group";
if (Group.GetAgentsCount() == 0) return "crew group empty";
DamageManagerComponent damage = DamageManagerComponent.Cast(Gun.FindComponent(DamageManagerComponent));
if (damage && damage.IsDestroyed()) return "gun destroyed";
return "";
}
void BeginRequest(ERR_HQReport report, float now)
{
Cancel("superseded by new HQ order");
FlushTraces();
OrderId++;
RadioId = 0;
SourceId = report.MessageId;
OrderShots = 0;
Released = false;
CommandOpen = true;
OrderedAt = now;
LastFailure = "";
Audit("COMMAND", string.Format("requested rounds=%1 HE radius=%2m; %3", ERR_MortarSalvo.ROUNDS, ERR_MortarSalvo.RADIUS_METRES, report.Description(now)));
}
void ObserveProjectile(IEntity projectileEntity, IEntity firingCharacter, bool playerGunner)
{
if (!projectileEntity)
{
Audit("FIRE CALLBACK", "native OnWeaponFired had no projectile; no confirmed shot counted");
return;
}
TotalShots++;
if (CommandOpen && Released && !playerGunner)
{
OrderShots++;
// Only a physical projectile unlocks the next load. It must be aimed again.
Released = false;
AimedAt = -1;
Audit("FIRED", string.Format("physical projectile=%1 origin=%2 order shots=%3 total shots=%4 predicted impact=%5 predicted flight=%6s gunner=%7 (impact not observed)", projectileEntity, projectileEntity.GetOrigin(), OrderShots, TotalShots, Impact, FlightTime, firingCharacter));
}
else
Audit("FIRED UNASSIGNED", string.Format("physical projectile=%1 origin=%2 player gunner=%3 order open=%4 committed=%5 total shots=%6; no active HQ order attribution", projectileEntity, projectileEntity.GetOrigin(), playerGunner, CommandOpen, Released, TotalShots));
}
void ReserveShellAirspace(float now)
{
// Enclose every still-airborne shell, including an earlier, longer flight.
// A later round must not move/shrink the existing exclusion or deadline.
if (now >= AirspaceUntil)
{
AirspaceImpact = Impact;
AirspaceRadius = 600;
}
AirspaceRadius = Math.Max(AirspaceRadius, vector.DistanceXZ(AirspaceImpact, Impact) + 600);
AirspaceUntil = Math.Max(AirspaceUntil, now + (FlightTime + 10) * 1000);
}
bool SpawnFailed(string reason)
{
SpawnFailure = reason;
Audit("DEPLOY FAILED", string.Format("reason=%1 claimed=%2 gun=%3 group=%4", reason, Claimed, Gun, Group));
return false;
}
void SearchResult(vector candidate, string reason)
{
LastCandidate = candidate;
int count;
SearchCounts.Find(reason, count);
SearchCounts.Set(reason, count + 1);
}
void SiteStatus(float now)
{
if (!SearchCounts.IsEmpty())
{
string counts;
foreach (string reason, int count : SearchCounts) counts += string.Format("%1=%2; ", reason, count);
Audit("SITE SEARCH", string.Format("candidate counts since last summary: %1 last candidate=%2", counts, LastCandidate));
SearchCounts.Clear();
}
int agents, living;
int actionState = -1;
if (Group)
{
array<AIAgent> crew = {};
Group.GetAgents(crew);
agents = crew.Count();
foreach (AIAgent agent : crew)
{
if (agent && ERR_Actors.CanFight(agent.GetControlledEntity())) living++;
}
}
if (Activity) actionState = Activity.GetActionState();
bool connected;
ERR_HQ hq = ERR_HQ.Get();
if (hq && Group) connected = hq.MortarConnected(Group);
Audit("SITE STATUS", string.Format("claimed=%1 startup=%2 operational=%3 crew agents=%4 fighting=%5 inventory HE=%6 radio connected=%7 cooldown remaining=%8s", Claimed, StartupActivated, Operational(), agents, living, CountShells(), connected, Math.Max(0, NextOrder - now) / 1000));
Audit("ORDER STATUS", string.Format("open=%1 route pending=%2 native action=%3 shell committed=%4 order shots=%5 total shots=%6 age=%7s last failure=%8", CommandOpen, RadioOrder != null, actionState, Released, OrderShots, TotalShots, Math.Max(0, now - OrderedAt) / 1000, LastFailure));
if (!SpawnFailure.IsEmpty()) Audit("PARTIAL DEPLOYMENT", SpawnFailure);
if (!Operational()) Trace("SITE BLOCK", OperationalReason(), "spawn failure=" + SpawnFailure);
}
bool Operational()
{
return OperationalReason().IsEmpty();
}
int CountShells()
{
if (!Group)
return 0;
int count;
array<IEntity> items = {};
array<AIAgent> agents = {};
Group.GetAgents(agents);
foreach (AIAgent agent : agents)
{
if (!agent || !ERR_Actors.CanFight(agent.GetControlledEntity()))
continue;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(agent.GetControlledEntity().FindComponent(InventoryStorageManagerComponent));
if (!inventory)
continue;
ERR_Inventory.AppendUnique(inventory, items);
}
foreach (IEntity item : items)
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == SHELL) count++;
return count;
}
void Bind(int siteId, SCR_AIGroup group, IEntity gun, float now)
{
SiteId = siteId;
Group = group;
Gun = gun;
Position = gun.GetOrigin();
SpawnedAt = now;
Claimed = true;
m_Readiness = new ERR_MortarReadiness(this);
}
int InventoryShells(InventoryStorageManagerComponent inventory)
{
if (!inventory)
return 0;
int count;
array<IEntity> items = {};
ERR_Inventory.Items(inventory, items);
foreach (IEntity item : items)
{
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == SHELL)
count++;
}
return count;
}
bool Stopped() { return m_Stopped; }
bool SupplyPending() { return m_Transfer && m_Transfer.Unresolved(); }
bool SupplyAuthorized(float now)
{
if (!Replication.IsServer() || m_Stopped || !StartupActivated || !Operational() || !CommandOpen || !ERR_HQ.MissionActive()) return false;
ERR_MortarSystem system = ERR_MortarSystem.Get();
if (!system || system.FindGun(Gun) != this) return false;
ERR_HQReport suppliedReport = Report;
if (!suppliedReport) suppliedReport = PendingSupplyReport;
return ERR_MortarPrediction.Fresh(suppliedReport, now);
}
void Stop()
{
if (m_Stopped) return;
m_Stopped = true;
Cancel("HQ stopped");
if (m_Readiness) m_Readiness.Stop();
}
ERR_MortarSupplyState SupplyState(float now)
{
// Observe an existing native operation even after its order was canceled.
// No second request may race an unresolved transfer on this battery.
if (m_Transfer)
{
ERR_MortarSupplyState observed = m_Transfer.Poll(now);
if (m_Transfer.CapturedOrder() == OrderId)
{
if (observed == ERR_MortarSupplyState.READY) m_Transfer = null;
return observed;
}
if (m_Transfer.Unresolved()) return ERR_MortarSupplyState.FAILED;
m_Transfer = null;
}
if (!SupplyAuthorized(now)) return SupplyStateFailed("current HQ order, crew or report is unavailable");
SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(Gun.FindComponent(SCR_AIVehicleUsageComponent));
IEntity gunner;
if (usage && usage.GetTurretCompartmentSlot())
gunner = usage.GetTurretCompartmentSlot().GetOccupant();
array<AIAgent> agents = {};
Group.GetAgents(agents);
float nearest = float.MAX;
if (!gunner)
{
foreach (AIAgent candidate : agents)
{
if (!candidate || candidate.GetControlledEntity() == RadioOperator || !ERR_Actors.CanFight(candidate.GetControlledEntity()))
continue;
float distance = vector.DistanceXZ(Gun.GetOrigin(), candidate.GetControlledEntity().GetOrigin());
if (distance < nearest)
{
nearest = distance;
gunner = candidate.GetControlledEntity();
}
}
}
if (!gunner) return SupplyStateFailed("no fighting gunner found");
if (ERR_Actors.Group(gunner) != Group) return SupplyStateFailed("turret occupant belongs to another group");
if (!ERR_Actors.CanFight(gunner)) return SupplyStateFailed("gunner cannot fight");
InventoryStorageManagerComponent destination = InventoryStorageManagerComponent.Cast(gunner.FindComponent(InventoryStorageManagerComponent));
if (!destination)
return SupplyStateFailed("gunner inventory missing");
if (InventoryShells(destination) > 0)
return ERR_MortarSupplyState.READY;
int nearbyDonors, donorShells, storageRejected;
array<IEntity> consideredShells = {};
foreach (AIAgent bearer : agents)
{
if (!bearer || !ERR_Actors.CanFight(bearer.GetControlledEntity()))
continue;
IEntity donor = bearer.GetControlledEntity();
if (donor == gunner || vector.DistanceXZ(donor.GetOrigin(), gunner.GetOrigin()) > 12)
continue;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(donor.FindComponent(InventoryStorageManagerComponent));
if (!inventory)
continue;
nearbyDonors++;
array<IEntity> items = {};
ERR_Inventory.Items(inventory, items);
foreach (IEntity item : items)
{
if (!item || !item.GetPrefabData() || item.GetPrefabData().GetPrefabName() != SHELL)
continue;
if (consideredShells.Contains(item) || m_AttemptedShells.Contains(item)) continue;
consideredShells.Insert(item);
donorShells++;
BaseInventoryStorageComponent storage = destination.FindStorageForItem(item, EStoragePurpose.PURPOSE_DEPOSIT);
if (!storage) { storageRejected++; continue; }
m_AttemptedShells.Insert(item); // even rejected/ambiguous requests are never retried
m_Transfer = new ERR_MortarSupplyTransfer(this, donor, gunner, item, storage, now);
if (!m_Transfer.Begin(now)) return SupplyStateFailed("exact shell transfer request rejected; no retry");
Audit("AMMO TRANSFER", string.Format("one exact-item move pending donor=%1 gunner=%2 shell=%3 order=%4; awaiting callback AND physical destination", donor, gunner, item, OrderId));
return ERR_MortarSupplyState.PENDING;
}
}
return SupplyStateFailed(string.Format("gunner empty; fighting donors within 12m=%1 unattempted HE=%2 destination storage rejected=%3", nearbyDonors, donorShells, storageRejected));
}
// Compatibility for existing native callers; request acceptance is NOT ready.
bool SupplyGunner() { return SupplyState(GetGame().GetWorld().GetWorldTime()) == ERR_MortarSupplyState.READY; }
protected ERR_MortarSupplyState SupplyStateFailed(string reason)
{
SupplyFailed(reason);
return ERR_MortarSupplyState.FAILED;
}
bool SupplyFailed(string reason)
{
LastFailure = reason;
Audit("AMMO FAILED", reason);
return false;
}
void Cancel(string reason = "cancel requested")
{
if (CommandOpen)
{
FlushTraces();
Audit("ORDER END", string.Format("reason=%1 observed shots=%2 shell committed=%3 elapsed=%4s last failure=%5", reason, OrderShots, Released, (GetGame().GetWorld().GetWorldTime() - OrderedAt) / 1000, LastFailure));
}
CommandOpen = false;
RadioOrder = null;
PendingRadioReport = null;
PendingSupplyReport = null;
if (m_Transfer) m_Transfer.Invalidate();
Report = null;
AimedAt = -1;
if (Activity)
Activity.Complete();
Activity = null;
}
// Idle distant batteries still report through HQ's scheduler. Their native
// AI needs full detail while firing or when players can interact with them.
protected void UpdateCrewDetail(float now, bool firing = false)
{
if (!Group || Group.GetPlayerCount(true) > 0)
return;
bool active = firing || Activity != null || ERR_MortarSystem.NearPlayer(Position);
int lod = -1;
if (active)
lod = 0;
if (Group.GetPermanentLOD() != lod)
Group.SetPermanentLOD(lod);
if (active && !Group.IsAIActivated())
Group.ActivateAI();
array<AIAgent> agents = {};
Group.GetAgents(agents);
foreach (AIAgent agent : agents)
{
if (!agent || EntityUtils.IsPlayer(agent.GetControlledEntity()))
continue;
if (agent.GetPermanentLOD() != lod)
agent.SetPermanentLOD(lod);
if (active && !agent.IsAIActivated() && ERR_Actors.CanFight(agent.GetControlledEntity()))
agent.ActivateAI();
}
}
void Update(float now)
{
if (m_Stopped) return;
if (!StartupActivated)
{
if (!SpawnFailure.IsEmpty()) return;
if (!m_Readiness) { SpawnFailed("initial support readiness owner missing"); return; }
ERR_MortarSupplyState startup = m_Readiness.Poll(now);
if (startup != ERR_MortarSupplyState.READY) return;
StartupActivated = true;
}
if (m_Transfer) m_Transfer.Poll(now);
if (!Operational())
{
Cancel(OperationalReason());
return;
}
if (Activity)
{
Trace("ACTIVITY", string.Format("native state=%1", Activity.GetActionState()), string.Format("age=%1s aim age=%2s committed=%3 shots=%4", (now - OrderedAt) / 1000, (now - AimedAt) / 1000, Released, OrderShots));
if (Activity.GetActionState() == EAIActionState.FAILED) Cancel("native artillery activity FAILED");
else if (Activity.GetActionState() == EAIActionState.COMPLETED) Cancel("native artillery activity COMPLETED (shot count is separate)");
else if (now - OrderedAt > ERR_MortarSalvo.TIMEOUT_MS) Cancel("120s artillery salvo timeout");
}
if (StartupActivated)
UpdateCrewDetail(now);
}
void Order(ERR_HQReport report, float now)
{
if (m_Stopped || !StartupActivated || !Operational() || !CommandOpen || Activity || !ERR_MortarPrediction.Fresh(report, now)) return;
Report = report.Snapshot();
OrderedAt = now;
NextOrder = now + 30000;
Released = false;
UpdateCrewDetail(now, true);
Activity = new SCR_AIStaticArtilleryActivity(Group.GetGroupUtilityComponent(), null, report.Position, SCR_EAIArtilleryAmmoType.HIGH_EXPLOSIVE, ERR_MortarSalvo.ROUNDS);
Group.GetGroupUtilityComponent().AddAction(Activity);
Audit("AIM", string.Format("native activity created; latest source=M%1 observed=%2", report.MessageId, report.Description(now)));
}
}
@@ -0,0 +1,231 @@
// The dedicated manpack operator has no mortar-shell backpack. Preserve the
// native chooser and its caller's original index for every eligible gunner.
modded class SCR_AIStaticArtilleryActivity
{
protected override AIAgent FindBestAgentForArtillery(notnull array<AIAgent> agents, notnull IEntity artilleryEntity, out int outIndex)
{
ERR_MortarSystem system = ERR_MortarSystem.Get();
ERR_MortarBattery battery;
if (system) battery = system.FindGun(artilleryEntity);
if (!battery) return super.FindBestAgentForArtillery(agents, artilleryEntity, outIndex);
array<AIAgent> gunners = {};
foreach (AIAgent agent : agents)
{
if (agent && agent.GetControlledEntity() != battery.RadioOperator && ERR_Actors.CanFight(agent.GetControlledEntity()))
gunners.Insert(agent);
}
int filteredIndex;
AIAgent selected = super.FindBestAgentForArtillery(gunners, artilleryEntity, filteredIndex);
outIndex = -1;
if (selected) outIndex = agents.Find(selected);
return selected;
}
}
// Leave all other artillery (including player-operated captured guns) native.
modded class SCR_AIGetArtilleryAimDistanceCompensation
{
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
{
IEntity gun;
GetVariableIn(PORT_ARTILLERY_ENTITY, gun);
ERR_MortarSystem system = ERR_MortarSystem.Get();
ERR_MortarBattery battery;
if (system)
battery = system.FindGun(gun);
if (!battery)
return super.EOnTaskSimulate(owner, dt);
battery.AimedAt = -1;
float now = GetGame().GetWorld().GetWorldTime();
ERR_HQReport report = system.Latest(battery, now);
if (!ERR_HQ.MissionActive()) { system.Withhold(battery, "aim: mission inactive"); return ENodeResult.FAIL; }
if (!battery.CommandOpen || battery.OrderShots >= ERR_MortarSalvo.ROUNDS) { system.Withhold(battery, "aim: salvo complete or order closed"); return ENodeResult.FAIL; }
if (battery.Released) { system.Withhold(battery, "aim: waiting for committed projectile"); return ENodeResult.FAIL; }
if (!report) { system.Withhold(battery, "aim: " + system.ContactFailure(battery)); return ENodeResult.FAIL; }
battery.Trace("AIM START", "solving moving intercept", string.Format("latest source=M%1; %2", report.MessageId, report.Description(now)));
ResourceName ammo;
GetVariableIn(PORT_AMMO_PREFAB, ammo);
if (ammo != ERR_MortarBattery.SHELL) { system.Withhold(battery, "unsupported ammunition prefab", ammo); return ENodeResult.FAIL; }
Resource resource = Resource.Load(ammo);
if (!resource || !resource.IsValid() || !resource.GetResource()) { system.Withhold(battery, "shell resource load failed", ammo); return ENodeResult.FAIL; }
IEntitySource source = resource.GetResource().ToEntitySource();
if (!source) { system.Withhold(battery, "shell resource has no entity source", ammo); return ENodeResult.FAIL; }
array<float> coefficients = {};
GetAmmoInitialSpeedCoefficients(ammo, coefficients);
if (coefficients.IsEmpty())
coefficients.Insert(1.0);
float minimum, maximum;
GetVerticalAimLimits(gun, minimum, maximum);
float flight = 30;
float offset;
int charge;
vector impact;
vector salvoOffset = ERR_MortarSalvo.Offset(battery.SiteId, battery.OrderId, battery.OrderShots);
bool converged;
// Iterate the moving intercept using the native shell's flight time.
// Reject non-convergence rather than fire with an arbitrary lead time.
for (int iteration = 0; iteration < 4; iteration++)
{
if (!ERR_MortarPrediction.Predict(report, now, flight + 2, impact)) { system.Withhold(battery, "aim prediction: " + ERR_MortarPrediction.FailureReason, string.Format("flight lead=%1s; %2", flight + 2, report.Description(now))); return ENodeResult.FAIL; }
if (!system.OutsideSettlements(impact)) { system.Withhold(battery, "aim target inside settlement exclusion", system.SettlementReason); return ENodeResult.FAIL; }
impact += salvoOffset;
impact[1] = SCR_TerrainHelper.GetTerrainY(impact);
float distance = vector.DistanceXZ(gun.GetOrigin(), impact);
float altitude = impact[1] - gun.GetOrigin()[1];
if (distance < 350 || distance > 4000) { system.Withhold(battery, "predicted impact out of range", string.Format("iteration=%1 distance=%2m impact=%3 allowed=350..4000m", iteration, distance, impact)); return ENodeResult.FAIL; }
bool reachable;
float calculated;
for (int i = 0; i < coefficients.Count(); i++)
{
if (!BallisticTable.GetAimHeightOfProjectileAltitudeFromSource(distance, offset, calculated, source, altitude, coefficients[i]))
continue;
float tangent = (offset + altitude) / distance;
if (calculated <= 0 || calculated > 75 || tangent < Math.Tan(minimum) || tangent > Math.Tan(maximum))
continue;
charge = i;
reachable = true;
break;
}
if (!reachable) { system.Withhold(battery, "no native ballistic solution within elevation/flight-time limits", string.Format("iteration=%1 distance=%2 altitude=%3 charges=%4 elevation radians=%5..%6 flight limit=75s", iteration, distance, altitude, coefficients.Count(), minimum, maximum)); return ENodeResult.FAIL; }
converged = Math.AbsFloat(calculated - flight) < 1;
flight = calculated;
if (converged)
break;
}
if (!converged) { system.Withhold(battery, "moving intercept did not converge in four iterations"); return ENodeResult.FAIL; }
if (!system.Safe(battery, impact, flight + 2)) { system.Withhold(battery, "aim impact safety rejected", system.SafetyReason); return ENodeResult.FAIL; }
battery.Impact = impact;
battery.AimOffset = salvoOffset;
battery.AimedShot = battery.OrderShots;
battery.FlightTime = flight;
battery.AimedAt = now;
battery.LastFailure = "";
battery.Trace("AIM SOLUTION", "ready", string.Format("predicted impact=%1 flight=%2s charge index=%3 aim height offset=%4m latest source=M%5", impact, flight, charge, offset, report.MessageId));
vector aim = impact + Vector(0, offset, 0);
SetVariableOut(PORT_AIM_POS, aim);
SetVariableOut(PORT_INIT_SPEED_ID, charge);
return ENodeResult.SUCCESS;
}
}
modded class SCR_AIShootStaticArtillery
{
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
{
IEntity gun;
GetVariableIn(PORT_ARTILLERY_ENTITY, gun);
ERR_MortarSystem system = ERR_MortarSystem.Get();
ERR_MortarBattery battery;
if (system)
battery = system.FindGun(gun);
if (battery && !system.AllowShot(battery))
{
battery.Trace("SHOOT NODE", "authorization rejected", battery.LastFailure);
return ENodeResult.FAIL;
}
ENodeResult result = super.EOnTaskSimulate(owner, dt);
if (battery)
battery.Trace("SHOOT NODE", string.Format("native result=%1", result), "authorization passed; node result does not confirm a physical shot");
return result;
}
}
modded class SCR_MortarMuzzleComponent
{
protected override void TransferShellToMortar()
{
ERR_MortarSystem system = ERR_MortarSystem.Get();
ERR_MortarBattery battery;
if (system && m_CharController && !EntityUtils.IsPlayer(m_CharController.GetOwner()))
battery = system.FindGun(GetOwner());
if (battery)
{
// The loading animation takes time. Recheck at the actual transfer,
// before native inventory insertion triggers the physical projectile.
if (!system.AllowShot(battery))
{
if (m_ShellComponent)
{
m_ShellComponent.GetOnShellUsed().Remove(TransferShellToMortar);
m_ShellComponent.SetLoadedState(false);
}
CharacterAnimationComponent animation = m_CharController.GetAnimationComponent();
if (animation && animation.GetCommandHandler())
animation.GetCommandHandler().FinishItemUse(false);
battery.Audit("ABORT", "final shell transfer rejected; " + battery.LastFailure);
return;
}
battery.Released = true;
battery.ReserveShellAirspace(GetGame().GetWorld().GetWorldTime());
battery.Audit("SHELL COMMIT", string.Format("final safety passed; gunner=%1 predicted impact=%2 flight=%3s; invoking native transfer, awaiting projectile event", m_CharController.GetOwner(), battery.Impact, battery.FlightTime));
}
super.TransferShellToMortar();
}
override void OnWeaponFired(IEntity effectEntity, BaseMuzzleComponent muzzle, IEntity projectileEntity)
{
IEntity firingCharacter;
if (m_CharController) firingCharacter = m_CharController.GetOwner();
super.OnWeaponFired(effectEntity, muzzle, projectileEntity);
ERR_MortarSystem system = ERR_MortarSystem.Get();
ERR_MortarBattery battery;
if (system)
battery = system.FindGun(GetOwner());
if (!battery)
return;
bool playerGunner;
if (firingCharacter) playerGunner = EntityUtils.IsPlayer(firingCharacter);
battery.ObserveProjectile(projectileEntity, firingCharacter, playerGunner);
}
}
// The native tree normally re-aims only every five shots (and skips the first
// re-aim). Each salvo shell needs its own spread point and fresh authorization.
modded class SCR_AIStaticArtilleryBehavior
{
ERR_MortarBattery ERR_GetMortarBattery()
{
ERR_MortarSystem system = ERR_MortarSystem.Get();
if (!system) return null;
return system.FindGun(m_ArtilleryEntity.m_Value);
}
}
modded class SCR_AIStaticArtilleryBehavior_ShootingLogic
{
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
{
ERR_MortarBattery battery;
SCR_AIStaticArtilleryBehavior behavior;
if (m_Utility)
{
behavior = SCR_AIStaticArtilleryBehavior.Cast(m_Utility.GetExecutedAction());
if (behavior) battery = behavior.ERR_GetMortarBattery();
}
if (battery)
{
int gate = ERR_MortarSupplyRules.CycleGate(battery.CommandOpen, battery.OrderShots, behavior.GetShotCount(), ERR_MortarSalvo.ROUNDS, ERR_MortarSupplyState.READY);
if (gate < 0) return ENodeResult.FAIL;
if (gate == 0) return ENodeResult.RUNNING;
// Native super increments the behavior counter. Wait BEFORE calling it,
// so repeated pending ticks cannot count the same projectile twice.
if (battery.OrderShots < ERR_MortarSalvo.ROUNDS)
{
ERR_MortarSupplyState supply = battery.SupplyState(GetGame().GetWorld().GetWorldTime());
if (supply == ERR_MortarSupplyState.PENDING) return ENodeResult.RUNNING;
if (supply == ERR_MortarSupplyState.FAILED)
{
ERR_MortarSystem system = ERR_MortarSystem.Get();
if (system) system.Withhold(battery, "next native load lacks confirmed physical gunner ammunition");
return ENodeResult.FAIL;
}
}
}
ENodeResult result = super.EOnTaskSimulate(owner, dt);
if (battery && result == ENodeResult.SUCCESS)
{
SetVariableOut(PORT_AIMING_NEEDED, true);
}
return result;
}
}
@@ -0,0 +1,131 @@
// All target coordinates come from delivered HQ observations, never a player's
// current transform. Road projection stops at an unknown junction/road end.
class ERR_MortarPrediction
{
// Read immediately after a failed synchronous prediction; no extra world scan.
static string FailureReason;
// Includes observation uplink, HQ downlink and native aiming. All stages
// retain the original observation time; radio delivery never renews it.
static const float MAX_REPORT_AGE_MS = 60000;
static bool Fresh(ERR_HQReport report, float now)
{
return report && report.Target && !report.Distress && now >= report.ObservedAt && now - report.ObservedAt <= MAX_REPORT_AGE_MS && report.TravelMode != "aircraft";
}
static bool Reject(string reason)
{
FailureReason = reason;
return false;
}
static vector ClosestOnSegment(vector point, vector start, vector end)
{
vector segment = end - start;
segment[1] = 0;
vector offset = point - start;
offset[1] = 0;
float lengthSq = segment.LengthSq();
if (lengthSq < 0.01)
return start;
return vector.Lerp(start, end, Math.Clamp(vector.Dot(offset, segment) / lengthSq, 0, 1));
}
static bool FollowRoad(array<vector> points, vector observed, vector velocity, float seconds, out vector impact)
{
if (!points || points.Count() < 2)
return Reject("road polyline has fewer than two points");
int segment = -1;
float closest = 20;
vector projected;
for (int i = 0; i < points.Count() - 1; i++)
{
vector candidate = ClosestOnSegment(observed, points[i], points[i + 1]);
float distance = vector.DistanceXZ(candidate, observed);
if (distance < closest)
{
closest = distance;
segment = i;
projected = candidate;
}
}
if (segment < 0)
return Reject("observed vehicle is not within 20m of a road segment");
vector forward = points[segment + 1] - points[segment];
forward[1] = 0;
forward.Normalize();
vector travel = velocity;
travel[1] = 0;
float speed = travel.Length();
travel.Normalize();
float alignment = vector.Dot(forward, travel);
if (Math.AbsFloat(alignment) < 0.7)
return Reject("vehicle heading crosses road; alignment below 0.7");
int step = 1;
int next = segment + 1;
if (alignment < 0)
{
step = -1;
next = segment;
}
float remaining = speed * seconds;
vector position = projected;
while (next >= 0 && next < points.Count())
{
float length = vector.DistanceXZ(position, points[next]);
if (length >= remaining && length > 0.01)
{
impact = vector.Lerp(position, points[next], remaining / length);
return true;
}
remaining -= length;
position = points[next];
next += step;
}
return Reject("prediction reaches unknown road end/junction");
}
static bool Predict(ERR_HQReport report, float now, float flightSeconds, out vector impact)
{
FailureReason = "";
if (!report) return Reject("target report missing");
if (report.Distress) return Reject("distress report cannot authorize fire");
if (now < report.ObservedAt) return Reject("observation timestamp is in the future");
if (now - report.ObservedAt > MAX_REPORT_AGE_MS) return Reject("observation older than 60s");
float seconds = (now - report.ObservedAt) / 1000 + flightSeconds;
if (seconds < 0 || seconds > 90)
return Reject("observation age plus flight outside 0..90s");
if (report.TravelMode == "aircraft") return Reject("aircraft target unsupported");
if (report.TravelMode == "mixed travel") return Reject("mixed travel cannot be predicted");
impact = report.Position;
if (!report.HasVelocity || report.Velocity.Length() < 0.5)
return true;
if (report.Velocity.Length() * seconds > 1800)
return Reject("predicted travel exceeds 1800m");
bool vehicle = report.TravelMode == "vehicle" || report.TravelMode == "in vehicle";
if (vehicle)
{
SCR_AIWorld world = SCR_AIWorld.Cast(GetGame().GetAIWorld());
if (!world || !world.GetRoadNetworkManager())
return Reject("road network unavailable");
BaseRoad road;
float roadDistance;
world.GetRoadNetworkManager().GetClosestRoad(report.Position, road, roadDistance, skipNavlinks: true);
if (!road) return Reject("no road near reported vehicle position");
if (roadDistance > 20) return Reject("reported vehicle farther than 20m from road");
array<vector> points = {};
road.GetPoints(points);
return FollowRoad(points, report.Position, report.Velocity, seconds, impact);
}
impact += report.Velocity * seconds;
return true;
}
static bool ThreatensFriendly(vector impact, vector position, vector velocity, float flightSeconds)
{
velocity[1] = 0;
vector future = position + velocity * Math.Clamp(flightSeconds, 0, 90);
// Protect the entire predicted path, not only where a soldier is now.
return vector.DistanceXZ(impact, ClosestOnSegment(impact, position, future)) <= 100;
}
}
@@ -0,0 +1,177 @@
enum ERR_MortarSupplyState { FAILED = -1, PENDING, READY }
class ERR_MortarSupplyRules
{
static int CycleGate(bool commandOpen, int confirmedShots, int behaviorShots, int limit, int supplyState)
{
if (!commandOpen) return -1;
if (confirmedShots <= behaviorShots) return 0;
if (confirmedShots < limit) return supplyState;
return 1;
}
}
class ERR_MortarInitialItem : ScriptedInventoryOperationCallback
{
bool Finished;
bool Succeeded;
protected void Finish(bool success) { if (!Finished) { Finished = true; Succeeded = success; } }
protected override void OnComplete() { Finish(true); }
protected override void OnFailed() { Finish(false); }
protected override void OnAllComplete() { Finish(true); }
protected override void OnAllFailed() { Finish(false); }
void Rejected() { Finish(false); }
}
// One finite allocation, after the ENTIRE original support crew exists. Failed
// or stopped setup retains physical assets and retires only its pending spawn intent.
class ERR_MortarReadiness
{
protected ERR_MortarBattery m_Battery;
protected ref array<IEntity> m_Members = {};
protected ref array<ref ERR_MortarInitialItem> m_Operations = {};
protected bool m_Allocated;
protected bool m_Ready;
protected bool m_Stopped;
protected bool m_Retired;
protected int m_RequestedShells;
void ERR_MortarReadiness(ERR_MortarBattery battery) { m_Battery = battery; }
static ERR_MortarSupplyState Population(int physical, int gunners, int operators, bool complete, bool expired)
{
if (physical > 4 || gunners > 3 || operators > 1) return ERR_MortarSupplyState.FAILED;
if (physical == 4 && gunners == 3 && operators == 1 && complete && !expired) return ERR_MortarSupplyState.READY;
if (expired) return ERR_MortarSupplyState.FAILED;
return ERR_MortarSupplyState.PENDING;
}
static bool AllocationValid(int shells) { return shells >= 0 && shells <= 9; }
int RequestedShells() { return m_RequestedShells; }
bool Ready() { return m_Ready && !m_Stopped; }
void Stop()
{
if (m_Stopped) return;
m_Stopped = true;
if (m_Ready || m_Retired || !m_Battery || !m_Battery.Group || !Replication.IsServer()) return;
m_Retired = true;
// As in Core initial guard cleanup: stopping the current request alone does
// not retire the native group's still-authored future expansion intent.
RetireGroup(m_Battery.Group);
}
static void RetireGroup(SCR_AIGroup group)
{
if (!group || !Replication.IsServer()) return;
group.SetSpawnImmediately(false);
group.m_aUnitPrefabSlots = new array<ResourceName>();
if (!GetGame()) return;
ChimeraAIWorld world = ChimeraAIWorld.Cast(GetGame().GetAIWorld());
if (world) world.PurgeSpawnRequestsForGroup(group);
}
protected ERR_MortarSupplyState Fail(string reason)
{
m_Battery.SpawnFailed(reason);
Stop();
return ERR_MortarSupplyState.FAILED;
}
protected bool Allocate()
{
m_Allocated = true; // before native requests; never refill or retry a failure
foreach (IEntity actor : m_Members)
{
if (actor == m_Battery.RadioOperator) continue;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));
int existing = m_Battery.InventoryShells(inventory);
if (!AllocationValid(existing)) return false;
if (ERR_HQRadio.Capability(actor) == 0 && !inventory.TrySpawnPrefabToStorage("{E1A5D4B878AA8980}Prefabs/Items/Equipment/Radios/Radio_R148.et"))
m_Battery.Audit("RADIO EQUIP", "optional crew handset did not fit; dedicated manpack remains required");
for (int i = existing; i < 9; i++)
{
ERR_MortarInitialItem operation = new ERR_MortarInitialItem();
m_Operations.Insert(operation);
m_RequestedShells++;
if (!inventory.TrySpawnPrefabToStorage(ERR_MortarBattery.SHELL, purpose: EStoragePurpose.PURPOSE_DEPOSIT, cb: operation))
{
operation.Rejected();
return false;
}
}
}
return true;
}
ERR_MortarSupplyState Poll(float now)
{
if (m_Stopped || !Replication.IsServer() || !m_Battery || m_Battery.Stopped()) return ERR_MortarSupplyState.FAILED;
if (m_Ready) return ERR_MortarSupplyState.READY;
SCR_AIGroup group = m_Battery.Group;
ERR_GameMode mode = ERR_GameMode.Get();
if (!mode || !group || !m_Battery.Gun || group.GetFaction() != mode.EnemyFaction() || group.GetPlayerCount(true) > 0) return Fail("initial support group/gun/faction changed");
DamageManagerComponent damage = DamageManagerComponent.Cast(m_Battery.Gun.FindComponent(DamageManagerComponent));
if (!damage || damage.IsDestroyed()) return Fail("initial support gun missing damage manager or destroyed");
bool expired = now < m_Battery.SpawnedAt || now - m_Battery.SpawnedAt >= 90000;
array<AIAgent> agents = {}; group.GetAgents(agents);
array<IEntity> physical = {};
int gunners, operators;
IEntity operatorActor;
foreach (AIAgent agent : agents)
{
if (!agent || !agent.GetControlledEntity()) continue;
IEntity actor = agent.GetControlledEntity();
if (physical.Contains(actor)) return Fail("initial support group reports duplicate physical actor");
physical.Insert(actor);
if (!ERR_Actors.CanFight(actor) || SCR_FactionManager.SGetFaction(actor) != mode.EnemyFaction() || !actor.GetPrefabData()) return Fail("initial support actor unavailable or has wrong faction/resource");
ResourceName prefab = actor.GetPrefabData().GetPrefabName();
if (prefab == ERR_MortarBattery.CREW) gunners++;
else if (prefab == ERR_MortarBattery.RADIO_OPERATOR) { operators++; operatorActor = actor; }
else return Fail("initial support actor does not belong to authored crew catalog");
}
ERR_MortarSupplyState population = Population(physical.Count(), gunners, operators, group.IsExpandComplete(), expired);
if (population == ERR_MortarSupplyState.FAILED) return Fail("initial four-person support population incomplete/invalid within 90 seconds");
if (population == ERR_MortarSupplyState.PENDING) return population;
if (m_Allocated)
{
foreach (IEntity original : m_Members)
if (!physical.Contains(original)) return Fail("initial support member replaced after finite allocation");
}
foreach (IEntity member : physical)
{
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(member.FindComponent(InventoryStorageManagerComponent));
if (!inventory) return ERR_MortarSupplyState.PENDING;
if (!m_Allocated && member != operatorActor && m_Battery.InventoryShells(inventory) < 9 && !inventory.CanInsertResource(ERR_MortarBattery.SHELL, EStoragePurpose.PURPOSE_DEPOSIT)) return ERR_MortarSupplyState.PENDING;
}
if (ERR_HQRadio.Capability(operatorActor) != 2) return ERR_MortarSupplyState.PENDING;
// Preserve the existing earliest activation delay, but it is not readiness.
if (now - m_Battery.SpawnedAt < 10000) return ERR_MortarSupplyState.PENDING;
if (!m_Allocated)
{
if (!group.GetGroupUtilityComponent() || !group.GetGroupUtilityComponent().m_VehicleMgr) return ERR_MortarSupplyState.PENDING;
SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(m_Battery.Gun.FindComponent(SCR_AIVehicleUsageComponent));
if (!usage || !group.GetGroupUtilityComponent().m_VehicleMgr.TryAddVehicle(usage)) return Fail("native support gun registration failed");
m_Members.Copy(physical); m_Battery.RadioOperator = operatorActor;
if (!Allocate()) return Fail("finite initial support shell allocation rejected; no retry");
return ERR_MortarSupplyState.PENDING; // never accept mutation-frame readiness
}
foreach (ERR_MortarInitialItem operation : m_Operations)
{
if (!operation.Finished) return ERR_MortarSupplyState.PENDING;
if (!operation.Succeeded) return Fail("finite initial support shell operation failed; no retry");
}
foreach (IEntity equipped : m_Members)
{
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(equipped.FindComponent(InventoryStorageManagerComponent));
int shells = m_Battery.InventoryShells(inventory);
if (equipped == operatorActor)
{
if (shells != 0) return Fail("dedicated initial manpack operator unexpectedly carries mortar shells");
}
else if (shells != 9) return ERR_MortarSupplyState.PENDING;
}
if (m_Battery.CountShells() != 27) return ERR_MortarSupplyState.PENDING;
m_Ready = true;
group.ActivateAI();
foreach (AIAgent readyAgent : agents)
{
if (readyAgent) { readyAgent.SetPermanentLOD(0); readyAgent.ActivateAI(); }
}
m_Battery.Audit("CREW READY", string.Format("four original physical members, one manpack, 27 confirmed HE; new shell requests=%1; allocation permanently closed", m_RequestedShells));
return ERR_MortarSupplyState.READY;
}
}
@@ -0,0 +1,16 @@
// One delivered HQ order drives a continuous native loading/firing cycle.
class ERR_MortarSalvo
{
static const int ROUNDS = 8;
static const float RADIUS_METRES = 40;
static const float TIMEOUT_MS = 120000;
static vector Offset(int site, int order, int shot)
{
// Stable throughout one ballistic solve; successive shells cover the disk
// instead of clustering on the same point or changing every iteration.
float radius = RADIUS_METRES * Math.Sqrt((shot + 1.0) / ROUNDS);
float angle = (site * 53 + order * 97 + shot * 137.5) * Math.DEG2RAD;
return Vector(Math.Sin(angle) * radius, 0, Math.Cos(angle) * radius);
}
}
@@ -0,0 +1,108 @@
class ERR_MortarSupplyCallback : ScriptedInventoryOperationCallback
{
ERR_MortarSupplyTransfer Transfer;
protected override void OnComplete() { if (Transfer) Transfer.Acknowledge(true); }
protected override void OnFailed() { if (Transfer) Transfer.Acknowledge(false); }
}
// Exact-item native transaction. Callbacks only record outcomes; the HQ tick
// authorizes progress after checking actual inventory ownership and the order.
class ERR_MortarSupplyTransfer
{
protected ERR_MortarBattery m_Battery;
protected IEntity m_Gun;
protected SCR_AIGroup m_Group;
protected IEntity m_Donor;
protected IEntity m_Gunner;
protected IEntity m_Shell;
protected InventoryStorageManagerComponent m_Source;
protected InventoryStorageManagerComponent m_Destination;
protected BaseInventoryStorageComponent m_Storage;
protected ref ERR_MortarSupplyCallback m_Callback;
protected int m_Order;
protected int m_Acknowledgement;
protected float m_Deadline;
protected bool m_Accepted;
protected bool m_Invalidated;
protected bool m_Resolved;
protected bool m_Ready;
void ERR_MortarSupplyTransfer(ERR_MortarBattery battery, IEntity donor, IEntity gunner, IEntity shell, BaseInventoryStorageComponent storage, float now)
{
m_Battery = battery; m_Gun = battery.Gun; m_Group = battery.Group;
m_Donor = donor; m_Gunner = gunner; m_Shell = shell; m_Storage = storage;
m_Order = battery.OrderId; m_Deadline = now + 8000;
m_Source = InventoryStorageManagerComponent.Cast(donor.FindComponent(InventoryStorageManagerComponent));
m_Destination = InventoryStorageManagerComponent.Cast(gunner.FindComponent(InventoryStorageManagerComponent));
}
static bool Authority(bool valid, bool invalidated, int capturedOrder, int currentOrder)
{
return valid && !invalidated && capturedOrder == currentOrder;
}
static bool Proven(bool callbackComplete, bool sourceContains, bool destinationContains, bool exactSlot)
{
return callbackComplete && !sourceContains && destinationContains && exactSlot;
}
protected bool Contains(InventoryStorageManagerComponent inventory)
{
if (!inventory || !m_Shell) return false;
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
return items.Contains(m_Shell);
}
protected bool Valid(float now)
{
if (!m_Battery || !Authority(m_Battery.SupplyAuthorized(now), m_Invalidated, m_Order, m_Battery.OrderId)) return false;
if (m_Battery.Gun != m_Gun || m_Battery.Group != m_Group || !m_Donor || !m_Gunner || m_Donor == m_Gunner || !m_Shell || !m_Source || !m_Destination || !m_Storage) return false;
if (!ERR_Actors.CanFight(m_Donor) || !ERR_Actors.CanFight(m_Gunner) || ERR_Actors.Group(m_Donor) != m_Group || ERR_Actors.Group(m_Gunner) != m_Group) return false;
Faction faction = m_Group.GetFaction();
if (SCR_FactionManager.SGetFaction(m_Donor) != faction || SCR_FactionManager.SGetFaction(m_Gunner) != faction || vector.Distance(m_Donor.GetOrigin(), m_Gunner.GetOrigin()) > 12) return false;
SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(m_Gun.FindComponent(SCR_AIVehicleUsageComponent));
if (!usage || !usage.GetTurretCompartmentSlot()) return false;
IEntity occupant = usage.GetTurretCompartmentSlot().GetOccupant();
return !occupant || occupant == m_Gunner;
}
void Acknowledge(bool success)
{
if (m_Acknowledgement != 0) return;
if (success) m_Acknowledgement = 1;
else m_Acknowledgement = -1;
}
bool Begin(float now)
{
if (m_Callback || !Replication.IsServer() || !Valid(now) || !Contains(m_Source) || Contains(m_Destination)) return false;
m_Callback = new ERR_MortarSupplyCallback(); m_Callback.Transfer = this;
// Do not use callback.GetItem(): the native contract excludes Move operations.
m_Accepted = m_Source.TryMoveItemToStorage(m_Shell, m_Storage, -1, m_Callback);
if (!m_Accepted) { Acknowledge(false); m_Resolved = true; }
return m_Accepted;
}
void Invalidate() { m_Invalidated = true; m_Ready = false; }
bool Unresolved() { return m_Accepted && !m_Resolved; }
int CapturedOrder() { return m_Order; }
ERR_MortarSupplyState Poll(float now)
{
if (!Replication.IsServer()) return ERR_MortarSupplyState.FAILED;
bool valid = Valid(now);
bool sourceContains = Contains(m_Source);
bool destinationContains = Contains(m_Destination);
bool exactSlot;
InventoryItemComponent item;
if (m_Shell) item = InventoryItemComponent.Cast(m_Shell.FindComponent(InventoryItemComponent));
if (item && item.GetParentSlot()) exactSlot = item.GetParentSlot().GetStorage() == m_Storage;
bool proven = Proven(m_Acknowledgement == 1, sourceContains, destinationContains, exactSlot);
if (proven || m_Acknowledgement < 0) m_Resolved = true;
// A successful callback without physical destination proof is ambiguous.
// Keep it reserved through timeout/cancellation; never start a second move.
if (!valid || now >= m_Deadline)
{
m_Invalidated = true; m_Ready = false;
return ERR_MortarSupplyState.FAILED;
}
if (proven)
{
m_Ready = true;
return ERR_MortarSupplyState.READY;
}
if (m_Acknowledgement < 0 || !m_Accepted) return ERR_MortarSupplyState.FAILED;
return ERR_MortarSupplyState.PENDING;
}
}
@@ -0,0 +1,244 @@
// Owned and ticked by HQ. Initial assets are authored once; losses are never replaced.
class ERR_MortarSystem
{
protected ERR_HQ m_HQ;
protected ref array<ref ERR_MortarBattery> m_Batteries = {};
protected ref ERR_SettlementSafety m_Settlements = new ERR_SettlementSafety();
protected bool m_Prepared;
protected bool m_Stopped;
protected float m_NextDecision;
string SafetyReason;
string SettlementReason;
void ERR_MortarSystem(ERR_HQ hq) { m_HQ = hq; }
static ERR_MortarSystem Get()
{
ERR_HQ hq = ERR_HQ.Get();
if (!hq || !Replication.IsServer()) return null;
return hq.Mortars();
}
static bool NearPlayer(vector position)
{
array<IEntity> players = {};
ERR_Actors.Players(players);
foreach (IEntity player : players)
if (vector.DistanceXZ(player.GetOrigin(), position) <= 1200) return true;
return false;
}
bool Prepare()
{
if (!Replication.IsServer() || m_Prepared || m_Stopped) return false;
m_Prepared = true;
vector position = ERR_Actors.Ground("6000 0 7000");
if (position[1] < 1) return false;
IEntity gun = ERR_Actors.Spawn(ERR_MortarBattery.GUN, position);
SCR_AIGroup group = SCR_AIGroup.Cast(ERR_Actors.Spawn(MortarGroup(), ERR_Actors.Ground(position + "0 0 4")));
if (!gun || !group)
{
ERR_Actors.DeleteSpawned(gun);
ERR_MortarReadiness.RetireGroup(group);
ERR_Actors.DeleteSpawned(group);
return false;
}
if (group.GetFaction() != ERR_GameMode.Get().EnemyFaction())
{
ERR_Actors.DeleteSpawned(gun);
ERR_MortarReadiness.RetireGroup(group);
ERR_Actors.DeleteSpawned(group);
return false;
}
FactionAffiliationComponent affiliation = FactionAffiliationComponent.Cast(gun.FindComponent(FactionAffiliationComponent));
if (affiliation) affiliation.SetAffiliatedFaction(ERR_GameMode.Get().EnemyFaction());
ERR_MortarBattery battery = new ERR_MortarBattery();
battery.Bind(1, group, gun, GetGame().GetWorld().GetWorldTime());
m_Batteries.Insert(battery);
ERR_GameMode mode = ERR_GameMode.Get();
mode.Own(gun);
mode.RegisterGroup(group);
m_HQ.ReserveGroup(group);
battery.Audit("DEPLOY", "authored gun and four-person crew; finite ammunition initialization pending");
return true;
}
static ResourceName MortarGroup() { return "{B84C05941C4C81B8}Prefabs/ERR/MortarCrew.et"; }
ERR_MortarBattery FindGun(IEntity gun)
{
foreach (ERR_MortarBattery battery : m_Batteries)
if (gun && battery.Gun == gun) return battery;
return null;
}
ERR_MortarBattery FindGroup(SCR_AIGroup group)
{
foreach (ERR_MortarBattery battery : m_Batteries)
if (group && battery.Group == group) return battery;
return null;
}
ERR_HQReport Latest(ERR_MortarBattery battery, float now)
{
// Only the coordinates actually delivered to this battery are available.
// A newer HQ contact cannot update a gun's knowledge without another downlink.
if (!battery || !ERR_MortarPrediction.Fresh(battery.Report, now)) return null;
return battery.Report;
}
string ContactFailure(ERR_MortarBattery battery)
{
if (!battery.Report) return "no delivered target report";
return "delivered target report expired or invalid";
}
bool OutsideSettlements(vector impact)
{
bool clear = m_Settlements.OutsideSettlements(impact);
SettlementReason = m_Settlements.SettlementReason;
return clear;
}
bool Safe(ERR_MortarBattery battery, vector impact, float flight)
{
SafetyReason = "clear";
if (!battery.Operational()) { SafetyReason = battery.OperationalReason(); return false; }
if (!OutsideSettlements(impact)) { SafetyReason = SettlementReason; return false; }
if (SCR_TerrainHelper.GetTerrainY(impact) < 0) { SafetyReason = "impact below Everon sea level"; return false; }
Faction faction = battery.Group.GetFaction();
if (!faction) { SafetyReason = "battery faction missing"; return false; }
array<IEntity> friendlies = {};
m_HQ.PhysicalForces(friendlies);
foreach (IEntity entity : friendlies)
{
Faction friendly = SCR_FactionManager.SGetFaction(entity);
if (!friendly || faction.IsFactionEnemy(friendly) || !ERR_Actors.Alive(entity)) continue;
vector velocity;
IEntity moving = CompartmentAccessComponent.GetVehicleIn(entity);
if (!moving) moving = entity;
if (moving.GetPhysics()) velocity = moving.GetPhysics().GetVelocity();
if (ERR_MortarPrediction.ThreatensFriendly(impact, entity.GetOrigin(), velocity, flight))
{
SafetyReason = "friendly physical force can enter the impact area";
return false;
}
}
return true;
}
bool Withhold(ERR_MortarBattery battery, string reason, string detail = "")
{
battery.LastFailure = reason + "; " + detail;
battery.Trace("WITHHELD", reason, detail);
// Finish the activity from the next HQ tick, never from inside its own node.
battery.Rejected = true;
return false;
}
bool AllowShot(ERR_MortarBattery battery)
{
float now = GetGame().GetWorld().GetWorldTime();
if (m_Stopped || !ERR_HQ.MissionActive()) return Withhold(battery, "mission inactive or HQ stopped");
if (!battery.Operational()) return Withhold(battery, battery.OperationalReason());
if (!battery.CommandOpen || battery.OrderShots >= ERR_MortarSalvo.ROUNDS) return Withhold(battery, "salvo complete or order closed");
if (battery.Released) return Withhold(battery, "waiting for committed projectile");
if (battery.AimedShot != battery.OrderShots || battery.AimedAt < 0 || now - battery.AimedAt > 10000) return Withhold(battery, "fresh aim solution required");
ERR_HQReport report = Latest(battery, now);
if (!report) return Withhold(battery, ContactFailure(battery));
vector updated;
if (!ERR_MortarPrediction.Predict(report, now, battery.FlightTime, updated)) return Withhold(battery, ERR_MortarPrediction.FailureReason);
updated += battery.AimOffset;
if (vector.DistanceXZ(updated, battery.Impact) > 60) return Withhold(battery, "predicted target left aimed impact area");
if (!OutsideSettlements(updated)) return Withhold(battery, SettlementReason);
if (!Safe(battery, battery.Impact, battery.FlightTime)) return Withhold(battery, SafetyReason);
return true;
}
protected void AdvanceOrder(ERR_MortarBattery battery, float now)
{
if (battery.RadioOrder)
{
int deliveredState = battery.RadioOrder.Advance(now, m_HQ.Journal());
if (deliveredState == 0) return;
ERR_HQReport delivered = battery.PendingRadioReport;
battery.RadioOrder = null;
battery.PendingRadioReport = null;
if (deliveredState < 0 || !ERR_MortarPrediction.Fresh(delivered, now) || !battery.Operational() || battery.Activity || !battery.CommandOpen)
{
battery.Cancel("radio delivery, report freshness or battery availability failed");
battery.NextOrder = now + 10000;
return;
}
battery.PendingSupplyReport = delivered;
}
if (!battery.PendingSupplyReport) return;
if (!battery.CommandOpen || !ERR_MortarPrediction.Fresh(battery.PendingSupplyReport, now) || !battery.Operational() || battery.Activity)
{
battery.Cancel("delivered order expired or became unavailable while awaiting physical ammunition");
battery.NextOrder = now + 10000;
return;
}
ERR_MortarSupplyState supply = battery.SupplyState(now);
if (supply == ERR_MortarSupplyState.PENDING) return;
if (supply == ERR_MortarSupplyState.FAILED)
{
battery.Cancel("physical gunner ammunition unavailable or transfer failed");
battery.NextOrder = now + 10000;
return;
}
ERR_HQReport ready = battery.PendingSupplyReport;
battery.PendingSupplyReport = null;
battery.Order(ready, now);
}
void Tick(float now)
{
if (m_Stopped || !Replication.IsServer()) return;
foreach (ERR_MortarBattery battery : m_Batteries)
{
if (battery.Rejected && !battery.Released)
{
battery.Cancel("native aim or firing authorization rejected");
battery.NextOrder = now + 10000;
}
battery.Rejected = false;
battery.Update(now);
AdvanceOrder(battery, now);
}
if (now < m_NextDecision) return;
m_NextDecision = now + 10000;
array<ref ERR_HQReport> reports = {};
m_HQ.SupportContacts(reports, now);
ERR_MortarBattery selected;
ERR_HQReport target;
float distance = float.MAX;
foreach (ERR_MortarBattery battery : m_Batteries)
{
if (!battery.StartupActivated || !battery.Operational() || battery.Activity || battery.RadioOrder || battery.PendingSupplyReport || battery.SupplyPending() || now < battery.NextOrder || battery.CountShells() == 0) continue;
foreach (ERR_HQReport report : reports)
{
float candidate = vector.DistanceXZ(battery.Position, report.Position);
if (candidate < 350 || candidate > 4000 || candidate >= distance || !OutsideSettlements(report.Position)) continue;
selected = battery;
target = report;
distance = candidate;
}
}
if (!selected || !target) return;
ERR_HQRoute route = m_HQ.Downlink(selected.Group, "MORTAR ORDER", target.Description(now), target.MessageId);
if (!route) return;
selected.BeginRequest(target, now);
selected.RadioId = route.MessageId;
selected.RadioOrder = route;
selected.PendingRadioReport = target.Snapshot();
m_NextDecision = now + 20000;
}
void AppendGuns(array<IEntity> entities)
{
foreach (ERR_MortarBattery battery : m_Batteries)
if (battery.Gun && !entities.Contains(battery.Gun)) entities.Insert(battery.Gun);
}
string Status()
{
int ready, shells;
foreach (ERR_MortarBattery battery : m_Batteries)
{
if (battery.StartupActivated && battery.Operational()) ready++;
shells += battery.CountShells();
}
return string.Format("mortars %1/%2; HE shells %3", ready, m_Batteries.Count(), shells);
}
void Stop()
{
m_Stopped = true;
foreach (ERR_MortarBattery battery : m_Batteries) battery.Stop();
}
}
@@ -0,0 +1,241 @@
#ifdef WORKBENCH
// Explicit synthetic observation only. Delivery, HQ scheduling and native fire
// are unchanged; this helper never writes directly into the HQ contact list.
modded class ERR_HQ
{
int ERR_QueueMortarFixtureReport(SCR_AIGroup source, IEntity target, vector position, float now)
{
if (!ERR_NativeMortarFiringProbe.Enabled() || !target || !m_Contacts.IsEmpty()) return 0;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != source || !unit.ReservedForSupport || !unit.Radio || unit.Uplink || unit.PendingReport) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!route || route.Nodes.IsEmpty()) return 0;
ERR_HQReport report = new ERR_HQReport();
report.MessageId = m_Journal.Message(); report.Target = target; report.Source = source;
report.Position = position; report.ObservedAt = now; report.DetailsObservedAt = now;
report.HasVelocity = true; report.Velocity = vector.Zero;
report.TravelMode = "on foot"; report.SeenEscapists = 1; report.SeenWeapons = "fixture observation";
route.MessageId = report.MessageId; route.Payload = "EXPLICIT SYNTHETIC OBSERVATION: " + report.Description(now);
unit.PendingReport = report; unit.Uplink = route;
m_Journal.Write("FIXTURE REPORT", route.Payload, report.MessageId);
return report.MessageId;
}
return 0;
}
void ERR_RemoveMortarFixtureReport(IEntity target)
{
if (!target) return;
for (int i = m_Contacts.Count() - 1; i >= 0; i--)
if (m_Contacts[i].Target == target) m_Contacts.Remove(i);
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.PendingReport && unit.PendingReport.Target == target) { unit.PendingReport = null; unit.Uplink = null; }
if ((unit.PendingOrder && unit.PendingOrder.Target == target) || (unit.Assignment && unit.Assignment.Target == target)) unit.Release();
}
}
}
// Observe only the actual native event. Node SUCCESS, accepted inventory moves
// and committed shell loading are never counted as physical projectiles.
modded class SCR_MortarMuzzleComponent
{
override void OnWeaponFired(IEntity effectEntity, BaseMuzzleComponent muzzle, IEntity projectileEntity)
{
ERR_NativeMortarFiringProbe probe = ERR_NativeMortarFiringProbe.Active();
if (probe) probe.NativeProjectile(GetOwner(), projectileEntity);
super.OnWeaponFired(effectEntity, muzzle, projectileEntity);
}
}
class ERR_NativeMortarFiringProbe
{
protected static ERR_NativeMortarFiringProbe s_Active;
protected ERR_GameMode m_Mode;
protected ERR_MortarBattery m_Battery;
protected IEntity m_Gun;
protected SCR_AIGroup m_Group;
protected IEntity m_Target;
protected vector m_Impact;
protected ref array<IEntity> m_Crew = {};
protected ref array<IEntity> m_InitialShells = {};
protected ref array<IEntity> m_Projectiles = {};
protected int m_Source;
protected int m_Order;
protected int m_Step;
protected int m_Events;
protected int m_StoppedShells;
protected float m_Deadline;
protected float m_NextDiagnostic;
protected float m_StopUntil;
protected bool m_Unsafe;
protected bool m_BadProjectile;
protected bool m_SawUplink;
protected bool m_SawDownlink;
protected bool m_SawActivity;
protected bool m_Stopped;
protected string m_BadReason;
static bool Enabled()
{
string enabled, outcome;
return Replication.IsServer() && System.GetCLIParam("errSmoke", enabled) && enabled == "1" && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "mortar-fire";
}
static ERR_NativeMortarFiringProbe Active() { return s_Active; }
void ERR_NativeMortarFiringProbe(ERR_GameMode mode)
{
m_Mode = mode;
m_Deadline = GetGame().GetWorld().GetWorldTime() + 180000;
if (Enabled() && !s_Active) s_Active = this;
}
protected bool Check(bool condition, string detail)
{
if (condition) { Print("ERR SMOKE PASS: mortar firing " + detail); return true; }
Print("ERR SMOKE FAIL: mortar firing " + detail, LogLevel.ERROR); Stop(); return false;
}
protected void Shells(out array<IEntity> shells)
{
shells.Clear();
foreach (IEntity actor : m_Crew)
{
if (!actor) continue;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
foreach (IEntity item : items)
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == ERR_MortarBattery.SHELL && !shells.Contains(item)) shells.Insert(item);
}
}
protected bool CheckNoOccupants(IEntity entity)
{
if (ChimeraCharacter.Cast(entity) || Vehicle.Cast(entity)) { m_Unsafe = true; return false; }
return true;
}
protected bool EmptyImpact(vector position)
{
m_Unsafe = false;
GetGame().GetWorld().QueryEntitiesByAABB(position - "200 5000 200", position + "200 5000 200", CheckNoOccupants, null, EQueryEntitiesFlags.ALL);
return !m_Unsafe;
}
protected bool SelectImpact(ERR_MortarSystem system)
{
// Bounded candidate survey: no clearance assumption from coordinates alone.
array<vector> offsets = {"-800 0 -600", "-600 0 -800", "0 0 -1000", "600 0 -800", "-1000 0 0", "800 0 -600", "-800 0 600", "0 0 1000"};
foreach (vector offset : offsets)
{
vector candidate = ERR_Actors.Ground(m_Battery.Position + offset);
if (candidate[1] < 1 || !EmptyImpact(candidate) || !system.Safe(m_Battery, candidate, 75)) continue;
bool clear = true;
for (int shot = 0; shot < ERR_MortarSalvo.ROUNDS; shot++)
{
vector spread = ERR_Actors.Ground(candidate + ERR_MortarSalvo.Offset(m_Battery.SiteId, m_Battery.OrderId + 1, shot));
if (!system.Safe(m_Battery, spread, 75)) { clear = false; break; }
}
if (!clear) continue;
m_Impact = candidate;
PrintFormat("ERR MORTAR FIXTURE IMPACT: position=%1 batteryDistance=%2; no characters/vehicles in 400m square; production settlement/friendly exclusions passed", candidate, vector.DistanceXZ(candidate, m_Battery.Position));
return true;
}
return false;
}
protected void Diagnose(float now)
{
if (now < m_NextDiagnostic) return;
m_NextDiagnostic = now + 5000;
if (!m_Battery) { Print("ERR MORTAR FIXTURE: waiting for one authored battery"); return; }
PrintFormat("ERR MORTAR FIXTURE: step=%1 startup=%2 source=M%3 observedEvents=%4 ready=%5 failure=%6", m_Step, m_Battery.StartupActivated, m_Source, m_Events, m_Battery.Operational(), m_Battery.SpawnFailure);
m_Battery.SiteStatus(now);
}
void NativeProjectile(IEntity gun, IEntity projectile)
{
if (m_Stopped || !m_Battery || gun != m_Gun) return;
if (!projectile) { m_BadProjectile = true; m_BadReason = "native fired event has no physical projectile"; return; }
if (m_Projectiles.Contains(projectile)) { m_BadProjectile = true; m_BadReason = "same physical projectile observed twice"; return; }
m_Projectiles.Insert(projectile); m_Events++;
float now = GetGame().GetWorld().GetWorldTime();
if (m_Step != 1 || !m_Battery.CommandOpen || !m_Battery.Released || m_Battery.SourceId != m_Source || m_Battery.AimedAt < 0 || now - m_Battery.AimedAt > 10000 || m_Battery.FlightTime <= 0)
{ m_BadProjectile = true; m_BadReason = "projectile lacks this delivered order and fresh native aim/commit"; }
PrintFormat("ERR MORTAR FIXTURE PROJECTILE: event=%1 entity=%2 origin=%3 order=%4 source=M%5 aimAge=%6 flight=%7; impact is not measured", m_Events, projectile, projectile.GetOrigin(), m_Battery.OrderId, m_Battery.SourceId, now - m_Battery.AimedAt, m_Battery.FlightTime);
}
int Tick(float now)
{
if (m_Stopped) return -1;
if (!Enabled() || s_Active != this || !m_Mode || !m_Mode.Active()) { Check(false, "explicit active fixture context retained"); return -1; }
ERR_HQ hq = ERR_HQ.Get();
ERR_MortarSystem system;
if (hq) system = hq.Mortars();
if (!system) { Check(false, "real HQ mortar service available"); return -1; }
if (!m_Battery)
{
array<IEntity> guns = {}; system.AppendGuns(guns);
if (guns.Count() == 1) { m_Gun = guns[0]; m_Battery = system.FindGun(m_Gun); }
}
Diagnose(now);
if (now >= m_Deadline) { Check(false, "bounded deadline; inspect readiness/route/activity/aim diagnostics"); return -1; }
if (m_BadProjectile) { Check(false, m_BadReason); return -1; }
if (!m_Battery) return 0;
if (!m_Battery.SpawnFailure.IsEmpty()) { Check(false, "battery startup failed: " + m_Battery.SpawnFailure); return -1; }
if (m_Step == 0)
{
if (!m_Battery.StartupActivated || !m_Battery.Operational() || !hq.MortarConnected(m_Battery.Group)) return 0;
m_Group = m_Battery.Group;
if (!Check(m_Group && m_Group.IsExpandComplete() && m_Group.GetAgentsCount() == 4 && m_Battery.TotalShots == 0 && m_Battery.OrderId == 0 && !m_Battery.CommandOpen && !m_Battery.Activity && !m_Battery.RadioOrder, "untasked original gun and complete four-person crew start without shots")) return -1;
array<AIAgent> agents = {}; m_Group.GetAgents(agents);
foreach (AIAgent agent : agents)
{
IEntity actor; if (agent) actor = agent.GetControlledEntity();
if (!Check(ERR_Actors.CanFight(actor) && !m_Crew.Contains(actor), "initial physical crew member is conscious and unique")) return -1;
m_Crew.Insert(actor);
}
if (!Check(m_Battery.RadioOperator && ERR_HQRadio.Capability(m_Battery.RadioOperator) == 2, "dedicated actual manpack supplies the radio route")) return -1;
Shells(m_InitialShells);
if (!Check(m_InitialShells.Count() == 27 && m_Battery.CountShells() == 27, "exactly 27 distinct physical initial HE shells")) return -1;
if (!Check(SelectImpact(system), "bounded candidate survey finds an unoccupied production-safe impact area")) return -1;
m_Target = ERR_Actors.Spawn(ERR_Resources.IntelFolder(), m_Impact);
if (!Check(m_Target != null, "fixture-owned inert report identity exists; no enemy perception is claimed")) return -1;
m_Source = hq.ERR_QueueMortarFixtureReport(m_Group, m_Target, m_Impact, now);
if (!Check(m_Source > 0, "synthetic observation enters actual existing radio uplink once")) return -1;
m_SawUplink = true; m_Deadline = now + 90000; m_Step = 1; return 0;
}
if (m_Battery.Gun != m_Gun || m_Battery.Group != m_Group) { Check(false, "original gun and crew identity retained"); return -1; }
if (!EmptyImpact(m_Impact)) { Check(false, "impact exclusion stays unoccupied before native firing/cancellation"); return -1; }
array<IEntity> remaining = {}; Shells(remaining);
foreach (IEntity item : remaining)
if (!m_InitialShells.Contains(item)) { Check(false, "no replacement HE shell appears after initialization"); return -1; }
if (m_Step == 1)
{
if (m_Battery.RadioOrder && m_Battery.SourceId == m_Source) { m_SawDownlink = true; m_Order = m_Battery.OrderId; }
if (m_Battery.Activity && m_Battery.Report && m_Battery.Report.MessageId == m_Source) m_SawActivity = true;
if (m_Battery.OrderId > 1 || (m_Battery.SourceId != 0 && m_Battery.SourceId != m_Source)) { Check(false, "one unchanged fixture source creates only one HQ order"); return -1; }
if (m_Events == 0) return 0;
if (!Check(m_Events == 1 && m_Battery.TotalShots == 1 && m_Battery.OrderShots == 1 && !m_Battery.Released && m_SawUplink && m_SawDownlink && m_SawActivity && m_Order == 1, "one physical projectile follows real uplink/downlink, native activity and fresh aim")) return -1;
if (!Check(remaining.Count() == 26 && m_Battery.CountShells() == 26, "one fired projectile consumes one of 27 original inventory shells")) return -1;
// Cancel on this later fixture tick, never reentrantly inside the firing node.
hq.ERR_RemoveMortarFixtureReport(m_Target);
system.Stop(); system.Stop();
if (!Check(!m_Battery.CommandOpen && !m_Battery.Activity && !m_Battery.RadioOrder, "explicit support Stop closes native order and route idempotently")) return -1;
m_StoppedShells = remaining.Count(); m_StopUntil = now + 12000; m_Deadline = m_StopUntil + 2000; m_Step = 2; return 0;
}
if (now < m_StopUntil) return 0;
if (!Check(m_Battery.TotalShots == 1 && m_Events == 1 && m_Battery.OrderId == m_Order && remaining.Count() == m_StoppedShells && !m_Battery.CommandOpen && !m_Battery.Activity && !m_Battery.RadioOrder, "stopped service issues no duplicate order, projectile or replenishment over 12 seconds")) return -1;
array<AIAgent> finalCrew = {}; m_Group.GetAgents(finalCrew);
if (!Check(finalCrew.Count() == 4 && m_Battery.Gun == m_Gun, "original group and gun retain four crew")) return -1;
foreach (AIAgent finalAgent : finalCrew)
if (!Check(finalAgent && m_Crew.Contains(finalAgent.GetControlledEntity()) && ERR_Actors.CanFight(finalAgent.GetControlledEntity()), "final conscious crew entity belongs to original physical roster")) return -1;
Stop(); return 1;
}
void Stop()
{
if (m_Stopped) return;
m_Stopped = true;
ERR_HQ hq = ERR_HQ.Get();
if (hq)
{
hq.ERR_RemoveMortarFixtureReport(m_Target);
if (m_Battery && m_Battery.SourceId == m_Source && m_Source > 0) m_Battery.Cancel("mortar firing fixture cleanup");
}
ERR_Actors.DeleteSpawned(m_Target); m_Target = null;
if (s_Active == this) s_Active = null;
}
void ~ERR_NativeMortarFiringProbe() { Stop(); }
}
#endif
@@ -0,0 +1,87 @@
#ifdef WORKBENCH
// Test access only: trigger the real delivered-order method on an existing
// registered squad. Radio transit is intentionally not simulated by this test.
modded class ERR_HQ
{
bool ERR_TestPatrolSearch(SCR_AIGroup group, out AIWaypoint search)
{
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != group) continue;
if (unit.Assignment || unit.PendingOrder || unit.Waypoint || !unit.Eligible(m_Mode)) return false;
ERR_HQReport order = new ERR_HQReport();
order.Position = group.GetOrigin() + "40 0 0";
order.ObservedAt = GetGame().GetWorld().GetWorldTime();
order.MessageId = m_Journal.Message();
unit.PendingOrder = order;
DeliverOrder(unit, order.ObservedAt);
search = unit.Waypoint;
return search && unit.Assignment == order;
}
return false;
}
bool ERR_TestPatrolRelease(SCR_AIGroup group, AIWaypoint search)
{
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Group != group || unit.Waypoint != search) continue;
unit.Release();
return !unit.Assignment && !unit.PendingOrder && !unit.Waypoint;
}
return false;
}
}
class ERR_NativePatrolHQProbe
{
protected ERR_GameMode m_Mode;
protected ERR_SiteRuntime m_Site;
protected AIWaypoint m_Search;
protected ref array<AIWaypoint> m_Baseline = {};
protected int m_Step;
protected float m_Wait;
void ERR_NativePatrolHQProbe(ERR_GameMode mode) { m_Mode = mode; }
protected bool Check(bool condition, string detail)
{
if (condition) { Print("ERR SMOKE PASS: patrol HQ " + detail); return true; }
Print("ERR SMOKE FAIL: patrol HQ " + detail, LogLevel.ERROR); return false;
}
int Tick(float now)
{
if (now < m_Wait) return 0;
ERR_HQ hq = ERR_HQ.Get();
if (!Check(hq != null, "real HQ available")) return -1;
if (m_Step == 0)
{
m_Site = m_Mode.Sites().Find("everon-outpost-1");
if (!Check(m_Site && m_Site.Group && m_Site.PatrolCycle, "existing outpost route available")) return -1;
m_Site.Group.GetWaypoints(m_Baseline);
if (!Check(!m_Baseline.IsEmpty() && hq.ERR_TestPatrolSearch(m_Site.Group, m_Search), "real delivered-order method assigns existing squad")) return -1;
m_Step = 1; m_Wait = now + 750; return 0;
}
if (m_Step == 1)
{
array<AIWaypoint> queue = {};
m_Site.Group.GetWaypoints(queue);
if (!Check(m_Search && !queue.IsEmpty() && queue[0] == m_Search && m_Site.Group.GetCurrentWaypoint() == m_Search, "Search preempts native patrol")) return -1;
foreach (AIWaypoint waypoint : m_Baseline)
if (!Check(queue.Contains(waypoint), "preempted baseline route remains queued")) return -1;
if (!Check(hq.ERR_TestPatrolRelease(m_Site.Group, m_Search), "real HQ release removes only its assignment")) return -1;
m_Step = 2; m_Wait = now + 750; return 0;
}
if (m_Step == 2)
{
AIWaypoint current = m_Site.Group.GetCurrentWaypoint();
if (!Check(current && (current == m_Site.PatrolCycle || m_Site.PatrolWaypoints.Contains(current)), "native patrol resumes after Search release")) return -1;
m_Step = 3; return 1;
}
return 1;
}
void Stop()
{
ERR_HQ hq = ERR_HQ.Get();
if (hq && m_Site && m_Search) hq.ERR_TestPatrolRelease(m_Site.Group, m_Search);
}
void ~ERR_NativePatrolHQProbe() { Stop(); }
}
#endif
@@ -0,0 +1,63 @@
// Vanilla named settlements supply exclusion areas; no original mission location system.
// Shared town/village exclusion for mortar impacts, roadblocks and mine sites.
// Fixed distance from mapped settlement centres, independent of mission
// activation radii. Scattered buildings and props are not settlements.
class ERR_SettlementSafety
{
static const float RADIUS = 200;
string SettlementReason;
protected vector m_SafeImpact;
protected bool m_SettlementNear;
protected vector m_LastSettlementImpact;
protected float m_LastSettlementCheck = -1;
protected bool m_LastSettlementClear;
bool OutsideSettlements(vector impact)
{
float now = GetGame().GetWorld().GetWorldTime();
if (m_LastSettlementCheck >= 0 && now >= m_LastSettlementCheck && now - m_LastSettlementCheck < 1000 && vector.DistanceXZ(impact, m_LastSettlementImpact) == 0)
return m_LastSettlementClear;
m_LastSettlementCheck = now;
m_LastSettlementImpact = impact;
m_LastSettlementClear = false;
m_SafeImpact = impact;
m_SettlementNear = false;
SettlementReason = "clear";
// Also cover named native map settlements, independent of whether the
// mission placed a garrison marker there. Generic building entities also
// include deer stands, bridge pillars, rubble and electrical cabinets.
// Broad vertical bounds keep the 200m distance horizontal on hills.
GetGame().GetWorld().QueryEntitiesByAABB(impact - Vector(RADIUS, 5000, RADIUS), impact + Vector(RADIUS, 5000, RADIUS), CheckSettlement, FilterSettlement, EQueryEntitiesFlags.ALL);
m_LastSettlementClear = !m_SettlementNear;
return m_LastSettlementClear;
}
protected bool FilterSettlement(IEntity entity)
{
return entity && entity.FindComponent(MapDescriptorComponent);
}
protected bool CheckSettlement(IEntity entity)
{
float radius;
MapDescriptorComponent descriptor = MapDescriptorComponent.Cast(entity.FindComponent(MapDescriptorComponent));
if (descriptor)
{
int type = descriptor.GetBaseType();
if (type == EMapDescriptorType.MDT_NAME_CITY)
radius = RADIUS;
else if (type == EMapDescriptorType.MDT_NAME_TOWN)
radius = RADIUS;
else if (type == EMapDescriptorType.MDT_NAME_VILLAGE || type == EMapDescriptorType.MDT_NAME_SETTLEMENT)
radius = RADIUS;
}
if (radius > 0 && vector.DistanceXZ(m_SafeImpact, entity.GetOrigin()) <= radius)
{
m_SettlementNear = true;
SettlementReason = string.Format("named map settlement entity=%1 position=%2 distance=%3m exclusion=%4m", entity, entity.GetOrigin(), vector.DistanceXZ(m_SafeImpact, entity.GetOrigin()), radius);
return false;
}
return true;
}
}
@@ -0,0 +1,9 @@
modded class ERR_ScenarioComponent
{
protected override bool PrepareAdditionalForces()
{
if (!super.PrepareAdditionalForces()) return false;
ERR_HQ hq = ERR_HQ.Get();
return hq && hq.PrepareSupport();
}
}
@@ -0,0 +1,9 @@
GameProject {
ID "ERR_Ai"
GUID "5192138CB9D5B911"
TITLE "Escapists Rereintroduced - Ai"
Dependencies {
"58D0FB3206B6F859"
"2528466DE220D91C"
}
}
@@ -0,0 +1,11 @@
SCR_MissionHeader {
World "{B6C516F86302C679}Worlds/ERR_Everon.ent"
SystemsConfig "{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf"
m_sName "Rereintroduced: Everon (development)"
m_sAuthor "Rereintroduced contributors"
m_sDescription "Independent escape prototype. Development scenario; runtime validation in progress."
m_sGameMode "Escape"
m_iPlayerCount 12
m_eSaveTypes 0
m_bShowInScenarioMenu 1
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{C1E20667DCE324ED}Missions/ERR_Everon.conf"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,36 @@
// Companion-specific commands extend Core's authenticated transport.
modded class ERR_AdminService
{
protected override string Setting(string section, string option)
{
if (section == "hq")
{
if (option == "interval") return "reportIntervalSeconds";
if (option == "squads") return "supportSquadLimit";
if (option == "radius") return "responseRadiusMetres";
}
if (section == "intel")
{
if (option == "carrying") return "aiIntelChancePercent";
}
return super.Setting(section, option);
}
protected override bool Extension(ERR_GameMode mode, string arguments, array<string> replies)
{
if (arguments != "status" && arguments != "hq show" && arguments != "hq log") return super.Extension(mode, arguments, replies);
ERR_HQ hq = ERR_HQ.Cast(mode.Command());
if (!hq) { replies.Insert("HQ unavailable"); return true; }
if (arguments == "hq show" || arguments == "status") replies.Insert(hq.Status());
else
{
int cursor;
hq.Journal().Read(Math.Max(0, hq.Journal().Sequence() - 8), replies, cursor);
if (replies.IsEmpty()) replies.Insert("HQ journal is empty.");
}
return true;
}
protected override string Help()
{
return super.Help() + " | hq show|log | hq interval|squads|radius show|set N | intel carrying show|set N";
}
}
@@ -0,0 +1,10 @@
#ifdef WORKBENCH
modded class ERR_MortarSystem
{
ERR_MortarBattery ERR_ProbeBattery()
{
if (m_Batteries.Count() != 1) return null;
return m_Batteries[0];
}
}
#endif
@@ -0,0 +1,114 @@
// Opt-in engine fixture: physical radios and production delivery routes only.
#ifdef WORKBENCH
modded class ERR_HQ
{
vector ERR_ProbeResponseOrigin()
{
foreach (ERR_HQUnit unit : m_Units)
if (!unit.ReservedForSupport && unit.Group) return unit.Group.GetOrigin() + "0 0 20";
return vector.Zero;
}
bool ERR_ProbeDeliveredResponse()
{
foreach (ERR_HQUnit unit : m_Units)
if (unit.Assignment && unit.Waypoint && unit.Group != unit.Assignment.Source) return true;
return false;
}
bool ERR_ProbeUniqueAssignments()
{
array<AIWaypoint> waypoints = {};
foreach (ERR_HQUnit unit : m_Units)
{
if (!unit.Waypoint) continue;
if (!unit.Assignment || waypoints.Contains(unit.Waypoint)) return false;
waypoints.Insert(unit.Waypoint);
}
return waypoints.Count() > 0 && Assigned() <= m_Mode.Settings().Get("supportSquadLimit");
}
string ERR_ProbePerception()
{
int targets, sightings, radios;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.Radio) radios++;
if (!unit.Utility) continue;
array<ref ERR_HQVisualContact> samples = {};
ERR_HQObservation.Gather(unit.Utility, GetGame().GetWorld().GetWorldTime(), samples);
sightings += samples.Count();
if (unit.Utility.m_Perception) targets += unit.Utility.m_Perception.m_aTargets.Count();
}
return string.Format("%1; radios=%2 targets=%3 fresh visual samples=%4", Status(), radios, targets, sightings);
}
ERR_HQRoute ERR_ProbeRoute(IEntity carrier = null, bool downlink = false)
{
if (carrier) return m_Network.Route(carrier, downlink);
foreach (ERR_HQUnit unit : m_Units)
if (unit.Radio) return m_Network.Route(unit.Radio, downlink);
return null;
}
bool ERR_ProbeSquadsReady()
{
int infantry;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.ReservedForSupport) continue;
infantry++;
if (!unit.Group || ERR_HQRadio.Capability(unit.Radio) != 2) return false;
array<AIAgent> agents = {};
unit.Group.GetAgents(agents);
if (agents.Count() != 6) return false;
}
return infantry == 6;
}
}
class ERR_NativeRadioProbe
{
protected ref ERR_HQRoute m_Route;
protected IEntity m_Carrier;
protected int m_Step;
int Tick(ERR_HQ hq, float now)
{
if (!hq) return -1;
if (m_Step == 0)
{
if (!hq.ERR_ProbeSquadsReady()) return 0;
Print("ERR SMOKE PASS: six physical six-person squads each have a manpack operator");
m_Route = hq.ERR_ProbeRoute();
if (!m_Route || m_Route.Nodes.IsEmpty()) return -1;
m_Carrier = m_Route.Nodes[0].Carrier;
m_Route.MessageId = hq.Journal().Message();
m_Step = 1;
}
int result = m_Route.Advance(now, hq.Journal());
if (result == 0) return 0;
if (m_Step == 3)
{
if (result >= 0) return -1;
Print("ERR SMOKE PASS: removing receiving manpack interrupts an in-flight HQ order");
return 1;
}
if (result < 0) return -1;
if (m_Step == 1) Print("ERR SMOKE PASS: physical manpack uplink delivers to HQ");
if (m_Step == 2) Print("ERR SMOKE PASS: HQ downlink delivers to a physical receiver");
m_Route = hq.ERR_ProbeRoute(m_Carrier, true);
if (!m_Route || m_Route.Nodes.IsEmpty()) return -1;
m_Route.MessageId = hq.Journal().Message();
m_Step++;
if (m_Step == 3)
{
// Start HQ transmission, then remove the actual receiving equipment.
if (m_Route.Advance(now, hq.Journal()) != 0) return -1;
IEntity receiver = m_Route.Nodes[0].Carrier;
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(receiver.FindComponent(InventoryStorageManagerComponent));
if (!inventory) return -1;
array<IEntity> items = {};
inventory.GetItems(items);
foreach (IEntity item : items)
if (item && item.FindComponent(BaseRadioComponent)) SCR_EntityHelper.DeleteEntityAndChildren(item);
}
return 0;
}
}
#endif
@@ -0,0 +1,434 @@
// Explicit, local Workbench diagnostic only. Never compiled into game/server builds.
#ifdef WORKBENCH
modded class ERR_GameMode
{
protected bool m_ERRTestPatrolHQ;
protected ref ERR_NativePatrolProbe m_ERRHQPatrolMovement;
protected ref ERR_NativePatrolHQProbe m_ERRHQPatrolOrder;
protected int m_ERRSmokeStep;
protected float m_ERRSmokeDeadline;
protected float m_ERRSmokeWait;
protected IEntity m_ERRSmokePlayer;
protected BaseDoorComponent m_ERRGate;
protected ERR_LocationComponent m_ERRSmokeRadio;
protected bool m_ERRSmokeDone;
protected bool m_ERRTestLostHelicopter;
protected bool m_ERRTestPlayerDeath;
protected bool m_ERRTestRadioNetwork;
protected bool m_ERRTestHQResponse;
protected bool m_ERRTestMortar;
protected bool m_ERRTestMortarFire;
protected ref ERR_NativeMortarFiringProbe m_ERRMortarFire;
protected float m_ERRNextProbeLog;
protected ref ERR_NativeRadioProbe m_ERRRadioProbe;
protected ref array<IEntity> m_ERRCacheFolders = {};
protected override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
string enabled;
if (SCR_Global.IsEditMode() || !Replication.IsServer() || !System.GetCLIParam("errSmoke", enabled) || enabled != "1") return;
string outcome;
m_ERRTestLostHelicopter = System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "lost-helicopter";
m_ERRTestRadioNetwork = outcome == "radio-network";
m_ERRTestHQResponse = outcome == "hq-response";
m_ERRTestMortar = outcome == "mortar-inventory";
m_ERRTestMortarFire = outcome == "mortar-fire";
m_ERRTestPatrolHQ = outcome == "patrol-hq";
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar;
m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000;
if (m_ERRTestMortarFire) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 330000;
if (m_ERRTestPatrolHQ) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 420000;
OnStop().Insert(ERR_StopHQPatrol);
OnPhaseChanged().Insert(ERR_SmokePhase);
GetGame().GetCallqueue().CallLater(ERR_SmokeTick, 500, true);
Print("ERR SMOKE: scripted integration test enabled; gameplay acceptance remains separate");
}
protected bool ERR_Check(bool condition, string name)
{
if (condition) { Print("ERR SMOKE PASS: " + name); return true; }
ERR_StopHQPatrol();
Print("ERR SMOKE FAIL: " + name, LogLevel.ERROR);
m_ERRSmokeDone = true;
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
return false;
}
protected void ERR_StopHQPatrol()
{
if (m_ERRMortarFire) m_ERRMortarFire.Stop();
if (m_ERRHQPatrolMovement) m_ERRHQPatrolMovement.Stop();
if (m_ERRHQPatrolOrder) m_ERRHQPatrolOrder.Stop();
}
protected void ERR_MovePlayer(vector position)
{
vector transform[4];
m_ERRSmokePlayer.GetWorldTransform(transform);
transform[3] = ERR_Actors.Ground(position);
ChimeraCharacter.Cast(m_ERRSmokePlayer).Teleport(transform);
}
protected ERR_UnlockPrisonAction ERR_FindLock(IEntity entity)
{
BaseActionsManagerComponent manager = BaseActionsManagerComponent.Cast(entity.FindComponent(BaseActionsManagerComponent));
if (manager)
{
array<BaseUserAction> actions = {};
manager.GetActionsList(actions);
foreach (BaseUserAction action : actions)
{
ERR_UnlockPrisonAction lock = ERR_UnlockPrisonAction.Cast(action);
if (lock) return lock;
}
}
IEntity child = entity.GetChildren();
while (child)
{
ERR_UnlockPrisonAction lock = ERR_FindLock(child);
if (lock) return lock;
child = child.GetSibling();
}
return null;
}
protected void ERR_SmokePhase(ERR_Phase previous, ERR_Phase current)
{
if (m_ERRSmokeDone || !ERR_MissionRules.Terminal(current)) return;
if (m_ERRTestMortarFire)
{
if (!ERR_Check(current == ERR_Phase.DEFEAT && m_ERRSmokeStep == 151, "native mortar first shot and stop complete before explicit reset")) return;
m_ERRSmokeDone = true;
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
ERR_StopHQPatrol();
Print("ERR SMOKE COMPLETE: native HQ radio to first mortar projectile and explicit stop; fixture reset requested");
return;
}
if (m_ERRTestPatrolHQ)
{
if (!ERR_Check(current == ERR_Phase.DEFEAT && m_ERRSmokeStep == 133, "HQ patrol preemption and physical resumption before explicit reset")) return;
m_ERRSmokeDone = true;
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
Print("ERR SMOKE COMPLETE: native HQ patrol preemption and physical resumption");
return;
}
if (m_ERRTestPlayerDeath)
{
if (!ERR_Check(current == ERR_Phase.DEFEAT && m_ERRSmokeStep == 91, "death exhausts round life and reaches defeat after spectator grace")) return;
}
else if (m_ERRTestLostHelicopter)
{
if (!ERR_Check(current == ERR_Phase.DEFEAT && m_ERRSmokeStep == 8, "lost extraction helicopter causes defeat")) return;
}
else if (!ERR_Check(current == ERR_Phase.VICTORY && m_ERRSmokeStep == 7, "scripted escape reaches victory after physical vehicle occupancy")) return;
m_ERRSmokeDone = true;
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
PrintFormat("ERR SMOKE COMPLETE: terminal=%1 lostHelicopterCase=%2 playerDeathCase=%3", current, m_ERRTestLostHelicopter, m_ERRTestPlayerDeath);
GetGame().GetCallqueue().CallLater(ERR_EndScreenshot, 4000);
}
protected bool ERR_CheckRoster()
{
ERR_PlayerRoster roster = new ERR_PlayerRoster();
UUID first = "00e77100-0000-0000-0000-000000000101";
UUID second = "00e77100-0000-0000-0000-000000000202";
if (!ERR_Check(roster.Bind(101, first) && roster.CanEnter(101, ERR_Phase.PRISON), "new identity may enter prison")) return false;
roster.Spawned(101, m_ERRSmokePlayer);
if (!ERR_Check(!roster.CanEnter(101, ERR_Phase.PRISON), "spawn consumes identity life")) return false;
roster.Disconnect(101);
if (!ERR_Check(roster.HasSurvivor() && !roster.Get(101), "disconnect retains living actor and clears connection")) return false;
if (!ERR_Check(roster.Bind(202, first) && !roster.CanEnter(202, ERR_Phase.PRISON), "reconnected identity retains spent life")) return false;
if (!ERR_Check(!roster.Bind(303, first), "duplicate active identity rejected")) return false;
if (!ERR_Check(roster.Bind(101, second) && roster.CanEnter(101, ERR_Phase.RADIO_DEFENCE) && !roster.CanEnter(101, ERR_Phase.EXTRACTION), "recycled connection receives independent life and extraction admission policy")) return false;
return true;
}
protected bool ERR_CheckCompanionCommands()
{
array<string> replies = {};
array<string> commands = {"hq interval show", "hq squads show", "hq radius show", "intel carrying show", "intel reveal show"};
array<string> keys = {"reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent"};
for (int i = 0; i < commands.Count(); i++)
{
Admin().Execute(this, true, commands[i], replies);
if (!ERR_Check(replies.Count() == 1 && replies[0] == keys[i] + "=" + Settings().Get(keys[i]).ToString(), "companion command retained: " + commands[i])) return false;
}
Admin().Execute(this, false, "hq log", replies);
if (!ERR_Check(replies.Count() == 1 && replies[0] == "Administrator access required.", "companion journal is behind Core admin authorization")) return false;
Admin().Execute(this, true, "hq show", replies);
ERR_HQ hq = ERR_HQ.Cast(Command());
if (!ERR_Check(hq && replies.Count() == 1 && replies[0] == hq.Status(), "companion HQ status uses the shared command service")) return false;
return true;
}
protected void ERR_PrisonScreenshot() { System.MakeScreenshot("$logs:err-prison"); }
protected void ERR_EndScreenshot() { System.MakeScreenshot("$logs:err-result"); }
protected void ERR_SmokeTick()
{
float now = GetWorld().GetWorldTime();
if (m_ERRSmokeDone) return;
if (now > m_ERRSmokeDeadline) { ERR_Check(false, "timeout at step " + m_ERRSmokeStep.ToString()); return; }
if (now < m_ERRSmokeWait) return;
if (m_ERRSmokeStep == 150)
{
int result = m_ERRMortarFire.Tick(now);
if (result < 0) { ERR_Check(false, "native mortar firing probe failed; see diagnostics"); return; }
if (result == 1) { m_ERRSmokeStep = 151; Transition(ERR_Phase.DEFEAT); }
return;
}
if (m_ERRSmokeStep == 130 || m_ERRSmokeStep == 132)
{
int result = m_ERRHQPatrolMovement.Tick(now);
if (result < 0) { ERR_StopHQPatrol(); GetGame().GetCallqueue().Remove(ERR_SmokeTick); return; }
if (result == 1)
{
if (m_ERRSmokeStep == 130) { m_ERRHQPatrolOrder = new ERR_NativePatrolHQProbe(this); m_ERRSmokeStep = 131; }
else { m_ERRSmokeStep = 133; Transition(ERR_Phase.DEFEAT); }
}
return;
}
if (m_ERRSmokeStep == 131)
{
int result = m_ERRHQPatrolOrder.Tick(now);
if (result < 0) { ERR_StopHQPatrol(); GetGame().GetCallqueue().Remove(ERR_SmokeTick); return; }
if (result == 1) { m_ERRHQPatrolMovement = new ERR_NativePatrolProbe(this); m_ERRSmokeStep = 132; }
return;
}
if (m_ERRSmokeStep == 0)
{
array<IEntity> players = {};
ERR_Actors.Players(players, true);
if (players.Count() != 1 || Phase() != ERR_Phase.PRISON) return;
m_ERRSmokePlayer = players[0];
if (!ERR_CheckRoster() || !ERR_NativeContractsProbe.Run(this, m_ERRSmokePlayer) || !ERR_CheckCompanionCommands()) return;
if (m_ERRTestPatrolHQ)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRHQPatrolMovement = new ERR_NativePatrolProbe(this);
m_ERRSmokeStep = 130;
return;
}
if (m_ERRTestMortarFire)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRMortarFire = new ERR_NativeMortarFiringProbe(this);
m_ERRSmokeStep = 150;
return;
}
if (m_ERRTestMortar)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRSmokeStep = 120;
return;
}
if (m_ERRTestHQResponse)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRSmokeStep = 110;
return;
}
if (m_ERRTestRadioNetwork)
{
m_ERRRadioProbe = new ERR_NativeRadioProbe();
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRSmokeStep = 100;
return;
}
if (m_ERRTestPlayerDeath)
{
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent)).Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
return;
}
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
if (!ERR_Check(vector.DistanceXZ(m_ERRSmokePlayer.GetOrigin(), PrisonPosition()) < 5, "initial prisoner position")) return;
foreach (ERR_LocationComponent location : m_Locations)
if (location.Kind() == ERR_LocationKind.RADIO) m_ERRSmokeRadio = location;
if (!ERR_Check(m_ERRSmokeRadio && ERR_Actors.Alive(ExtractionVehicle()), "radio and extraction vehicle exist")) return;
ERR_UnlockPrisonAction lock;
foreach (IEntity tracked : m_OwnedEntities)
{
if (tracked) lock = ERR_FindLock(tracked);
if (lock) break;
}
if (!ERR_Check(lock != null, "authored gate exposes lock action")) return;
ERR_MovePlayer(lock.GetOwner().GetOrigin() + "1 0 1");
vector gateLow, gateHigh;
lock.GetOwner().GetWorldBounds(gateLow, gateHigh);
PrintFormat("ERR GEOMETRY: gate low=%1 high=%2", gateLow, gateHigh);
IEntity wall = lock.GetOwner().GetParent().GetChildren();
while (wall)
{
vector wallLow, wallHigh;
wall.GetWorldBounds(wallLow, wallHigh);
PrintFormat("ERR GEOMETRY: child origin=%1 low=%2 high=%3", wall.GetOrigin(), wallLow, wallHigh);
wall = wall.GetSibling();
}
GetGame().GetCallqueue().CallLater(ERR_PrisonScreenshot, 2000);
if (!ERR_Check(lock.CanBePerformedScript(m_ERRSmokePlayer), "lock permits prisoner")) return;
m_ERRGate = BaseDoorComponent.Cast(lock.GetOwner().FindComponent(BaseDoorComponent));
lock.PerformAction(lock.GetOwner(), m_ERRSmokePlayer);
if (!ERR_Check(Phase() == ERR_Phase.RADIO_SEARCH, "lock action advances mission")) return;
array<IEntity> cacheStock = {};
ERR_Inventory.Items(InventoryStorageManagerComponent.Cast(Sites().Find("everon-supply-1").Container.FindComponent(InventoryStorageManagerComponent)), cacheStock);
foreach (IEntity tracked : cacheStock)
{
if (tracked && tracked.GetPrefabData() && tracked.GetPrefabData().GetPrefabName() == ERR_Resources.ObjectiveDocument()) m_ERRCacheFolders.Insert(tracked);
}
if (!ERR_Check(m_ERRCacheFolders.Count() == 2, "two guaranteed physical cache documents")) return;
if (!ERR_Check(m_Settings.Set("aiIntelChancePercent", 0), "test does not rely on random intel")) return;
if (!ERR_Check(m_Settings.Set("radioDefenceSeconds", 30), "isolated test profile defence duration")) return;
m_ERRSmokeStep = 1;
}
else if (m_ERRSmokeStep == 1 || m_ERRSmokeStep == 2)
{
if (m_ERRSmokeStep == 2 && !ERR_Check(m_ERRGate && m_ERRGate.IsOpen() && m_ERRGate.CanCharacterPass(0.6), "unlocked gate physically permits passage")) return;
ERR_MovePlayer(Sites().Find("everon-supply-1").Container.GetOrigin() + "0 0 2");
SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_InventoryStorageManagerComponent));
InventoryStorageManagerComponent source = InventoryStorageManagerComponent.Cast(Sites().Find("everon-supply-1").Container.FindComponent(InventoryStorageManagerComponent));
BaseInventoryStorageComponent destination = inventory.FindStorageForItem(m_ERRCacheFolders[m_ERRSmokeStep - 1]);
if (!ERR_Check(destination && source.TryMoveItemToStorage(m_ERRCacheFolders[m_ERRSmokeStep - 1], destination), "authored cache document recovered into inventory")) return;
m_ERRSmokeStep++;
m_ERRSmokeWait = now + 2500;
}
else if (m_ERRSmokeStep == 3)
{
if (!ERR_Check(m_ERRSmokeRadio.Knowledge() == 2, "carried intel identifies radio through intel service")) return;
if (!ERR_Check(!TuneRadio(m_ERRSmokePlayer, m_ERRSmokeRadio), "radio rejects distant player")) return;
ERR_MovePlayer(m_ERRSmokeRadio.Position() + "2 0 0");
m_ERRSmokeStep = 30;
m_ERRSmokeWait = now + 1000;
}
else if (m_ERRSmokeStep == 30)
{
PrintFormat("ERR SMOKE: radio=%1 player=%2", m_ERRSmokeRadio.Position(), m_ERRSmokePlayer.GetOrigin());
if (!ERR_Check(TuneRadio(m_ERRSmokePlayer, m_ERRSmokeRadio), "identified radio starts defence")) return;
m_ERRSmokeStep = 4;
m_ERRSmokeWait = now + 3000;
}
else if (m_ERRSmokeStep == 4)
{
if (!ERR_Check(DefenceOccupied(), "occupied defence timer running")) return;
ERR_MovePlayer(m_ERRSmokeRadio.Position() + "90 0 0");
m_ERRSmokeStep = 5;
m_ERRSmokeWait = now + 2500;
}
else if (m_ERRSmokeStep == 5)
{
if (!ERR_Check(!DefenceOccupied() && Phase() == ERR_Phase.RADIO_DEFENCE, "leaving area resets defence")) return;
ERR_MovePlayer(m_ERRSmokeRadio.Position() + "2 0 0");
m_ERRSmokeStep = 6;
m_ERRSmokeWait = now + 33000;
}
else if (m_ERRSmokeStep == 6)
{
if (!ERR_Check(Phase() == ERR_Phase.EXTRACTION, "continuous occupied defence completes")) return;
if (m_ERRTestLostHelicopter)
{
m_ERRSmokeStep = 8;
ERR_Actors.DeleteSpawned(ExtractionVehicle());
return;
}
CompartmentAccessComponent access = CompartmentAccessComponent.Cast(m_ERRSmokePlayer.FindComponent(CompartmentAccessComponent));
BaseCompartmentSlot slot = access.FindFreeCompartment(ExtractionVehicle(), ECompartmentType.PILOT);
if (!ERR_Check(slot && access.GetInVehicle(ExtractionVehicle(), slot, true, -1, ECloseDoorAfterActions.INVALID, false), "boarding extraction vehicle")) return;
m_ERRSmokeStep = 7;
m_ERRSmokeWait = now + 3000;
}
else if (m_ERRSmokeStep == 120)
{
ERR_MortarBattery battery = ERR_MortarSystem.Get().ERR_ProbeBattery();
if (!battery || !battery.StartupActivated) return;
if (!ERR_Check(battery.Operational() && battery.Group.GetAgentsCount() == 4, "authored physical mortar and four-person crew initialize")) return;
if (!ERR_Check(ERR_HQRadio.Capability(battery.RadioOperator) == 2, "mortar has a dedicated physical manpack operator")) return;
if (!ERR_Check(battery.CountShells() == 27, "mortar starts with exactly 27 physical HE shells")) return;
array<AIAgent> agents = {};
battery.Group.GetAgents(agents);
foreach (AIAgent agent : agents)
{
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(agent.GetControlledEntity().FindComponent(InventoryStorageManagerComponent));
array<IEntity> items = {};
ERR_Inventory.Items(inventory, items);
foreach (IEntity item : items)
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == ERR_MortarBattery.SHELL) SCR_EntityHelper.DeleteEntityAndChildren(item);
}
m_ERRSmokeStep = 121;
m_ERRSmokeWait = now + 15000;
}
else if (m_ERRSmokeStep == 121)
{
ERR_MortarBattery battery = ERR_MortarSystem.Get().ERR_ProbeBattery();
if (!ERR_Check(battery.CountShells() == 0 && battery.TotalShots == 0, "depleted mortar inventory stays empty without fabricated ammunition")) return;
ERR_Actors.DeleteSpawned(battery.Gun);
ERR_Actors.DeleteSpawned(battery.Group);
m_ERRSmokeStep = 122;
m_ERRSmokeWait = now + 12000;
}
else if (m_ERRSmokeStep == 122)
{
ERR_MortarBattery battery = ERR_MortarSystem.Get().ERR_ProbeBattery();
if (!ERR_Check(battery && !battery.Gun && !battery.Group && !battery.Operational(), "lost mortar and crew remain lost without replacement spawning")) return;
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
damage.EnableDamageHandling(true);
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 110)
{
ERR_HQ hq = ERR_HQ.Cast(Command());
if (!hq || !hq.ERR_ProbeSquadsReady()) return;
ERR_MovePlayer(hq.ERR_ProbeResponseOrigin());
m_ERRSmokeStep = 111;
m_ERRSmokeWait = now + 1000;
}
else if (m_ERRSmokeStep == 111)
{
ERR_HQ hq = ERR_HQ.Cast(Command());
if (now >= m_ERRNextProbeLog)
{
Print("ERR HQ PROBE: " + hq.ERR_ProbePerception());
m_ERRNextProbeLog = now + 10000;
}
if (!hq.ERR_ProbeDeliveredResponse()) return;
if (!ERR_Check(true, "native visual contact reaches HQ and orders a different existing squad")) return;
if (!ERR_Check(hq.ERR_ProbeUniqueAssignments(), "HQ uses distinct waypoints within the existing force and order limits")) return;
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
damage.EnableDamageHandling(true);
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 100)
{
int result = m_ERRRadioProbe.Tick(ERR_HQ.Cast(Command()), now);
if (result == 0) return;
if (!ERR_Check(result == 1, "native radio delivery and interruption sequence")) return;
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
damage.EnableDamageHandling(true);
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 9)
{
SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
if (!ERR_Check(!ERR_Actors.Alive(m_ERRSmokePlayer), "native damage kills prisoner")) return;
if (!ERR_Check(controller && controller.ERR_ObserverState() == ERR_ObserverReason.SPENT_LIFE, "death selects spectator without another life")) return;
if (!ERR_Check(controller.ERR_HasObserverCamera() && SCR_ManualCamera.Cast(GetGame().GetCameraManager().CurrentCamera()), "spectator camera activates after native death")) return;
m_ERRSmokeStep = 91;
}
else if (m_ERRSmokeStep == 7)
{
if (!ERR_Check(CompartmentAccessComponent.GetVehicleIn(m_ERRSmokePlayer) == ExtractionVehicle(), "physical extraction occupancy")) return;
// Controlled transport tests the boundary detector, not piloting skill.
ExtractionVehicle().SetOrigin(m_EscapeCenter + Vector(m_EscapeRadius + 100, 300, 0));
m_ERRSmokeWait = now + 5000;
}
}
void ~ERR_GameMode()
{
if (GetGame())
{
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
GetGame().GetCallqueue().Remove(ERR_PrisonScreenshot);
GetGame().GetCallqueue().Remove(ERR_EndScreenshot);
}
}
}
#endif
@@ -0,0 +1,16 @@
#ifndef WORKBENCH
modded class ArmaReforgerScripted
{
override protected ResourceName ERR_DiagnosticHeader(string project)
{
if (project == "chat") return "{C1E20667DCE324ED}Missions/ERR_Everon.conf";
return super.ERR_DiagnosticHeader(project);
}
override protected string ERR_DiagnosticAddon(string project)
{
if (project == "chat") return "FA804F411BDDF2C6";
return super.ERR_DiagnosticAddon(project);
}
}
#endif
@@ -0,0 +1,51 @@
[WorkbenchPluginAttribute(name: "Validate Rereintroduced scenario", wbModules: {"WorldEditor"})]
class ERR_ValidateWorldPlugin : WorldEditorPlugin
{
protected bool m_Obstructed;
protected bool CheckClearance(IEntity entity)
{
if (entity && entity.GetVObject()) m_Obstructed = true;
return !m_Obstructed;
}
override void Run() { Validate(); }
override void RunCommandline() { Validate(); }
protected void Validate()
{
WorldEditor editor = Workbench.GetModule(WorldEditor);
if (!editor) { Print("ERR VALIDATION: World Editor missing", LogLevel.ERROR); return; }
WorldEditorAPI api = editor.GetApi();
if (!api) { Print("ERR VALIDATION: world API missing", LogLevel.ERROR); return; }
PrintFormat("ERR VALIDATION: prison terrain=%1, radio terrain=%2, extraction terrain=%3", api.GetTerrainSurfaceY(6090,7160), api.GetTerrainSurfaceY(6500,7200), api.GetTerrainSurfaceY(7000,7500));
for (int dx = -6; dx <= 6; dx += 3)
for (int dz = -6; dz <= 6; dz += 3)
PrintFormat("ERR TERRAIN: x=%1 z=%2 y=%3", 6090 + dx, 7160 + dz, api.GetTerrainSurfaceY(6090 + dx, 7160 + dz));
float bestSlope = 1000;
vector bestPosition;
for (int x = 5800; x <= 6200; x += 10)
{
for (int z = 6800; z <= 7200; z += 10)
{
float low = 10000;
float high = -10000;
for (int sx = -9; sx <= 9; sx += 3)
for (int sz = -15; sz <= 9; sz += 3)
{
float height = api.GetTerrainSurfaceY(x + sx, z + sz);
low = Math.Min(low, height);
high = Math.Max(high, height);
}
if (low > 5 && high - low < bestSlope)
{
m_Obstructed = false;
api.GetWorld().QueryEntitiesByAABB(Vector(x - 10, low + 0.1, z - 16), Vector(x + 10, high + 5, z + 10), CheckClearance);
if (m_Obstructed) continue;
bestSlope = high - low;
bestPosition = Vector(x, api.GetTerrainSurfaceY(x, z), z);
}
}
}
PrintFormat("ERR SITE CANDIDATE: position=%1 elevationRange=%2", bestPosition, bestSlope);
string play;
if (System.GetCLIParam("errPlay", play) && play == "1") editor.SwitchToGameMode();
}
}
@@ -0,0 +1,12 @@
GameProject {
ID "ERR_Chat"
GUID "FA804F411BDDF2C6"
TITLE "Escapists Rereintroduced - Chat"
Dependencies {
"58D0FB3206B6F859"
"2528466DE220D91C"
"5192138CB9D5B911"
"D31039C7C53E348A"
"9AAEE9041D79809E"
}
}
@@ -0,0 +1,136 @@
ERR_ScenarioDefinition {
MinimumRadioSources 2
Sites {
ERR_SiteDefinition {
Id "everon-prison-1"
Label "Prison"
Kind 0
Prefab "{BE6B8D56349038A6}Prefabs/ERR/Prison.et"
Position 6090 0 7160
Guarded 1
GuardOffset 35 0 0
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
ContainerOffset -4 0 0
Stock {
ERR_SiteStock { Prefab "{C0F7DD85A86B2900}Prefabs/Weapons/Handguns/PM/Handgun_PM.et" Count 5 }
ERR_SiteStock { Prefab "{8B853CDD11BA916E}Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et" Count 8 }
ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 }
}
}
ERR_SiteDefinition {
Id "everon-supply-1"
Label "Southern supply cache"
Kind 4
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
Position 6150 0 7050
Guarded 1
GuardOffset 18 0 0
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
ContainerOffset 0 0 0
Stock {
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 8 }
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 16 }
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
}
RevealOnEscape 1
}
ERR_SiteDefinition {
Id "everon-radio-1"
Label "Radio station"
DiscoverRadius 8
Kind 1
Prefab "{F7E7E3D6ACF0C860}Prefabs/ERR/Radio.et"
Position 6500 0 7200
Guarded 1
GuardOffset 30 0 0
}
ERR_SiteDefinition {
Id "everon-extraction-1"
Label "Initial helicopter pickup site"
Kind 2
Prefab "{033503110AC34EAC}Prefabs/ERR/Extraction.et"
Position 7000 0 7500
Guarded 1
GuardOffset 30 0 0
}
ERR_SiteDefinition {
Id "everon-supply-2"
Label "Western supply cache"
Kind 4
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
Position 5960 0 7220
Guarded 1
GuardOffset 16 0 0
Patrol {
ERR_SitePatrolPoint { Offset 18 0 0 }
ERR_SitePatrolPoint { Offset 18 0 24 }
ERR_SitePatrolPoint { Offset -6 0 24 }
ERR_SitePatrolPoint { Offset -6 0 0 }
}
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
DiscoverRadius 25
RevealOnEscape 1
Transport ERR_SiteTransport {
Prefab "{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et"
Offset 0 0 -8
Heading 180
ClearanceRadius 4
MaximumTerrainRange 1
}
Stock {
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 4 }
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 8 }
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 6 }
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
}
}
ERR_SiteDefinition {
Id "everon-medical-1"
Label "Medical stash"
Kind 4
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
Position 6340 0 7400
Guarded 0
GuardOffset 16 0 0
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
DiscoverRadius 25
RevealOnEscape 0
Stock {
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 6 }
ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 }
ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 3 }
}
}
ERR_SiteDefinition {
Id "everon-outpost-1"
Label "Eastern guard outpost"
Kind 3
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
Position 6740 0 7300
Guarded 1
GuardOffset 16 0 0
Patrol {
ERR_SitePatrolPoint { Offset 18 0 0 }
ERR_SitePatrolPoint { Offset 18 0 24 }
ERR_SitePatrolPoint { Offset -6 0 24 }
ERR_SitePatrolPoint { Offset -6 0 0 }
}
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
DiscoverRadius 35
RevealOnEscape 0
Stock {
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
}
Props {
ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset 0 0 -4 }
ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset -4 0 0 Angles 90 0 0 }
ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset 4 0 0 Angles 90 0 0 }
}
}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{BC310DC0CD27F523}Configs/ERR/EveronSites.conf"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,24 @@
SCR_EntityCatalogMultiList {
m_eEntityCatalogType VEHICLE
m_aMultiLists {
SCR_EntityCatalogMultiListEntry {
m_sIdentifier "Mission transport"
m_aEntities {
SCR_EntityCatalogEntry {
m_sEntityPrefab "{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et"
m_aEntityDataList {
SCR_EntityCatalogEditorData { m_eValidEditorModes 33 }
SCR_EntityCatalogSpawnerData { m_eSlotTypes 24 }
}
}
SCR_EntityCatalogEntry {
m_sEntityPrefab "{DF5CCB7C0FF049F4}Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et"
m_aEntityDataList {
SCR_EntityCatalogEditorData { m_eValidEditorModes 33 }
SCR_EntityCatalogSpawnerData { m_eSlotTypes VEHICLE_LARGE }
}
}
}
}
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{E4785D3AF1D043C2}Configs/ERR/Factions/MissionVehicles.conf"
Configurations {
ResourceClass PC {}
ResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,277 @@
SCR_Faction : "{E7B7EA4823DD81F0}Configs/Factions/BLUFOR.conf" {
FactionKey "US"
UIInfo SCR_FactionUIInfo "{528C961236B7DCD3}" {
Name "#AR-Faction_US"
Icon "{EB7F65DBC9392557}UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USA.edds"
m_sNameUpper "#AR-Faction_US-UC"
}
"Identity of soldiers" FactionIdentity "{570D128F4022EF5A}" : "{B600946E9ACC17C2}Configs/Identities/FactionIdentity_US.conf" {
}
"Radio encryption key" "chickenNuggets"
m_sFactionFlag "{46FB2FB2C2125A3C}UI/Textures/Flags/US-flag-base-3it.edds"
m_FactionFlagMaterial "{610803CC3F3D6649}Assets/Props/Fabric/Flags/Data/Flag_1_2_USA.emat"
m_FactionLabel FACTION_US
m_CallsignInfo SCR_FactionCallsignInfo "{5DA0F2A6677ADA9E}" : "{CB7824D572DD0D5C}Configs/Callsigns/Callsigns_US.conf" {
}
m_iFactionRadioFrequency 48000
m_aEntityCatalogs {
SCR_EntityCatalogMultiList "{5C68A0EE815FA292}" : "{B56E8B4D4B195559}Configs/EntityCatalog/US/Characters_EntityCatalog_US.conf" {
}
SCR_EntityCatalogMultiList "{5C9E82F29B327997}" : "{E4785D3AF1D043C2}Configs/ERR/Factions/MissionVehicles.conf" {
}
SCR_EntityCatalogMultiList "{5C68A0EE8B97CA50}" : "{4E70E7C4C2C17D4A}Configs/EntityCatalog/US/Groups_EntityCatalog_US.conf" {
}
SCR_EntityCatalog "{5C68A0EEB7DB3E84}" : "{0E4B62F186F97C43}Configs/EntityCatalog/US/WeaponTripod_EntityCatalog_US.conf" {
}
SCR_EntityCatalogMultiList "{5C68A0EEB3F124F9}" : "{5F7EC52FC40A03E2}Configs/EntityCatalog/US/InventoryItems_EntityCatalog_US.conf" {
}
SCR_EntityCatalog "{5C9EDDD37394AD40}" : "{0BF36EFF9FFAF92B}Configs/EntityCatalog/US/SupplyContainerItems_EntityCatalog_US.conf" {
}
}
m_aFlagNames +{
}
m_aBaseCallsigns {
SCR_MilitaryBaseCallsign "{5C90D92F493E764B}" {
m_sCallsign "#AR-Campaign_PointAlabama"
m_sCallsignShort "#AR-Comm_Variable_Base_Alabama_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Alabama_US_UC"
m_iSignalIndex 0
}
SCR_MilitaryBaseCallsign "{5C90D92F49F79967}" {
m_sCallsign "#AR-Campaign_PointAlaska"
m_sCallsignShort "#AR-Comm_Variable_Base_Alaska_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Alaska_US_UC"
m_iSignalIndex 1
}
SCR_MilitaryBaseCallsign "{5C90D92F482DA59B}" {
m_sCallsign "#AR-Campaign_PointArizona"
m_sCallsignShort "#AR-Comm_Variable_Base_Arizona_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Arizona_US_UC"
m_iSignalIndex 2
}
SCR_MilitaryBaseCallsign "{5C90D92F483330D2}" {
m_sCallsign "#AR-Campaign_PointArkansas"
m_sCallsignShort "#AR-Comm_Variable_Base_Arkansas_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Arkansas_US_UC"
m_iSignalIndex 3
}
SCR_MilitaryBaseCallsign "{5C90D92F48170DA8}" {
m_sCallsign "#AR-Campaign_PointCalifornia"
m_sCallsignShort "#AR-Comm_Variable_Base_California_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_California_US_UC"
m_iSignalIndex 4
}
SCR_MilitaryBaseCallsign "{5C90D92F487834E8}" {
m_sCallsign "#AR-Campaign_PointColorado"
m_sCallsignShort "#AR-Comm_Variable_Base_Colorado_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Colorado_US_UC"
m_iSignalIndex 5
}
SCR_MilitaryBaseCallsign "{5C90D92F48410A86}" {
m_sCallsign "#AR-Campaign_PointConnecticut"
m_sCallsignShort "#AR-Comm_Variable_Base_Connecticut_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Connecticut_US_UC"
m_iSignalIndex 6
}
SCR_MilitaryBaseCallsign "{5C90D92F48A4E31F}" {
m_sCallsign "#AR-Campaign_PointDelaware"
m_sCallsignShort "#AR-Comm_Variable_Base_Delaware_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Delaware_US_UC"
m_iSignalIndex 7
}
SCR_MilitaryBaseCallsign "{5C90D92F488C6B57}" {
m_sCallsign "#AR-Campaign_PointFlorida"
m_sCallsignShort "#AR-Comm_Variable_Base_Florida_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Florida_US_UC"
m_iSignalIndex 8
}
SCR_MilitaryBaseCallsign "{5C90D92F4896F764}" {
m_sCallsign "#AR-Campaign_PointGeorgia"
m_sCallsignShort "#AR-Comm_Variable_Base_Georgia_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Georgia_US_UC"
m_iSignalIndex 9
}
SCR_MilitaryBaseCallsign "{5C90D92F48FBD90E}" {
m_sCallsign "#AR-Campaign_PointHawaii"
m_sCallsignShort "#AR-Comm_Variable_Base_Hawaii_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Hawaii_US_UC"
m_iSignalIndex 10
}
SCR_MilitaryBaseCallsign "{5C90D92F48DFF562}" {
m_sCallsign "#AR-Campaign_PointIdaho"
m_sCallsignShort "#AR-Comm_Variable_Base_Idaho_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Idaho_US_UC"
m_iSignalIndex 11
}
SCR_MilitaryBaseCallsign "{5C90D92F7724C851}" {
m_sCallsign "#AR-Campaign_PointIllinois"
m_sCallsignShort "#AR-Comm_Variable_Base_Illinois_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Illinois_US_UC"
m_iSignalIndex 12
}
SCR_MilitaryBaseCallsign "{5C90D92F77097F3F}" {
m_sCallsign "#AR-Campaign_PointIndiana"
m_sCallsignShort "#AR-Comm_Variable_Base_Indiana_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Indiana_US_UC"
m_iSignalIndex 13
}
SCR_MilitaryBaseCallsign "{5C90D92F77102B55}" {
m_sCallsign "#AR-Campaign_PointIowa"
m_sCallsignShort "#AR-Comm_Variable_Base_Iowa_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Iowa_US_UC"
m_iSignalIndex 14
}
SCR_MilitaryBaseCallsign "{5C90D92F777ABD04}" {
m_sCallsign "#AR-Campaign_PointKansas"
m_sCallsignShort "#AR-Comm_Variable_Base_Kansas_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Kansas_US_UC"
m_iSignalIndex 15
}
SCR_MilitaryBaseCallsign "{5C90D92F775EBBC1}" {
m_sCallsign "#AR-Campaign_PointKentucky"
m_sCallsignShort "#AR-Comm_Variable_Base_Kentucky_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Kentucky_US_UC"
m_iSignalIndex 16
}
SCR_MilitaryBaseCallsign "{5C90D92F77A28EB6}" {
m_sCallsign "#AR-Campaign_PointLouisiana"
m_sCallsignShort "#AR-Comm_Variable_Base_Louisiana_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Louisiana_US_UC"
m_iSignalIndex 17
}
SCR_MilitaryBaseCallsign "{5C90D92F77871C23}" {
m_sCallsign "#AR-Campaign_PointMaine"
m_sCallsignShort "#AR-Comm_Variable_Base_Maine_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Maine_US_UC"
m_iSignalIndex 18
}
SCR_MilitaryBaseCallsign "{5C90D92F77EB96A0}" {
m_sCallsign "#AR-Campaign_PointMaryland"
m_sCallsignShort "#AR-Comm_Variable_Base_Maryland_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Maryland_US_UC"
m_iSignalIndex 19
}
SCR_MilitaryBaseCallsign "{5C90D92F77CC2518}" {
m_sCallsign "#AR-Campaign_PointMassachusetts"
m_sCallsignShort "#AR-Comm_Variable_Base_Massachusetts_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Massachusetts_US_UC"
m_iSignalIndex 20
}
SCR_MilitaryBaseCallsign "{5C90D92F77D3715B}" {
m_sCallsign "#AR-Campaign_PointMichigan"
m_sCallsignShort "#AR-Comm_Variable_Base_Michigan_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Michigan_US_UC"
m_iSignalIndex 21
}
SCR_MilitaryBaseCallsign "{5C90D92F7635D418}" {
m_sCallsign "#AR-Campaign_PointMinnesota"
m_sCallsignShort "#AR-Comm_Variable_Base_Minnesota_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Minnesota_US_UC"
m_iSignalIndex 22
}
SCR_MilitaryBaseCallsign "{5C90D92F761C3FF2}" {
m_sCallsign "#AR-Campaign_PointMississippi"
m_sCallsignShort "#AR-Comm_Variable_Base_Mississippi_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Mississippi_US_UC"
m_iSignalIndex 23
}
SCR_MilitaryBaseCallsign "{5C90D92F7660CFAA}" {
m_sCallsign "#AR-Campaign_PointMissouri"
m_sCallsignShort "#AR-Comm_Variable_Base_Missouri_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Missouri_US_UC"
m_iSignalIndex 24
}
SCR_MilitaryBaseCallsign "{5C90D92F764A6E6B}" {
m_sCallsign "#AR-Campaign_PointMontana"
m_sCallsignShort "#AR-Comm_Variable_Base_Montana_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Montana_US_UC"
m_iSignalIndex 25
}
SCR_MilitaryBaseCallsign "{5C90D92F76AD4D35}" {
m_sCallsign "#AR-Campaign_PointNebraska"
m_sCallsignShort "#AR-Comm_Variable_Base_Nebraska_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Nebraska_US_UC"
m_iSignalIndex 26
}
SCR_MilitaryBaseCallsign "{5C90D92F76B1EF3A}" {
m_sCallsign "#AR-Campaign_PointNevada"
m_sCallsignShort "#AR-Comm_Variable_Base_Nevada_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Nevada_US_UC"
m_iSignalIndex 27
}
SCR_MilitaryBaseCallsign "{5C90D92F7695FF2F}" {
m_sCallsign "#AR-Campaign_PointNewYork"
m_sCallsignShort "#AR-Comm_Variable_Base_NewYork_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_NewYork_US_UC"
m_iSignalIndex 28
}
SCR_MilitaryBaseCallsign "{5C90D92F76FF94B1}" {
m_sCallsign "#AR-Campaign_PointOhio"
m_sCallsignShort "#AR-Comm_Variable_Base_Ohio_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Ohio_US_UC"
m_iSignalIndex 29
}
SCR_MilitaryBaseCallsign "{5C90D92F76C68EED}" {
m_sCallsign "#AR-Campaign_PointOklahoma"
m_sCallsignShort "#AR-Comm_Variable_Base_Oklahoma_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Oklahoma_US_UC"
m_iSignalIndex 30
}
SCR_MilitaryBaseCallsign "{5C90D92F752A9F29}" {
m_sCallsign "#AR-Campaign_PointOregon"
m_sCallsignShort "#AR-Comm_Variable_Base_Oregon_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Oregon_US_UC"
m_iSignalIndex 31
}
SCR_MilitaryBaseCallsign "{5C90D92F750E6FB9}" {
m_sCallsign "#AR-Campaign_PointPennsylvania"
m_sCallsignShort "#AR-Comm_Variable_Base_Pennsylvania_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Pennsylvania_US_UC"
m_iSignalIndex 32
}
SCR_MilitaryBaseCallsign "{5C90D92F7517240F}" {
m_sCallsign "#AR-Campaign_PointTexas"
m_sCallsignShort "#AR-Comm_Variable_Base_Texas_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Texas_US_UC"
m_iSignalIndex 33
}
SCR_MilitaryBaseCallsign "{5C90D92F7574D867}" {
m_sCallsign "#AR-Campaign_PointUtah"
m_sCallsignShort "#AR-Comm_Variable_Base_Utah_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Utah_US_UC"
m_iSignalIndex 34
}
SCR_MilitaryBaseCallsign "{5C90D92F755C4871}" {
m_sCallsign "#AR-Campaign_PointVermont"
m_sCallsignShort "#AR-Comm_Variable_Base_Vermont_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Vermont_US_UC"
m_iSignalIndex 35
}
SCR_MilitaryBaseCallsign "{5C90D92F75A0502B}" {
m_sCallsign "#AR-Campaign_PointVirginia"
m_sCallsignShort "#AR-Comm_Variable_Base_Virginia_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Virginia_US_UC"
m_iSignalIndex 36
}
SCR_MilitaryBaseCallsign "{5C90D92F758ABFD3}" {
m_sCallsign "#AR-Campaign_PointWashington"
m_sCallsignShort "#AR-Comm_Variable_Base_Washington_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Washington_US_UC"
m_iSignalIndex 37
}
SCR_MilitaryBaseCallsign "{5C90D92F75EF8263}" {
m_sCallsign "#AR-Campaign_PointWisconsin"
m_sCallsignShort "#AR-Comm_Variable_Base_Wisconsin_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Wisconsin_US_UC"
m_iSignalIndex 38
}
SCR_MilitaryBaseCallsign "{5C90D92F75F0F224}" {
m_sCallsign "#AR-Campaign_PointWyoming"
m_sCallsignShort "#AR-Comm_Variable_Base_Wyoming_US"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Wyoming_US_UC"
m_iSignalIndex 39
}
}
m_FactionHomeTerritoryConfig SCR_FactionHomeTerritoryConfig "{5AEE94D54FB58C33}" : "{B548A5B264939A98}Configs/Identities/Territories/FactionHomeTerritory_US.conf" {
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{5C67A1DDE0044806}Configs/ERR/Factions/US.conf"
Configurations {
ResourceClass PC {}
ResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,276 @@
SCR_Faction : "{B122E3B10BB3404B}Configs/Factions/OPFOR.conf" {
FactionKey "USSR"
UIInfo SCR_FactionUIInfo "{528C96127F8B6B08}" {
Name "#AR-Faction_USSR"
Icon "{40B12B0DF911B856}UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USSR.edds"
m_sNameUpper "#AR-Faction_USSR-UC"
}
"Identity of soldiers" FactionIdentity "{570CFDC6685B6B25}" : "{FBBCD73926989580}Configs/Identities/FactionIdentity_USSR.conf" {
}
"Radio encryption key" "coldBorscht"
m_sFactionFlag "{50824EB9F2C215AB}UI/Textures/Flags/USSR-flag-base-3it.edds"
m_FactionFlagMaterial "{B47B52D9DA68905D}Assets/Props/Fabric/Flags/Data/Flag_1_2_SovietArmy.emat"
m_FactionLabel FACTION_USSR
m_CallsignInfo SCR_FactionCallsignInfo "{5DA0F2A67DFB8809}" : "{958043CE1648EC43}Configs/Callsigns/Callsigns_USSR.conf" {
}
m_iFactionRadioFrequency 42000
m_aEntityCatalogs {
SCR_EntityCatalogMultiList "{5C68A0E9BD5E5DD9}" : "{3B679F1799D55F6F}Configs/EntityCatalog/USSR/Characters_EntityCatalog_USSR.conf" {
}
SCR_EntityCatalogMultiList "{5C9E82F285C09E24}" : "{E4785D3AF1D043C2}Configs/ERR/Factions/MissionVehicles.conf" {
}
SCR_EntityCatalogMultiList "{5C68A0E9B9AA3C2D}" : "{37D5B75AAC3E72EA}Configs/EntityCatalog/USSR/Groups_EntityCatalog_USSR.conf" {
}
SCR_EntityCatalog "{5C68A0E9A51460AB}" : "{DDF17C8C140BD1F2}Configs/EntityCatalog/USSR/WeaponTripod_EntityCatalog_USSR.conf" {
}
SCR_EntityCatalogMultiList "{5C68A0E9AFE1E631}" : "{C53421647C3D0D2E}Configs/EntityCatalog/USSR/InventoryItems_EntityCatalog_USSR.conf" {
}
SCR_EntityCatalog "{5C9EDDD378BA3298}" : "{B4CA6761AC935808}Configs/EntityCatalog/USSR/SupplyContainerItems_EntityCatalog_USSR.conf" {
}
}
m_iIdentityVoiceSignal 100
m_aBaseCallsigns {
SCR_MilitaryBaseCallsign "{5C9108F95F3FB520}" {
m_sCallsign "#AR-Campaign_PointArena"
m_sCallsignShort "#AR-Comm_Variable_Base_Arena_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Arena_RU_UC"
m_iSignalIndex 0
}
SCR_MilitaryBaseCallsign "{5C9108F95F0034DB}" {
m_sCallsign "#AR-Campaign_PointAvrora"
m_sCallsignShort "#AR-Comm_Variable_Base_Avrora_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Avrora_RU_UC"
m_iSignalIndex 1
}
SCR_MilitaryBaseCallsign "{5C9108F95F6514E7}" {
m_sCallsign "#AR-Campaign_PointBekas"
m_sCallsignShort "#AR-Comm_Variable_Base_Bekas_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Bekas_RU_UC"
m_iSignalIndex 2
}
SCR_MilitaryBaseCallsign "{5C9108F95F4EE8BF}" {
m_sCallsign "#AR-Campaign_PointBizon"
m_sCallsignShort "#AR-Comm_Variable_Base_Bizon_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Bizon_RU_UC"
m_iSignalIndex 3
}
SCR_MilitaryBaseCallsign "{5C9108F95F5021F9}" {
m_sCallsign "#AR-Campaign_PointBolero"
m_sCallsignShort "#AR-Comm_Variable_Base_Bolero_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Bolero_RU_UC"
m_iSignalIndex 4
}
SCR_MilitaryBaseCallsign "{5C9108F95FBA4C89}" {
m_sCallsign "#AR-Campaign_PointCafftan"
m_sCallsignShort "#AR-Comm_Variable_Base_Cafftan_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Cafftan_RU_UC"
m_iSignalIndex 5
}
SCR_MilitaryBaseCallsign "{5C9108F95F9C00A9}" {
m_sCallsign "#AR-Campaign_PointKaban"
m_sCallsignShort "#AR-Comm_Variable_Base_Kaban_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Kaban_RU_UC"
m_iSignalIndex 6
}
SCR_MilitaryBaseCallsign "{5C9108F95FE17E10}" {
m_sCallsign "#AR-Campaign_PointConsul"
m_sCallsignShort "#AR-Comm_Variable_Base_Consul_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Consul_RU_UC"
m_iSignalIndex 7
}
SCR_MilitaryBaseCallsign "{5C9108F95FCBA475}" {
m_sCallsign "#AR-Campaign_PointDimok"
m_sCallsignShort "#AR-Comm_Variable_Base_Dimok_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Dimok_RU_UC"
m_iSignalIndex 8
}
SCR_MilitaryBaseCallsign "{5C9108F95E2B2963}" {
m_sCallsign "#AR-Campaign_PointEffir"
m_sCallsignShort "#AR-Comm_Variable_Base_Effir_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Effir_RU_UC"
m_iSignalIndex 9
}
SCR_MilitaryBaseCallsign "{5C9108F95E3040F5}" {
m_sCallsign "#AR-Campaign_PointFakir"
m_sCallsignShort "#AR-Comm_Variable_Base_Fakir_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Fakir_RU_UC"
m_iSignalIndex 10
}
SCR_MilitaryBaseCallsign "{5C9108F95E17C67D}" {
m_sCallsign "#AR-Campaign_PointGips"
m_sCallsignShort "#AR-Comm_Variable_Base_Gips_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Gips_RU_UC"
m_iSignalIndex 11
}
SCR_MilitaryBaseCallsign "{5C9108F95E797F8A}" {
m_sCallsign "#AR-Campaign_PointGussar"
m_sCallsignShort "#AR-Comm_Variable_Base_Gussar_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Gussar_RU_UC"
m_iSignalIndex 12
}
SCR_MilitaryBaseCallsign "{5C9108F95E431F83}" {
m_sCallsign "#AR-Campaign_PointIgla"
m_sCallsignShort "#AR-Comm_Variable_Base_Igla_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Igla_RU_UC"
m_iSignalIndex 13
}
SCR_MilitaryBaseCallsign "{5C9108F95EA7F87E}" {
m_sCallsign "#AR-Campaign_PointKhek"
m_sCallsignShort "#AR-Comm_Variable_Base_Khek_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Khek_RU_UC"
m_iSignalIndex 14
}
SCR_MilitaryBaseCallsign "{5C9108F95E88C6B9}" {
m_sCallsign "#AR-Campaign_PointLednik"
m_sCallsignShort "#AR-Comm_Variable_Base_Lednik_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Lednik_RU_UC"
m_iSignalIndex 15
}
SCR_MilitaryBaseCallsign "{5C9108F95EEDE322}" {
m_sCallsign "#AR-Campaign_PointMatros"
m_sCallsignShort "#AR-Comm_Variable_Base_Matros_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Matros_RU_UC"
m_iSignalIndex 16
}
SCR_MilitaryBaseCallsign "{5C9108F95EF6244A}" {
m_sCallsign "#AR-Campaign_PointMuskat"
m_sCallsignShort "#AR-Comm_Variable_Base_Muskat_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Muskat_RU_UC"
m_iSignalIndex 17
}
SCR_MilitaryBaseCallsign "{5C9108F95EDAF04A}" {
m_sCallsign "#AR-Campaign_PointNagan"
m_sCallsignShort "#AR-Comm_Variable_Base_Nagan_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Nagan_RU_UC"
m_iSignalIndex 18
}
SCR_MilitaryBaseCallsign "{5C9108F95D3CCF27}" {
m_sCallsign "#AR-Campaign_PointNitka"
m_sCallsignShort "#AR-Comm_Variable_Base_Nitka_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Nitka_RU_UC"
m_iSignalIndex 19
}
SCR_MilitaryBaseCallsign "{5C9108F95D076483}" {
m_sCallsign "#AR-Campaign_PointOmega"
m_sCallsignShort "#AR-Comm_Variable_Base_Omega_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Omega_RU_UC"
m_iSignalIndex 20
}
SCR_MilitaryBaseCallsign "{5C9108F95D68D0F3}" {
m_sCallsign "#AR-Campaign_PointPlazma"
m_sCallsignShort "#AR-Comm_Variable_Base_Plazma_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Plazma_RU_UC"
m_iSignalIndex 21
}
SCR_MilitaryBaseCallsign "{5C9108F95D4C0F8E}" {
m_sCallsign "#AR-Campaign_PointPolyn"
m_sCallsignShort "#AR-Comm_Variable_Base_Polyn_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Polyn_RU_UC"
m_iSignalIndex 22
}
SCR_MilitaryBaseCallsign "{5C9108F95D56EEEE}" {
m_sCallsign "#AR-Campaign_PointProlog"
m_sCallsignShort "#AR-Comm_Variable_Base_Prolog_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Prolog_RU_UC"
m_iSignalIndex 23
}
SCR_MilitaryBaseCallsign "{5C9108F95DBA92EE}" {
m_sCallsign "#AR-Campaign_PointRabkor"
m_sCallsignShort "#AR-Comm_Variable_Base_Rabkor_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Rabkor_RU_UC"
m_iSignalIndex 24
}
SCR_MilitaryBaseCallsign "{5C9108F95C69680D}" {
m_sCallsign "#AR-Campaign_PointRadon"
m_sCallsignShort "#AR-Comm_Variable_Base_Radon_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Radon_RU_UC"
m_iSignalIndex 25
}
SCR_MilitaryBaseCallsign "{5C9108F95C4FD930}" {
m_sCallsign "#AR-Campaign_PointSadko"
m_sCallsignShort "#AR-Comm_Variable_Base_Sadko_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Sadko_RU_UC"
m_iSignalIndex 26
}
SCR_MilitaryBaseCallsign "{5C9108F95C5255FD}" {
m_sCallsign "#AR-Campaign_PointSekret"
m_sCallsignShort "#AR-Comm_Variable_Base_Sekret_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Sekret_RU_UC"
m_iSignalIndex 27
}
SCR_MilitaryBaseCallsign "{5C9108F95CB621AE}" {
m_sCallsign "#AR-Campaign_PointShtanga"
m_sCallsignShort "#AR-Comm_Variable_Base_Shtanga_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Shtanga_RU_UC"
m_iSignalIndex 28
}
SCR_MilitaryBaseCallsign "{5C9108F95C9545BC}" {
m_sCallsign "#AR-Campaign_PointShuka"
m_sCallsignShort "#AR-Comm_Variable_Base_Shuka_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Shuka_RU_UC"
m_iSignalIndex 29
}
SCR_MilitaryBaseCallsign "{5C9108F95CFE26C3}" {
m_sCallsign "#AR-Campaign_PointTabor"
m_sCallsignShort "#AR-Comm_Variable_Base_Tabor_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Tabor_RU_UC"
m_iSignalIndex 30
}
SCR_MilitaryBaseCallsign "{5C9108F95CDD263C}" {
m_sCallsign "#AR-Campaign_PointTenor"
m_sCallsignShort "#AR-Comm_Variable_Base_Tenor_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Tenor_RU_UC"
m_iSignalIndex 31
}
SCR_MilitaryBaseCallsign "{5C9108F95B27128C}" {
m_sCallsign "#AR-Campaign_PointTsikson"
m_sCallsignShort "#AR-Comm_Variable_Base_Tsikson_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Tsikson_RU_UC"
m_iSignalIndex 32
}
SCR_MilitaryBaseCallsign "{5C9108F95B08D83D}" {
m_sCallsign "#AR-Campaign_PointUlan"
m_sCallsignShort "#AR-Comm_Variable_Base_Ulan_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Ulan_RU_UC"
m_iSignalIndex 33
}
SCR_MilitaryBaseCallsign "{5C9108F95B6D3FC2}" {
m_sCallsign "#AR-Campaign_PointVermout"
m_sCallsignShort "#AR-Comm_Variable_Base_Vermout_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Vermout_RU_UC"
m_iSignalIndex 34
}
SCR_MilitaryBaseCallsign "{5C9108F95B712949}" {
m_sCallsign "#AR-Campaign_PointViympel"
m_sCallsignShort "#AR-Comm_Variable_Base_Viympel_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Viympel_RU_UC"
m_iSignalIndex 35
}
SCR_MilitaryBaseCallsign "{5C9108F95B57D185}" {
m_sCallsign "#AR-Campaign_PointYantar"
m_sCallsignShort "#AR-Comm_Variable_Base_Yantar_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Yantar_RU_UC"
m_iSignalIndex 36
}
SCR_MilitaryBaseCallsign "{5C9108F95BB17114}" {
m_sCallsign "#AR-Campaign_PointYolka"
m_sCallsignShort "#AR-Comm_Variable_Base_Yolka_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Yolka_RU_UC"
m_iSignalIndex 37
}
SCR_MilitaryBaseCallsign "{5C9108F95B97C054}" {
m_sCallsign "#AR-Campaign_PointZheton"
m_sCallsignShort "#AR-Comm_Variable_Base_Zheton_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Zheton_RU_UC"
m_iSignalIndex 38
}
SCR_MilitaryBaseCallsign "{5C9108F95BFC33E5}" {
m_sCallsign "#AR-Campaign_PointZurna"
m_sCallsignShort "#AR-Comm_Variable_Base_Zurna_RU"
m_sCallsignUpperCase "#AR-Comm_Variable_Base_Zurna_RU_UC"
m_iSignalIndex 39
}
}
m_FactionHomeTerritoryConfig SCR_FactionHomeTerritoryConfig "{5AEE94D5517C30BD}" : "{31FC78AF00523A99}Configs/Identities/Territories/FactionHomeTerritory_USSR.conf" {
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{D7A5CFA62A36480D}Configs/ERR/Factions/USSR.conf"
Configurations {
ResourceClass PC {}
ResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,21 @@
SCR_GameOverScreenConfig : "{651583FFFB7FC765}Configs/GameOverScreen/BaseGameOverScreensConfig.conf" {
m_aGameOverScreens {
ERR_EscapeGameOverScreenInfo "{6B193DC8DDC63507}" {
m_GameOverScreenId VICTORY
m_GameOverContentLayout "{C4507D07F3C54831}UI/layouts/HUD/GameOver/EndScreen/EndScreenContent_NoImage.layout"
m_OptionalParams SCR_BaseGameOverScreenInfoOptional "{4984A5C1BFEFC04E}" {
m_sTitle "Escape complete"
m_sAudioOneShot "SOUND_ONVICTORY"
}
}
ERR_FailureGameOverScreenInfo "{E66F29A7A8AD7438}" {
m_GameOverScreenId LOOSE
m_GameOverContentLayout "{C4507D07F3C54831}UI/layouts/HUD/GameOver/EndScreen/EndScreenContent_NoImage.layout"
m_OptionalParams SCR_BaseGameOverScreenInfoOptional "{3DBF0BDE715945FA}" {
m_sTitle "Escape failed"
m_sDebriefing "No surviving prisoners can complete the escape, or the extraction helicopter has been lost."
m_sAudioOneShot "SOUND_ONDEFEAT"
}
}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{F6633922A25F9441}Configs/ERR/GameOverScreens.conf"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,7 @@
ERR_FactionCatalog {
PlayerFactionKey "US"
EnemyFactionKey "USSR"
PrisonerPrefab "{3FF693715C9F8928}Prefabs/ERR/Prisoner.et"
GuardGroupPrefab "{D5A4D0D3AE1A3E26}Prefabs/ERR/Patrol.et"
ExtractionPrefab "{DF5CCB7C0FF049F4}Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et"
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{BE50B97B8E2B36E6}Configs/ERR/VanillaFactions.conf"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,11 @@
SCR_MissionHeader {
World "{B6C516F86302C679}Worlds/ERR_Everon.ent"
SystemsConfig "{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf"
m_sName "Rereintroduced: Everon Base (development)"
m_sAuthor "Rereintroduced contributors"
m_sDescription "Independent base escape mission using vanilla Reforger. Companion addons optional. Development scenario."
m_sGameMode "Escape"
m_iPlayerCount 12
m_eSaveTypes 0
m_bShowInScenarioMenu 1
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{AD62322D5213C440}Missions/ERR_Everon_Base.conf"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,6 @@
GenericEntity {
components {
ERR_LocationComponent "{C17CA14398A1CD7E}" { m_Kind 2 }
RplComponent "{0BF5BAAA5FBFEECE}" { Streamable Disabled }
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{033503110AC34EAC}Prefabs/ERR/Extraction.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,10 @@
SCR_FactionManager : "{A242612865F2A48E}Prefabs/MP/Managers/Factions/FactionManager_Base.et" {
Factions {
SCR_Faction : "{5C67A1DDE0044806}Configs/ERR/Factions/US.conf" {
m_sFactionBackground "{F8AC305446D5D480}UI/Textures/DeployMenu/Loadout-BG/Loadout_US_BG.imageset"
}
SCR_Faction : "{D7A5CFA62A36480D}Configs/ERR/Factions/USSR.conf" {
m_sFactionBackground "{21533F2089005056}UI/Textures/DeployMenu/Loadout-BG/Loadout_BG_USSR.imageset"
}
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{5414041A15DC4B54}Prefabs/ERR/FactionManager.et"
Configurations {
EntityTemplateResourceClass PC {}
EntityTemplateResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,13 @@
GenericEntity {
components {
MeshObject "{A557F6DC012E5101}" {
Object "{268DBDABB3C94AD7}Assets/Props/Military/Sandbags/Sandbag_01_short.xob"
Materials {
MaterialAssignClass "{A557F6DC012E5102}" { SourceMaterial "Sandbags_01_Short" AssignedMaterial "{31529E064AA7C917}Assets/Props/Military/Sandbags/Data/Sandbags_01_short_Burlap.emat" }
MaterialAssignClass "{A557F6DC012E5103}" { SourceMaterial "Sandbags_01_MLOD" AssignedMaterial "{2169E8EB73E1C127}Assets/Props/Military/Sandbags/Data/Sandbags_01_Burlap_MLOD.emat" }
}
}
RigidBody "{A557F6DC012E5104}" { ModelGeometry 1 Static 1 }
RplComponent "{A557F6DC012E5105}" {}
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et"
Configurations {
ResourceClass PC {}
ResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,14 @@
ERR_GameMode : "{0F307326459A1395}Prefabs/MP/Modes/GameMode_Base.et" {
components {
SCR_GameOverScreenManagerComponent "{56DEC646298AD219}" {
m_GameOverScreenConfig SCR_GameOverScreenConfig "{56DEC6462FFDD82D}" : "{F6633922A25F9441}Configs/ERR/GameOverScreens.conf" {}
}
ERR_ScenarioComponent "{B78E910E88DE30D2}" {
m_Definition "{BC310DC0CD27F523}Configs/ERR/EveronSites.conf"
}
SCR_RespawnSystemComponent "{56B2B4793051E7C9}" {
m_SpawnLogic ERR_SpawnLogic "{79AD722B2EFD595F}" {}
}
}
m_bUseSpawnPreload 0
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{978E045E53EF36C8}Prefabs/ERR/GameMode.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,5 @@
GenericEntity : "{6D56FED1E55A8F84}Prefabs/Items/Misc/IntelligenceFolder_E_01/IntelligenceFolder_E_01.et" {
components {
ERR_DocumentComponent "{E4598D0BE2C251A3}" {}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,10 @@
SCR_AIGroup : "{E552DABF3636C2AD}Prefabs/Groups/OPFOR/Group_USSR_RifleSquad.et" {
m_aUnitPrefabSlots {
"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"
"{612F43A4D5AE765F}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et"
"{23ADBBC31B6A3DC6}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AR.et"
"{1C78331E156A3D65}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AT.et"
"{333DA6244C7DA34C}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SR.et"
"{BF643BE4ADBDFDD3}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_LAT.et"
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{D5A4D0D3AE1A3E26}Prefabs/ERR/Patrol.et"
Configurations {
EntityTemplateResourceClass PC {}
EntityTemplateResourceClass HEADLESS {}
}
}
@@ -0,0 +1,90 @@
GenericEntity {
components {
ERR_LocationComponent "{3B60CBEB3C04333C}" { m_Kind 0 }
Hierarchy "{30ADADE77D1EC3B8}" {}
RplComponent "{7FA5168C6FBD0C22}" {}
}
{
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "2879356FFFBE36E0"
coords -6 0 6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "C99EF9AFCEBA863D"
coords -3 0 6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "91048277F04ACA61"
coords 0 0 6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "8F2200A922FB0A6E"
coords 3 0 6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "3C442429BBCF5D2F"
coords -6 0 -6
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "9E855CC802C592CA"
coords 6 0 -6
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "778DAC42C9208F67"
coords -6 0 -3
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "7E350EB9053673C4"
coords 6 0 -3
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "AD17884D5EA37D37"
coords -6 0 0
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "1A157E23E1A995D8"
coords 6 0 0
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "3A78A6F3ACB7ACB1"
coords -6 0 3
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "275B472B565FFF6C"
coords 6 0 3
angles 0 -90 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "1B20E11B3FC7B59A"
coords -6 0 -6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "2735B52246DD6213"
coords -3 0 -6
angles 0 0 0
}
GenericEntity : "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et" {
ID "28101A0E33470B38"
coords 3 0 -6
angles 0 0 0
}
GenericEntity : "{C3FDC4DBCD58C2F5}Prefabs/ERR/PrisonDoor.et" {
ID "54D8F96ECC743335"
scale 1.5
coords 0 -0.1 -6
angles 0 0 0
}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{BE6B8D56349038A6}Prefabs/ERR/Prison.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,19 @@
GenericEntity : "{34B08027DBDE322A}Prefabs/Structures/BuildingParts/Doors/Door_MetalGate_01_Short_LEFT_EXT_ST_B.et" {
components {
DoorComponent "{221C667A9F7D4B69}" {
DoorAction ERR_PrisonDoorAction "{50888D3646A61640}" {
ParentContextList { "SCR_DoorUserAction" }
}
}
ActionsManagerComponent "{F32B667C3C823800}" {
ActionContexts { UserActionContext "{50888D37F529F720}" { ContextName "SCR_DoorUserAction" Radius 2 } }
additionalActions {
ERR_UnlockPrisonAction "{CA7918FEA177BFB8}" {
ParentContextList { "SCR_DoorUserAction" }
UIInfo SCR_ActionUIInfo "{F734C81E11AA6BEF}" { Name "Pick prison lock" }
Duration 4
}
}
}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{C3FDC4DBCD58C2F5}Prefabs/ERR/PrisonDoor.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,8 @@
GenericEntity {
components {
Hierarchy "{4F20A90EDBD625A4}" {}
MeshObject "{4F20A90EDBD625A1}" { Object "{0B96D139FEBCA006}Assets/Structures/Walls/Concrete/ConcreteWall_01_3m.xob" }
RigidBody "{4F20A90EDBD625A2}" { ModelGeometry 1 Static 1 }
RplComponent "{4F20A90EDBD625A3}" {}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,55 @@
SCR_ChimeraCharacter : "{836E7E39AAC5888B}Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et" {
components {
ActionsManagerComponent "{520EA1D2F659CE02}" {
additionalActions {
ERR_LoadCasualtyAction "{E7016B8C499EC8A3}" {
ParentContextList { "Chest" "LowerTorso" }
UIInfo SCR_ActionUIInfo "{E7016B8C499EC8A4}" { Name "Load casualty into extraction helicopter" }
Duration 5
}
}
}
SCR_EditableCharacterComponent "{520EA1D2F659C85C}" {
m_UIInfo SCR_EditableEntityUIInfo "{5298E609432D192D}" {
Name "Prisoner"
}
}
SCR_CharacterInventoryStorageComponent "{520EA1D2DB118DAC}" {
components {
SCR_EquipmentStorageComponent "{56B49DA9722B635D}" {
InitialStorageSlots {
SCR_EquipmentStorageSlot BinocularSlot { Prefab "" }
SCR_EquipmentStorageSlot WristwatchSlot {
Prefab "{78ED4FEF62BBA728}Prefabs/Items/Equipment/Watches/Watch_SandY184A.et"
}
}
}
}
}
BaseLoadoutManagerComponent "{520EA1D2DB11821E}" {
Slots {
LoadoutSlotInfo Hat { Prefab "{F545C1BE7C99954A}Prefabs/Characters/HeadGear/Hat_Patrol_US_01/Hat_Patrol_US_01.et" }
LoadoutSlotInfo Jacket { Prefab "{3CCA7A9BB4FD3197}Prefabs/Characters/Uniforms/Jacket_US_BDU_rolledup.et" }
LoadoutSlotInfo Pants { Prefab "{604BB72BE8E023C2}Prefabs/Characters/Uniforms/Pants_US_BDU.et" }
SCR_FeetLoadoutSlotInfo Boots { Prefab "{DAAFD15478BDE1C3}Prefabs/Characters/Footwear/CombatBoots_US_01.et" }
LoadoutSlotInfo ArmoredVest { Prefab "" }
LoadoutSlotInfo Back { Prefab "" }
LoadoutSlotInfo Vest { Prefab "" }
LoadoutSlotInfo HandWear { Prefab "" }
}
}
SCR_InventoryStorageManagerComponent "{520EA1D2DB118DE5}" {
InitialInventoryItems {
ItemsInitConfigurationItem "{EA7AC3C2078B68C1}" {
TargetStorage "Prefabs/Characters/Uniforms/Pants_US_BDU.et"
PrefabsToSpawn {
"{A81F501D3EF6F38E}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et"
"{A81F501D3EF6F38E}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et"
"{D70216B1B2889129}Prefabs/Items/Medicine/Tourniquet_01/Tourniquet_US_01.et"
"{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et"
}
}
}
}
}
}
@@ -0,0 +1,7 @@
MetaFileClass {
Name "{3FF693715C9F8928}Prefabs/ERR/Prisoner.et"
Configurations {
EntityTemplateResourceClass PC {}
EntityTemplateResourceClass HEADLESS : PC {}
}
}
@@ -0,0 +1,16 @@
GenericEntity {
components {
MeshObject "{111C06CB740ED195}" { Object "{77C9FCF3FB1246E9}Assets/Items/Equipment/Radios/Radio_R107M/Radio_R107M_01_item.xob" }
RigidBody "{4C174A44D07B91BA}" { ModelGeometry 1 Static 1 }
ERR_LocationComponent "{C19CA6CC83470879}" { m_Kind 1 }
RplComponent "{54ED7463161A5622}" { Streamable Disabled }
ActionsManagerComponent "{B081EC0768636EAB}" {
ActionContexts { UserActionContext "{C1A75A5D8B7EF1E4}" { ContextName "ERR_Radio" Radius 2 } }
additionalActions { ERR_TuneRadioAction "{7ABBB6B5D73DDD95}" {
ParentContextList { "ERR_Radio" }
UIInfo SCR_ActionUIInfo "{1B42BB7CEDECB994}" { Name "Contact extraction HQ" }
Duration 8
} }
}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{F7E7E3D6ACF0C860}Prefabs/ERR/Radio.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,7 @@
SCR_ManualCamera {
m_bInputEnabled 0
m_bStartAtEntity 1
m_aComponents {
ERR_FollowSurvivorCameraComponent "{965C2E8B2339B926}" {}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{EB1210AAE1BB8F54}Prefabs/ERR/SpectatorCamera.et"
Configurations {
EntityTemplateResourceClass PC {
}
EntityTemplateResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,28 @@
GenericEntity : "{EBBC859CCD94D96D}Prefabs/Props/EmptyStorages/USSR_AmmoBox_empty.et" {
components {
MeshObject "{6530845A09309E37}" {
Object "{819ED3266EE5113B}Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/EquipmentBoxWooden_Weapon_01.xob"
Materials {
MaterialAssignClass "{6530845A093091BB}" {
SourceMaterial "EquipmentBoxWooden_Weapon_01"
AssignedMaterial "{7D2E831AFA5CF50D}Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/Data/EquipmentBoxWooden_Weapon_01_USSR.emat"
}
MaterialAssignClass "{6530845A093091B2}" {
SourceMaterial "EquipmentBoxWooden_Weapon_01_Decal"
}
}
}
SCR_UniversalInventoryStorageComponent "{6530845A09302DE0}" {
MaxCumulativeVolume 120000
MaxItemSize 120 40 40
m_fMaxWeight 80
Attributes SCR_ItemAttributeCollection "{6530845A09302DFF}" {
ItemDisplayName SCR_InventoryUIInfo "{6530845A09302D03}" {
Name "Supply cache"
Description "Limited equipment shared between prisoners."
}
}
}
InventoryStorageManagerComponent "{18A1D42A468F584F}" {}
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,6 @@
GenericEntity {
components {
ERR_LocationComponent "{8E7CFEA92C1811F0}" { m_Kind 4 }
RplComponent "{98A4A31435A9CA04}" { Streamable Disabled }
}
}
@@ -0,0 +1,9 @@
MetaFileClass {
Name "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
Configurations {
ResourceClass PC {
}
ResourceClass HEADLESS : PC {
}
}
}
@@ -0,0 +1,39 @@
class ERR_UnlockPrisonAction : ScriptedUserAction
{
override bool CanBePerformedScript(IEntity user)
{
ERR_GameMode mode = ERR_GameMode.Get();
return mode && mode.Phase() == ERR_Phase.PRISON && ERR_Actors.CanFight(user);
}
override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (!mode || !mode.UnlockPrison(pUserEntity)) return;
BaseDoorComponent door = BaseDoorComponent.Cast(pOwnerEntity.FindComponent(BaseDoorComponent));
if (door) door.UseDoorAction(pUserEntity);
}
}
class ERR_PrisonDoorAction : SCR_DoorUserAction
{
override bool CanBePerformedScript(IEntity user)
{
ERR_GameMode mode = ERR_GameMode.Get();
return mode && mode.Phase() > ERR_Phase.PRISON && super.CanBePerformedScript(user);
}
}
class ERR_TuneRadioAction : ScriptedUserAction
{
override bool CanBePerformedScript(IEntity user)
{
ERR_GameMode mode = ERR_GameMode.Get();
ERR_LocationComponent location = ERR_LocationComponent.Cast(GetOwner().FindComponent(ERR_LocationComponent));
return mode && mode.Phase() == ERR_Phase.RADIO_SEARCH && location && location.Knowledge() == 2 && ERR_Actors.CanFight(user);
}
override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (mode) mode.TuneRadio(pUserEntity, ERR_LocationComponent.Cast(pOwnerEntity.FindComponent(ERR_LocationComponent)));
}
}
@@ -0,0 +1,81 @@
class ERR_Actors
{
static bool Alive(IEntity actor)
{
if (!actor) return false;
DamageManagerComponent damage = DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent));
return damage && !damage.IsDestroyed();
}
static bool CanFight(IEntity actor)
{
if (!Alive(actor)) return false;
CharacterControllerComponent controller = CharacterControllerComponent.Cast(actor.FindComponent(CharacterControllerComponent));
return controller && !controller.IsUnconscious();
}
static SCR_AIGroup Group(IEntity actor)
{
if (!actor) return null;
AIControlComponent control = AIControlComponent.Cast(actor.FindComponent(AIControlComponent));
if (!control || !control.GetAIAgent()) return null;
return SCR_AIGroup.Cast(control.GetAIAgent().GetParentGroup());
}
static bool Player(IEntity actor)
{
return actor && GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(actor) > 0;
}
static IEntity Spawn(ResourceName prefab, vector position, vector angles = "0 0 0")
{
if (!Replication.IsServer() || prefab.IsEmpty()) return null;
Resource resource = Resource.Load(prefab);
if (!resource || !resource.IsValid()) return null;
EntitySpawnParams params = new EntitySpawnParams();
params.TransformMode = ETransformMode.WORLD;
Math3D.AnglesToMatrix(angles, params.Transform);
params.Transform[3] = position;
return GetGame().SpawnEntityPrefab(resource, GetGame().GetWorld(), params);
}
static void DeleteSpawned(IEntity entity)
{
if (!Replication.IsServer() || !entity || Player(entity)) return;
SCR_AIGroup group = SCR_AIGroup.Cast(entity);
if (group)
{
// Never remove a group that has acquired a player since mission creation.
if (group.GetPlayerCount(true) > 0) return;
group.DespawnMembers();
}
SCR_EntityHelper.DeleteEntityAndChildren(entity);
}
static vector Ground(vector position)
{
position[1] = GetGame().GetWorld().GetSurfaceY(position[0], position[2]) + 0.1;
return position;
}
static void Players(out array<IEntity> players, bool conscious = false)
{
players.Clear();
array<int> ids = {};
GetGame().GetPlayerManager().GetPlayers(ids);
foreach (int id : ids)
{
IEntity actor = GetGame().GetPlayerManager().GetPlayerControlledEntity(id);
if (Alive(actor) && (!conscious || CanFight(actor))) players.Insert(actor);
}
}
}
// One server-owned implementation is installed by the AI addon.
class ERR_CommandService
{
void Tick(float now) {}
void Stop() {}
void RegisterGroup(SCR_AIGroup group) {}
void UnregisterGroup(SCR_AIGroup group) {}
}
@@ -0,0 +1,111 @@
// Transport-independent administration. Only the owning controller supplies
// authorization, derived on the server from its authenticated player ID.
class ERR_CommandArguments
{
static string CoreSetting(string section, string option)
{
if (section == "mission" && option == "radio") return "radioDefenceSeconds";
if (section == "intel" && option == "reveal") return "intelRevealChancePercent";
return "";
}
static bool Integer(string text, out int value)
{
if (text.IsEmpty() || text.Length() > 6) return false;
for (int i = 0; i < text.Length(); i++)
if ("0123456789".IndexOf(text.Substring(i, 1)) < 0) return false;
value = text.ToInt();
return true;
}
}
class ERR_AdminService
{
protected string Setting(string section, string option)
{
return ERR_CommandArguments.CoreSetting(section, option);
}
protected bool Extension(ERR_GameMode mode, string arguments, array<string> replies) { return false; }
protected bool TimeCommand(ERR_GameMode mode, array<string> parts, array<string> replies)
{
if (parts.Count() < 2 || parts[0] != "mission" || (parts[1] != "time" && parts[1] != "speed")) return false;
string key = "startTimeMinutes";
if (parts[1] == "speed") key = "timeMultiplier";
if (parts.Count() == 3 && parts[2] == "show")
{
if (mode.Time()) replies.Insert(mode.Time().Status());
replies.Insert("Next round: " + ERR_TimeService.Clock(mode.Settings().Get("startTimeMinutes")) + ", " + mode.Settings().Get("timeMultiplier").ToString() + "x progression.");
return true;
}
int value;
bool valid;
if (parts.Count() == 4 && parts[2] == "set")
{
if (key == "startTimeMinutes") valid = ERR_TimeService.ParseClock(parts[3], value);
else valid = ERR_CommandArguments.Integer(parts[3], value);
}
if (valid && mode.Settings().Set(key, value))
replies.Insert("Saved for next round: " + ERR_TimeService.Clock(mode.Settings().Get("startTimeMinutes")) + ", " + mode.Settings().Get("timeMultiplier").ToString() + "x progression. Current round clock unchanged.");
else replies.Insert("Invalid time or settings could not be saved. Use mission time set HH:MM (00:00-23:59) or mission speed set N (1-24). Previous setting retained.");
return true;
}
protected string SettingHelp(string key)
{
if (key == "intelRevealChancePercent")
return "Use /esc intel reveal set N (0-100). This is the chance that a first document identifies its location exactly; otherwise it gives a rough location. A second document for that location always identifies it. Changes affect newly recovered documents immediately; known locations and spent documents remain unchanged.";
return "";
}
protected void SettingCommand(ERR_Settings settings, string key, array<string> parts, array<string> replies)
{
if (parts.Count() == 3 && parts[2] == "show") { replies.Insert(key + "=" + settings.Get(key).ToString()); return; }
string help = SettingHelp(key);
if (parts.Count() == 3 && parts[2] == "help" && !help.IsEmpty()) { replies.Insert(help); return; }
int value;
if (parts.Count() == 4 && parts[2] == "set" && ERR_CommandArguments.Integer(parts[3], value) && settings.Set(key, value))
replies.Insert(key + "=" + value.ToString() + " saved");
else
{
string failure = "Invalid value or settings could not be saved; previous setting retained.";
if (!help.IsEmpty()) failure += " " + help;
replies.Insert(failure);
}
}
protected string Help()
{
return "/esc status | settings | mission abandon | mission radio show|set N | mission date show|set YYYY-MM-DD|authored | mission weather show|set authored|clear|overcast|rain | mission time show|set HH:MM | mission speed show|set N | intel reveal show|set N|help | spectate next|previous";
}
void Execute(ERR_GameMode mode, bool authorized, string arguments, array<string> replies)
{
replies.Clear();
if (!Replication.IsServer() || !mode) return;
if (!authorized) { replies.Insert("Administrator access required."); return; }
if (arguments.Length() > 160) { replies.Insert("Command is too long."); return; }
arguments = arguments.Trim(); arguments.ToLower();
if (arguments == "status") { replies.Insert(mode.Status()); Extension(mode, arguments, replies); return; }
if (arguments == "mission abandon")
{
if (mode.AbandonRound()) replies.Insert("Round abandoned. The normal defeat and restart sequence has begun.");
else replies.Insert("Only an active round can be abandoned.");
return;
}
if (!mode.Settings()) { replies.Insert("Mission settings are not ready."); return; }
if (arguments == "settings")
{
foreach (string key : ERR_Settings.Keys()) replies.Insert(key + "=" + mode.Settings().Get(key).ToString());
return;
}
if (Extension(mode, arguments, replies)) return;
array<string> parts = {};
arguments.Split(" ", parts, true);
if (ERR_EnvironmentCommands.Execute(mode.Settings(), mode.Environment(), parts, replies)) return;
if (TimeCommand(mode, parts, replies)) return;
if (parts.Count() == 3 || parts.Count() == 4)
{
string key = Setting(parts[0], parts[1]);
if (!key.IsEmpty())
{
SettingCommand(mode.Settings(), key, parts, replies);
return;
}
}
replies.Insert(Help());
}
}
@@ -0,0 +1,82 @@
// Conservative fallback for a sleeping, engine-off Mi8 whose native simulation
// has not yet populated contact flags. Reads physical support; never wakes it.
class ERR_CasualtyGroundSupport
{
static bool SupportHit(float fraction, float normalY, bool selfHit, bool dynamicHit)
{
return fraction >= 0 && fraction < 1 && normalY >= 0.85 && !selfHit && !dynamicHit;
}
static bool BelongsTo(IEntity entity, IEntity root)
{
while (entity)
{
if (entity == root) return true;
entity = entity.GetParent();
}
return false;
}
static bool WheelCenter(Vehicle aircraft, string bone, out vector center, bool diagnostics = false)
{
if (!aircraft) return false;
if (aircraft.GetBoneIndex(bone) == -1)
{
if (diagnostics) Print("ERR GEAR PIVOT MISSING: " + bone);
return false;
}
vector identity[4]; Math3D.MatrixIdentity4(identity);
PointInfo pivot = new PointInfo();
pivot.Set(aircraft, bone, identity);
vector world[4]; pivot.GetWorldTransform(world);
center = world[3];
if (diagnostics) PrintFormat("ERR GEAR PIVOT: bone=%1 node=%2 center=%3", bone, pivot.GetNodeId(), center);
return pivot.GetNodeId() != -1;
}
static bool WheelSupported(Vehicle aircraft, vector center, float radius, bool diagnostics = false)
{
vector bottom = center - Vector(0, radius, 0);
TraceParam trace = new TraceParam();
trace.Start = bottom + "0 0.10 0";
trace.End = bottom - "0 0.12 0";
trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
trace.LayerMask = TRACE_LAYER_CAMERA;
trace.Exclude = aircraft;
float fraction = aircraft.GetWorld().TraceMove(trace, null);
bool selfHit = trace.TraceEnt && BelongsTo(trace.TraceEnt, aircraft);
bool dynamicHit;
if (trace.TraceEnt)
{
Physics surface = trace.TraceEnt.GetPhysics();
// Unknown/entity-only support and moving actors/vehicles are not parking.
dynamicHit = !surface || surface.IsDynamic();
}
bool supported = SupportHit(fraction, trace.TraceNorm[1], selfHit, dynamicHit);
if (diagnostics)
{
vector contact = vector.Lerp(trace.Start, trace.End, fraction);
float terrainY = aircraft.GetWorld().GetSurfaceY(bottom[0], bottom[2]);
PrintFormat("ERR GEAR TERRAIN: bottom=%1 terrainY=%2 tireTerrainGap=%3", bottom, terrainY, bottom[1] - terrainY);
PrintFormat("ERR GEAR SUPPORT: center=%1 radius=%2 bottom=%3 fraction=%4 normal=%5 self=%6 dynamic=%7 supported=%8 gap=%9", center, radius, bottom, fraction, trace.TraceNorm, selfHit, dynamicHit, supported, bottom[1] - contact[1]);
}
return supported;
}
static bool Parked(Vehicle aircraft, bool diagnostics = false)
{
if (!aircraft || !aircraft.GetPrefabData() || !aircraft.GetPrefabData().GetPrefabName().Contains("/Mi8MT/")) return false;
Physics physics = aircraft.GetPhysics();
HelicopterControllerComponent controller = HelicopterControllerComponent.Cast(aircraft.FindComponent(HelicopterControllerComponent));
if (!physics || !controller || !controller.GetSimulation()) return false;
if (diagnostics) PrintFormat("ERR PARKED SUPPORT: physicsAwake=%1 engineOn=%2 nativeContact=%3", physics.IsActive(), controller.GetSimulation().EngineIsOn(), controller.GetSimulation().HasAnyGroundContact());
if (physics.IsActive() || controller.GetSimulation().EngineIsOn()) return false;
vector front, left, right;
if (!WheelCenter(aircraft, "v_wheel_F", front, diagnostics) || !WheelCenter(aircraft, "v_wheel_bL", left, diagnostics) || !WheelCenter(aircraft, "v_wheel_bR", right, diagnostics)) return false;
// Fail closed if native pivot resolution collapses to an owner origin or
// otherwise cannot represent the authored three-point landing footprint.
if (vector.DistanceXZ(front, left) < 1 || vector.DistanceXZ(front, right) < 1 || vector.DistanceXZ(left, right) < 1) return false;
// Radii come from installed Mi8_base.et's authored landing-gear configuration.
// Every wheel needs a short, upward-facing static collision directly below.
bool a = WheelSupported(aircraft, front, 0.30, diagnostics);
bool b = WheelSupported(aircraft, left, 0.45, diagnostics);
bool c = WheelSupported(aircraft, right, 0.45, diagnostics);
return a && b && c;
}
}
@@ -0,0 +1,48 @@
// Round-owned server service; only the aircraft reference is replicated for action visibility.
modded class ERR_GameMode
{
protected ref ERR_CasualtyLoadingService m_ERRCasualtyLoading;
[RplProp()]
protected RplId m_ERRCasualtyAircraftId = RplId.Invalid();
ERR_CasualtyLoadingService CasualtyLoading() { return m_ERRCasualtyLoading; }
Vehicle CasualtyLoadingAircraft()
{
if (Replication.IsServer()) return ExtractionVehicle();
RplComponent component = RplComponent.Cast(Replication.FindItem(m_ERRCasualtyAircraftId));
if (!component) return null;
return Vehicle.Cast(component.GetEntity());
}
protected void ERR_UpdateCasualtyAircraft(float now)
{
Vehicle aircraft = ExtractionVehicle();
if (!aircraft)
{
if (m_ERRCasualtyAircraftId != RplId.Invalid()) { m_ERRCasualtyAircraftId = RplId.Invalid(); Replication.BumpMe(); }
return;
}
RplComponent component = RplComponent.Cast(aircraft.FindComponent(RplComponent));
if (!component || m_ERRCasualtyAircraftId == component.Id()) return;
m_ERRCasualtyAircraftId = component.Id();
Replication.BumpMe();
}
protected void ERR_StopCasualtyLoading()
{
if (m_ERRCasualtyLoading)
{
Players().OnChanged().Remove(m_ERRCasualtyLoading.RosterChanged);
OnTick().Remove(m_ERRCasualtyLoading.Tick);
m_ERRCasualtyLoading.Stop();
}
OnTick().Remove(ERR_UpdateCasualtyAircraft);
}
protected override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
if (!Replication.IsServer() || SCR_Global.IsEditMode()) return;
m_ERRCasualtyLoading = new ERR_CasualtyLoadingService(this);
OnTick().Insert(ERR_UpdateCasualtyAircraft);
OnTick().Insert(m_ERRCasualtyLoading.Tick);
Players().OnChanged().Insert(m_ERRCasualtyLoading.RosterChanged);
OnStop().Insert(ERR_StopCasualtyLoading);
}
}
@@ -0,0 +1,75 @@
// Only successor service methods initiate this controller-owned handshake.
// No caller-supplied entity/seat RPC can ask the server to load another player.
modded class SCR_PlayerController
{
protected RplId m_ERRPreparedLoadMode = RplId.Invalid();
protected int m_ERRPreparedLoadNonce;
protected int m_ERRPreparedLoadClock;
protected int m_ERRLastLoadNonce;
void ERR_PrepareCasualtyLoad(RplId modeId, int nonce)
{
if (!Replication.IsServer()) return;
if (this == GetGame().GetPlayerController()) ERR_PrepareCasualtyLoadOwner(modeId, nonce);
else Rpc(ERR_PrepareCasualtyLoadOwner, modeId, nonce);
}
[RplRpc(RplChannel.Reliable, RplRcver.Owner)]
protected void ERR_PrepareCasualtyLoadOwner(RplId modeId, int nonce)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (this != GetGame().GetPlayerController() || !mode || !mode.Active() || mode.Phase() != ERR_Phase.EXTRACTION || ERR_CasualtyLoadingRules.EntityId(mode) != modeId || !ERR_CasualtyLoadingRules.GroundSettled(GetControlledEntity())) return;
if (m_ERRPreparedLoadMode == modeId && nonce <= m_ERRLastLoadNonce) return;
if (nonce <= 0) return;
m_ERRPreparedLoadMode = modeId;
m_ERRPreparedLoadNonce = nonce;
m_ERRLastLoadNonce = nonce;
m_ERRPreparedLoadClock = System.GetTickCount();
if (Replication.IsServer()) ERR_CasualtyLoadReady(modeId, nonce);
else Rpc(ERR_CasualtyLoadReady, modeId, nonce);
}
[RplRpc(RplChannel.Reliable, RplRcver.Server)]
protected void ERR_CasualtyLoadReady(RplId modeId, int nonce)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (!Replication.IsServer() || !mode || ERR_CasualtyLoadingRules.EntityId(mode) != modeId || !mode.CasualtyLoading()) return;
mode.CasualtyLoading().OwnerReady(this, nonce);
}
void ERR_CommitCasualtyLoad(RplId modeId, int nonce, RplId callerId, RplId actorId, RplId vehicleId, RplId ownerId, int slotId)
{
if (!Replication.IsServer()) return;
if (this == GetGame().GetPlayerController()) ERR_CommitCasualtyLoadOwner(modeId, nonce, callerId, actorId, vehicleId, ownerId, slotId);
else Rpc(ERR_CommitCasualtyLoadOwner, modeId, nonce, callerId, actorId, vehicleId, ownerId, slotId);
}
[RplRpc(RplChannel.Reliable, RplRcver.Owner)]
protected void ERR_CommitCasualtyLoadOwner(RplId modeId, int nonce, RplId callerId, RplId actorId, RplId vehicleId, RplId ownerId, int slotId)
{
bool lease = this == GetGame().GetPlayerController() && m_ERRPreparedLoadMode == modeId && m_ERRPreparedLoadNonce == nonce && ERR_CasualtyLoadingRules.Within(m_ERRPreparedLoadClock, System.GetTickCount(), 3000);
if (m_ERRPreparedLoadMode == modeId && m_ERRPreparedLoadNonce == nonce) m_ERRPreparedLoadNonce = 0;
// Consume the local lease before the native call so duplicates cannot act.
bool accepted;
ERR_GameMode mode = ERR_GameMode.Get();
IEntity actor = GetControlledEntity();
IEntity caller = ERR_CasualtyLoadingRules.Entity(callerId);
Vehicle vehicle = Vehicle.Cast(ERR_CasualtyLoadingRules.Entity(vehicleId));
IEntity owner = ERR_CasualtyLoadingRules.Entity(ownerId);
if (lease && mode && ERR_CasualtyLoadingRules.EntityId(mode) == modeId && ERR_CasualtyLoadingRules.EntityId(actor) == actorId && vehicle == mode.CasualtyLoadingAircraft() && ERR_CasualtyLoadingRules.Nearby(mode, caller, actor) && owner)
{
BaseCompartmentManagerComponent manager = BaseCompartmentManagerComponent.Cast(owner.FindComponent(BaseCompartmentManagerComponent));
SCR_CompartmentAccessComponent access = SCR_CompartmentAccessComponent.Cast(actor.FindComponent(SCR_CompartmentAccessComponent));
BaseCompartmentSlot seat;
if (manager) seat = manager.FindCompartment(slotId);
if (access && ERR_CasualtyLoadingRules.TransportBench(seat, vehicle) && seat.GetOwner() == owner && !seat.GetOccupant() && seat.IsCompartmentAccessible() && !seat.IsGetInLockedFor(actor) && (!seat.IsReserved() || seat.IsReservedBy(actor)))
accepted = access.GetInVehicle(owner, seat, true, -1, ECloseDoorAfterActions.INVALID, false);
}
// Missing replicated entities or rejected native entry fail once; never retry.
if (Replication.IsServer()) ERR_CasualtyLoadResult(modeId, nonce, accepted);
else Rpc(ERR_CasualtyLoadResult, modeId, nonce, accepted);
}
[RplRpc(RplChannel.Reliable, RplRcver.Server)]
protected void ERR_CasualtyLoadResult(RplId modeId, int nonce, bool accepted)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (!Replication.IsServer() || !mode || ERR_CasualtyLoadingRules.EntityId(mode) != modeId || !mode.CasualtyLoading()) return;
mode.CasualtyLoading().OwnerResult(this, nonce, accepted);
}
}
@@ -0,0 +1,305 @@
// First release supports only the registered Mi8 extraction aircraft's physical
// child transport benches. Nothing changes health, ownership, or seat classes.
class ERR_CasualtyLoadingRules
{
static int RoundAction(int phase)
{
if (phase == ERR_Phase.PREPARING) return 0;
if (ERR_MissionRules.Terminal(phase)) return 2;
return 1;
}
static bool ObserveTicket(bool committed, bool physical, bool authorized)
{
return physical && (committed || authorized);
}
static bool Within(int started, int now, int limit) { return now >= started && now - started < limit; }
static bool SettledFor(int started, int observed, int now)
{
return started >= 0 && now >= started && now - started >= 5000 && Within(observed, now, 2000);
}
static bool Ranges(float callerToCasualty, float callerToAircraft, float casualtyToAircraft)
{
return callerToCasualty >= 0 && callerToCasualty <= 3 && callerToAircraft >= 0 && callerToAircraft <= 12 && casualtyToAircraft >= 0 && casualtyToAircraft <= 12;
}
static bool AircraftMotion(bool groundContact, float up, float speed, float angularSpeed)
{
return groundContact && up >= 0.85 && speed >= 0 && speed <= 0.5 && angularSpeed >= 0 && angularSpeed <= 0.1;
}
static RplId EntityId(IEntity entity)
{
if (!entity) return RplId.Invalid();
RplComponent component = RplComponent.Cast(entity.FindComponent(RplComponent));
if (!component) return RplId.Invalid();
return component.Id();
}
static IEntity Entity(RplId id)
{
if (id == RplId.Invalid()) return null;
RplComponent component = RplComponent.Cast(Replication.FindItem(id));
if (!component) return null;
return component.GetEntity();
}
static bool Down(IEntity actor)
{
if (!ERR_Actors.Alive(actor)) return false;
CharacterControllerComponent controller = CharacterControllerComponent.Cast(actor.FindComponent(CharacterControllerComponent));
return controller && controller.GetLifeState() == ECharacterLifeState.INCAPACITATED;
}
static bool GroundSettled(IEntity actor)
{
if (!Down(actor) || CompartmentAccessComponent.GetVehicleIn(actor)) return false;
CharacterAnimationComponent animation = CharacterAnimationComponent.Cast(actor.FindComponent(CharacterAnimationComponent));
SCR_CompartmentAccessComponent access = SCR_CompartmentAccessComponent.Cast(actor.FindComponent(SCR_CompartmentAccessComponent));
Physics physics = actor.GetPhysics();
return animation && !animation.PhysicsIsFalling() && physics && physics.GetVelocity().Length() <= 0.5 && access && !access.IsGettingIn() && !access.IsGettingOut();
}
static bool AircraftReady(Vehicle aircraft)
{
if (!ERR_Actors.Alive(aircraft)) return false;
HelicopterControllerComponent controller = HelicopterControllerComponent.Cast(aircraft.FindComponent(HelicopterControllerComponent));
Physics physics = aircraft.GetPhysics();
if (!controller || !controller.GetSimulation() || !physics) return false;
vector transform[4]; aircraft.GetWorldTransform(transform);
if (!AircraftMotion(true, transform[1][1], physics.GetVelocity().Length(), physics.GetAngularVelocity().Length())) return false;
if (controller.GetSimulation().HasAnyGroundContact()) return true;
return ERR_CasualtyGroundSupport.Parked(aircraft);
}
static bool LineOfSight(IEntity caller, IEntity casualty)
{
ChimeraCharacter rescuer = ChimeraCharacter.Cast(caller);
ChimeraCharacter patient = ChimeraCharacter.Cast(casualty);
if (!rescuer || !patient || !GetGame()) return false;
TraceParam trace = new TraceParam();
trace.Start = rescuer.AimingPosition();
trace.End = patient.AimingPosition();
trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
trace.LayerMask = TRACE_LAYER_CAMERA;
trace.Exclude = caller;
if (GetGame().GetWorld().TraceMove(trace, null) >= 1) return true;
// Hitting the intended body's clothing/attachment is still sight of that body.
IEntity hit = trace.TraceEnt;
while (hit)
{
if (hit == casualty) return true;
hit = hit.GetParent();
}
return false;
}
static bool Nearby(ERR_GameMode mode, IEntity caller, IEntity casualty)
{
if (!mode || !mode.Active() || mode.Phase() != ERR_Phase.EXTRACTION || !caller || caller == casualty) return false;
CharacterControllerComponent rescuer = CharacterControllerComponent.Cast(caller.FindComponent(CharacterControllerComponent));
if (!ERR_Actors.CanFight(caller) || !rescuer || rescuer.GetLifeState() != ECharacterLifeState.ALIVE || !GroundSettled(casualty) || CompartmentAccessComponent.GetVehicleIn(caller)) return false;
Vehicle aircraft = mode.CasualtyLoadingAircraft();
if (!aircraft || !Ranges(vector.Distance(caller.GetOrigin(), casualty.GetOrigin()), vector.Distance(caller.GetOrigin(), aircraft.GetOrigin()), vector.Distance(casualty.GetOrigin(), aircraft.GetOrigin())) || !AircraftReady(aircraft)) return false;
Faction faction = mode.PlayerFaction();
return faction && SCR_FactionManager.SGetFaction(caller) == faction && SCR_FactionManager.SGetFaction(casualty) == faction && LineOfSight(caller, casualty);
}
static bool TransportBench(BaseCompartmentSlot seat, Vehicle aircraft)
{
if (!seat || !aircraft || seat.GetType() != ECompartmentType.CARGO || SCR_PatientCompartmentSlot.Cast(seat)) return false;
IEntity owner = seat.GetOwner();
if (!owner || owner == aircraft || !owner.GetPrefabData() || !owner.GetPrefabData().GetPrefabName().Contains("VehPart_MI8_seats")) return false;
while (owner)
{
if (owner == aircraft) return true;
owner = owner.GetParent();
}
return false;
}
}
class ERR_CasualtySettling
{
IEntity Actor;
UUID Account;
int Connection;
int Since;
int Observed;
}
class ERR_CasualtyLoadTicket
{
IEntity Caller;
IEntity Casualty;
Vehicle Aircraft;
BaseCompartmentSlot Seat;
UUID CallerAccount;
UUID CasualtyAccount;
int CallerConnection;
int CasualtyConnection;
int Nonce;
int Started;
int CommittedAt;
bool Committed;
bool OwnerReported;
}
class ERR_CasualtyLoadingService
{
protected ERR_GameMode m_Mode;
protected bool m_Stopped;
protected int m_NextNonce;
protected ref array<ref ERR_CasualtySettling> m_Settling = {};
protected ref array<ref ERR_CasualtyLoadTicket> m_Pending = {};
protected ref ScriptInvoker m_OnResolved = new ScriptInvoker();
void ERR_CasualtyLoadingService(ERR_GameMode mode) { m_Mode = mode; }
ScriptInvoker OnResolved() { return m_OnResolved; } // (IEntity casualty, bool physicallyLoaded)
int PendingCount() { return m_Pending.Count(); }
protected ERR_PlayerLife CurrentLife(IEntity actor)
{
if (!m_Mode || !m_Mode.Players()) return null;
return m_Mode.Players().CurrentActor(actor);
}
protected bool SameLife(IEntity actor, UUID account, int connection)
{
ERR_PlayerLife life = CurrentLife(actor);
return life && life.AccountId == account && life.ConnectionId == connection;
}
protected bool Settled(IEntity actor, int now)
{
foreach (ERR_CasualtySettling sample : m_Settling)
if (sample.Actor == actor && SameLife(actor, sample.Account, sample.Connection)) return ERR_CasualtyLoadingRules.GroundSettled(actor) && ERR_CasualtyLoadingRules.SettledFor(sample.Since, sample.Observed, now);
return false;
}
protected void Observe(int now)
{
for (int index = m_Settling.Count() - 1; index >= 0; index--)
{
ERR_CasualtySettling sample = m_Settling[index];
if (!SameLife(sample.Actor, sample.Account, sample.Connection) || !ERR_CasualtyLoadingRules.GroundSettled(sample.Actor) || !ERR_CasualtyLoadingRules.Within(sample.Observed, now, 2000)) m_Settling.Remove(index);
else sample.Observed = now;
}
array<ref ERR_PlayerLife> lives = {}; m_Mode.Players().Participants(lives);
foreach (ERR_PlayerLife life : lives)
{
if (!CurrentLife(life.Actor) || !ERR_CasualtyLoadingRules.GroundSettled(life.Actor)) continue;
bool found;
foreach (ERR_CasualtySettling tracked : m_Settling) if (tracked.Actor == life.Actor) { found = true; break; }
if (found) continue;
ERR_CasualtySettling added = new ERR_CasualtySettling();
added.Actor = life.Actor; added.Account = life.AccountId; added.Connection = life.ConnectionId; added.Since = now; added.Observed = now;
m_Settling.Insert(added);
}
}
protected bool PendingActor(IEntity caller, IEntity casualty)
{
foreach (ERR_CasualtyLoadTicket pending : m_Pending)
if (pending.Caller == caller || pending.Casualty == casualty) return true;
return false;
}
protected BaseCompartmentSlot AvailableSeat(IEntity casualty, Vehicle aircraft)
{
array<BaseCompartmentSlot> seats = {}; m_Mode.Extraction().Seats(seats);
foreach (BaseCompartmentSlot seat : seats)
{
if (!ERR_CasualtyLoadingRules.TransportBench(seat, aircraft) || seat.GetOccupant() || seat.IsReserved() || !seat.IsCompartmentAccessible() || seat.IsGetInLockedFor(casualty)) continue;
bool pendingSeat;
foreach (ERR_CasualtyLoadTicket pending : m_Pending) if (pending.Seat == seat) { pendingSeat = true; break; }
if (!pendingSeat) return seat;
}
return null;
}
bool CanLoad(IEntity caller, IEntity casualty)
{
if (!Replication.IsServer() || m_Stopped || !ERR_CasualtyLoadingRules.Nearby(m_Mode, caller, casualty)) return false;
if (!CurrentLife(caller) || !CurrentLife(casualty) || !Settled(casualty, System.GetTickCount()) || PendingActor(caller, casualty)) return false;
return AvailableSeat(casualty, m_Mode.ExtractionVehicle()) != null;
}
bool Begin(IEntity caller, IEntity casualty)
{
if (!CanLoad(caller, casualty) || m_NextNonce >= 2147483646) return false;
ERR_PlayerLife callerLife = CurrentLife(caller);
ERR_PlayerLife casualtyLife = CurrentLife(casualty);
SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(casualtyLife.ConnectionId));
if (!controller || ERR_CasualtyLoadingRules.EntityId(m_Mode) == RplId.Invalid() || ERR_CasualtyLoadingRules.EntityId(caller) == RplId.Invalid() || ERR_CasualtyLoadingRules.EntityId(casualty) == RplId.Invalid() || ERR_CasualtyLoadingRules.EntityId(m_Mode.ExtractionVehicle()) == RplId.Invalid()) return false;
ERR_CasualtyLoadTicket ticket = new ERR_CasualtyLoadTicket();
ticket.Caller = caller; ticket.Casualty = casualty; ticket.Aircraft = m_Mode.ExtractionVehicle();
ticket.Seat = AvailableSeat(casualty, ticket.Aircraft);
if (!ticket.Seat || ERR_CasualtyLoadingRules.EntityId(ticket.Seat.GetOwner()) == RplId.Invalid()) return false;
ticket.CallerAccount = callerLife.AccountId; ticket.CasualtyAccount = casualtyLife.AccountId;
ticket.CallerConnection = callerLife.ConnectionId; ticket.CasualtyConnection = casualtyLife.ConnectionId;
ticket.Started = System.GetTickCount(); ticket.Nonce = ++m_NextNonce;
m_Pending.Insert(ticket);
ticket.Seat.SetReserved(casualty);
if (!ticket.Seat.IsReservedBy(casualty)) { Resolve(ticket, false); return false; }
// Preparation never moves the actor. Its owner starts a local real-time lease.
controller.ERR_PrepareCasualtyLoad(ERR_CasualtyLoadingRules.EntityId(m_Mode), ticket.Nonce);
return true;
}
protected ERR_CasualtyLoadTicket Ticket(SCR_PlayerController controller, int nonce)
{
if (!controller || !GetGame() || !GetGame().GetPlayerManager() || GetGame().GetPlayerManager().GetPlayerController(controller.GetPlayerId()) != controller) return null;
foreach (ERR_CasualtyLoadTicket ticket : m_Pending)
if (ticket.Nonce == nonce && ticket.CasualtyConnection == controller.GetPlayerId() && ticket.Casualty == controller.GetControlledEntity()) return ticket;
return null;
}
void OwnerReady(SCR_PlayerController controller, int nonce)
{
if (!Replication.IsServer() || m_Stopped) return;
ERR_CasualtyLoadTicket ticket = Ticket(controller, nonce);
if (!ticket || ticket.Committed) return;
int now = System.GetTickCount();
if (!ValidTicket(ticket) || !ERR_CasualtyLoadingRules.Within(ticket.Started, now, 5000) || !Settled(ticket.Casualty, now) || !ERR_CasualtyLoadingRules.Nearby(m_Mode, ticket.Caller, ticket.Casualty) || ticket.Seat.GetOccupant() || !ticket.Seat.IsCompartmentAccessible() || ticket.Seat.IsGetInLockedFor(ticket.Casualty) || !ticket.Seat.IsReservedBy(ticket.Casualty)) { Resolve(ticket, false); return; }
ticket.Committed = true; ticket.CommittedAt = now;
// Final authority/physical validation is the commit boundary. No retries.
controller.ERR_CommitCasualtyLoad(ERR_CasualtyLoadingRules.EntityId(m_Mode), nonce, ERR_CasualtyLoadingRules.EntityId(ticket.Caller), ERR_CasualtyLoadingRules.EntityId(ticket.Casualty), ERR_CasualtyLoadingRules.EntityId(ticket.Aircraft), ERR_CasualtyLoadingRules.EntityId(ticket.Seat.GetOwner()), ticket.Seat.GetCompartmentSlotID());
}
void OwnerResult(SCR_PlayerController controller, int nonce, bool accepted)
{
if (!Replication.IsServer() || m_Stopped) return;
ERR_CasualtyLoadTicket ticket = Ticket(controller, nonce);
if (!ticket || !ticket.Committed || ticket.OwnerReported) return;
ticket.OwnerReported = true;
if (!accepted) Print("Rereintroduced [casualty]: owner declined loading; observing physical outcome until expiry.");
// Neither positive nor negative client acknowledgements release a reserved
// seat while an authorized owner command could still be in flight.
}
protected bool PhysicalTicket(ERR_CasualtyLoadTicket ticket)
{
// Death cannot revoke an in-flight commit. Keep the vacant seat reserved
// while the captured body exists; its owner may still see the prior state.
return m_Mode && m_Mode.Active() && m_Mode.Phase() == ERR_Phase.EXTRACTION && ticket.Aircraft == m_Mode.ExtractionVehicle() && ERR_Actors.Alive(ticket.Aircraft) && ticket.Casualty != null && ERR_CasualtyLoadingRules.TransportBench(ticket.Seat, ticket.Aircraft);
}
protected bool ValidTicket(ERR_CasualtyLoadTicket ticket)
{
return m_Mode && m_Mode.Active() && m_Mode.Phase() == ERR_Phase.EXTRACTION && ticket.Aircraft == m_Mode.ExtractionVehicle() && ERR_Actors.Alive(ticket.Aircraft) && ERR_Actors.Alive(ticket.Casualty) && SameLife(ticket.Caller, ticket.CallerAccount, ticket.CallerConnection) && SameLife(ticket.Casualty, ticket.CasualtyAccount, ticket.CasualtyConnection) && ERR_CasualtyLoadingRules.TransportBench(ticket.Seat, ticket.Aircraft);
}
protected void Resolve(ERR_CasualtyLoadTicket ticket, bool success)
{
int index = m_Pending.Find(ticket); if (index < 0) return;
m_Pending.Remove(index);
if (ticket.Seat && ticket.Casualty && ticket.Seat.IsReservedBy(ticket.Casualty)) ticket.Seat.SetReserved(null);
m_OnResolved.Invoke(ticket.Casualty, success);
}
void Tick(float worldNow)
{
if (!Replication.IsServer() || m_Stopped || !m_Mode) return;
int roundAction = ERR_CasualtyLoadingRules.RoundAction(m_Mode.Phase());
if (roundAction == 0) return;
if (roundAction == 2) { Stop(); return; }
int now = System.GetTickCount();
Observe(now);
array<ref ERR_CasualtyLoadTicket> snapshot = {}; foreach (ERR_CasualtyLoadTicket item : m_Pending) snapshot.Insert(item);
foreach (ERR_CasualtyLoadTicket ticket : snapshot)
{
if (m_Stopped) return;
// Commit authorizes one move of the captured body; a later caller/target
// disconnect cannot revoke that command or release its seat prematurely.
if (!ERR_CasualtyLoadingRules.ObserveTicket(ticket.Committed, PhysicalTicket(ticket), ValidTicket(ticket))) { Resolve(ticket, false); continue; }
bool aboard = CompartmentAccessComponent.GetVehicleIn(ticket.Casualty) == ticket.Aircraft && ticket.Seat.GetOccupant() == ticket.Casualty;
if (aboard && ticket.Committed) { Resolve(ticket, ERR_Actors.Alive(ticket.Casualty)); continue; }
if (ticket.Committed)
{
// Owner's prepare-to-commit lease is only 3s; this 8s observation budget
// leaves room for replication. Timeouts do not issue compensating teleports.
if (!ERR_CasualtyLoadingRules.Within(ticket.CommittedAt, now, 8000)) Resolve(ticket, false);
}
else if (!ERR_CasualtyLoadingRules.Within(ticket.Started, now, 5000) || !ERR_CasualtyLoadingRules.Nearby(m_Mode, ticket.Caller, ticket.Casualty)) Resolve(ticket, false);
}
}
void RosterChanged(int connection) { if (GetGame()) Tick(GetGame().GetWorld().GetWorldTime()); }
void Stop()
{
if (!Replication.IsServer() || m_Stopped) return;
m_Stopped = true; m_Settling.Clear();
while (!m_Pending.IsEmpty()) Resolve(m_Pending[m_Pending.Count() - 1], false);
}
}
@@ -0,0 +1,51 @@
// Read replicated discovery locally. A server-wide marker list never leaks
// locations which have not been recovered through gameplay.
modded class ERR_LocationComponent
{
protected ref SCR_MapMarkerBase m_ERRMarker;
protected int m_ERRShown;
protected string m_ERRShownLabel;
protected override void EOnInit(IEntity owner)
{
super.EOnInit(owner);
if (RplSession.Mode() != RplMode.Dedicated && !SCR_Global.IsEditMode())
GetGame().GetCallqueue().CallLater(ERR_UpdateMarker, 1500, true);
}
protected void ERR_UpdateMarker()
{
if (!GetGame().GetPlayerController() || Knowledge() <= 0 || (Knowledge() == m_ERRShown && Label() == m_ERRShownLabel)) return;
SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance();
if (!manager || !manager.GetMarkerConfig()) return;
if (!m_ERRMarker)
{
m_ERRMarker = new SCR_MapMarkerBase();
m_ERRMarker.SetType(SCR_EMapMarkerType.PLACED_CUSTOM);
vector p = Position();
m_ERRMarker.SetWorldPos(Math.Round(p[0]), Math.Round(p[2]));
m_ERRMarker.SetMarkerConfigID(0);
manager.InsertStaticMarker(m_ERRMarker, true);
}
string label = "Unknown location";
if (Knowledge() == 2)
{
if (!Label().IsEmpty()) label = Label();
else if (Kind() == ERR_LocationKind.RADIO) label = "Radio station";
else if (Kind() == ERR_LocationKind.EXTRACTION) label = "Initial helicopter pickup site";
else if (Kind() == ERR_LocationKind.DEPOT) label = "Supply cache";
else if (Kind() == ERR_LocationKind.PRISON) label = "Prison";
else label = Id();
}
m_ERRMarker.SetCustomText(label);
m_ERRShown = Knowledge();
m_ERRShownLabel = Label();
}
protected override void OnDelete(IEntity owner)
{
if (GetGame()) GetGame().GetCallqueue().Remove(ERR_UpdateMarker);
SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance();
if (manager && m_ERRMarker) manager.RemoveStaticMarker(m_ERRMarker);
m_ERRMarker = null;
super.OnDelete(owner);
}
}
@@ -0,0 +1,62 @@
// Base mission discovery: recovering physical documents works without companions.
// The Intel addon optionally assigns extra documents to enemy inventories.
class ERR_DiscoveryService
{
protected ERR_GameMode m_Mode;
protected ref set<IEntity> m_Spent = new set<IEntity>();
void ERR_DiscoveryService(ERR_GameMode mode) { m_Mode = mode; }
static void Folders(InventoryStorageManagerComponent inventory, out array<IEntity> folders)
{
folders.Clear();
SCR_PrefabNamePredicate predicate = new SCR_PrefabNamePredicate();
predicate.prefabName = ERR_Resources.IntelFolder();
array<IEntity> intel = {};
inventory.FindItems(intel, predicate, EStoragePurpose.PURPOSE_ANY);
foreach (IEntity folder : intel)
if (folder && !folders.Contains(folder)) folders.Insert(folder);
array<IEntity> objectives = {};
predicate.prefabName = ERR_Resources.ObjectiveDocument();
inventory.FindItems(objectives, predicate, EStoragePurpose.PURPOSE_ANY);
foreach (IEntity objective : objectives)
if (objective && !folders.Contains(objective)) folders.Insert(objective);
}
void Tick(float now)
{
if (!Replication.IsServer()) return;
array<IEntity> players = {};
ERR_Actors.Players(players);
foreach (IEntity player : players) Recover(player);
}
protected void Recover(IEntity player)
{
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(player.FindComponent(InventoryStorageManagerComponent));
if (!inventory) return;
array<IEntity> folders = {};
Folders(inventory, folders);
foreach (IEntity folder : folders)
{
if (!folder || m_Spent.Contains(folder) || m_Spent.Count() >= 4096) continue;
array<ERR_LocationComponent> locations = {};
m_Mode.Locations(locations);
array<ERR_LocationComponent> eligible = {};
ERR_DocumentComponent document = ERR_DocumentComponent.Cast(folder.FindComponent(ERR_DocumentComponent));
foreach (ERR_LocationComponent location : locations)
{
if (!location || location.Knowledge() >= 2) continue;
if (document)
{
if (location.Id() == document.TargetId()) eligible.Insert(location);
}
else if (location.Kind() != ERR_LocationKind.PRISON && location.Kind() != ERR_LocationKind.EXTRACTION) eligible.Insert(location);
}
if (eligible.IsEmpty()) continue;
ERR_LocationComponent chosen = eligible.GetRandomElement();
if (!chosen.Discover(Math.RandomInt(0, 100), m_Mode.Settings().Get("intelRevealChancePercent"))) continue;
m_Spent.Insert(folder);
PrintFormat("Rereintroduced [intel]: player %1 recovered folder; location=%2 knowledge=%3", GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(player), chosen.Id(), chosen.Knowledge());
}
}
void Stop() { m_Spent.Clear(); }
}
@@ -0,0 +1,8 @@
[ComponentEditorProps(category: "Rereintroduced", description: "Physical document identifying one authored objective")]
class ERR_DocumentComponentClass : ScriptComponentClass {}
class ERR_DocumentComponent : ScriptComponent
{
protected string m_TargetId;
void SetTarget(string id) { if (Replication.IsServer()) m_TargetId = id; }
string TargetId() { return m_TargetId; }
}
@@ -0,0 +1,164 @@
// The server applies optional date/weather choices once at round preparation.
// Zero values preserve the world's authored environment and existing defaults.
class ERR_EnvironmentService
{
protected TimeAndWeatherManagerEntity m_Manager;
protected bool m_Started;
protected bool m_Stopped;
protected int m_DateCode;
protected int m_Profile;
static string Pad2(int value)
{
if (value < 10) return "0" + value.ToString();
return value.ToString();
}
static string Date(int code)
{
if (code == 0) return "authored";
if (!ERR_Settings.Valid("startDateCode", code)) return "unavailable";
int year = 1900 + code / 10000;
int month = (code % 10000) / 100;
int day = code % 100;
return year.ToString() + "-" + Pad2(month) + "-" + Pad2(day);
}
static bool ParseDate(string text, out int code)
{
if (text == "authored") { code = 0; return true; }
if (text.Length() != 10 || text.Substring(4, 1) != "-" || text.Substring(7, 1) != "-") return false;
int year, month, day;
if (!ERR_CommandArguments.Integer(text.Substring(0, 4), year) || !ERR_CommandArguments.Integer(text.Substring(5, 2), month) || !ERR_CommandArguments.Integer(text.Substring(8, 2), day)) return false;
if (year < 1900 || year > 2050 || month < 1 || month > 12 || day < 1 || day > 31) return false;
int parsed = (year - 1900) * 10000 + month * 100 + day;
if (!ERR_Settings.Valid("startDateCode", parsed)) return false;
code = parsed;
return true;
}
static string ProfileName(int profile)
{
if (profile == 0) return "authored";
if (profile == 1) return "clear";
if (profile == 2) return "overcast";
if (profile == 3) return "rain";
return "unavailable";
}
static string WeatherStateName(int profile)
{
if (profile == 1) return "Clear";
if (profile == 2) return "Overcast";
if (profile == 3) return "Rainy";
return "";
}
static bool ParseProfile(string text, out int profile)
{
if (text == "authored") { profile = 0; return true; }
if (text == "clear") { profile = 1; return true; }
if (text == "overcast") { profile = 2; return true; }
if (text == "rain" || text == "rainy") { profile = 3; return true; }
return false;
}
static bool HasWeatherState(TimeAndWeatherManagerEntity manager, string name)
{
if (!manager || name.IsEmpty()) return false;
array<ref WeatherState> states = {};
manager.GetWeatherStatesList(states);
foreach (WeatherState state : states)
if (state && state.GetStateName() == name) return true;
return false;
}
bool Start(ERR_GameMode mode)
{
if (!Replication.IsServer() || !mode || !mode.Settings()) return false;
ChimeraWorld world = ChimeraWorld.CastFrom(mode.GetWorld());
if (!world) return false;
return StartOn(world.GetTimeAndWeatherManager(), mode.Settings().Get("startDateCode"), mode.Settings().Get("weatherProfile"));
}
protected bool StartOn(TimeAndWeatherManagerEntity manager, int dateCode, int profile)
{
if (!Replication.IsServer() || m_Stopped) return false;
if (m_Started) return true;
if (!manager || !ERR_Settings.Valid("startDateCode", dateCode) || !ERR_Settings.Valid("weatherProfile", profile)) return false;
int year = 1900 + dateCode / 10000;
int month = (dateCode % 10000) / 100;
int day = dateCode % 100;
if (dateCode != 0 && !manager.CheckValidDate(year, month, day)) return false;
string weather = WeatherStateName(profile);
BaseWeatherStateTransitionManager transitions = manager.GetTransitionManager();
if (profile != 0 && (!transitions || !manager.GetCurrentWeatherState() || !HasWeatherState(manager, weather))) return false;
int previousYear, previousMonth, previousDay;
manager.GetDate(previousYear, previousMonth, previousDay);
if (dateCode != 0 && !manager.SetDate(year, month, day, true)) return false;
if (profile != 0)
{
string previousWeather = manager.GetCurrentWeatherState().GetStateName();
bool previousLooping = manager.IsWeatherLooping();
// Use the native replicated weather route, never local editor previews.
// Loop the selected family; native variants/wind still follow vanilla rules.
manager.ForceWeatherTo(true, weather, 0, 24);
WeatherState current = manager.GetCurrentWeatherState();
WeatherState next = transitions.GetNextState();
if (!manager.IsWeatherLooping() || ((!current || current.GetStateName() != weather) && (!next || next.GetStateName() != weather)))
{
manager.ForceWeatherTo(previousLooping, previousWeather, 0, 24);
if (dateCode != 0) manager.SetDate(previousYear, previousMonth, previousDay, true);
return false;
}
}
m_Manager = manager;
m_DateCode = dateCode;
m_Profile = profile;
m_Started = true;
PrintFormat("Rereintroduced [environment]: date=%1 weather=%2", Date(dateCode), ProfileName(profile));
return true;
}
bool Started() { return m_Started && !m_Stopped; }
int DateCode() { return m_DateCode; }
int Profile() { return m_Profile; }
int CurrentDateCode()
{
if (!Started() || !m_Manager) return -1;
return (m_Manager.GetYear() - 1900) * 10000 + m_Manager.GetMonth() * 100 + m_Manager.GetDay();
}
string CurrentWeather()
{
if (!Started() || !m_Manager) return "unavailable";
WeatherState weather = m_Manager.GetCurrentWeatherState();
if (!weather) return "unavailable";
return weather.GetStateName();
}
string Status()
{
if (!Started()) return "Environment not started.";
return "Current date " + Date(CurrentDateCode()) + ", weather " + CurrentWeather() + " (round profile " + ProfileName(m_Profile) + ").";
}
void Stop() { m_Stopped = true; m_Manager = null; }
}
// Called after the server-owned admin authorization gate. Saving cannot change
// the active service; accepted changes are consumed by the next mission instance.
class ERR_EnvironmentCommands
{
static bool Execute(ERR_Settings settings, ERR_EnvironmentService environment, array<string> parts, array<string> replies)
{
if (!Replication.IsServer() || !settings || parts.Count() < 2 || parts[0] != "mission" || (parts[1] != "date" && parts[1] != "weather")) return false;
if (parts.Count() == 3 && parts[2] == "show")
{
if (environment) replies.Insert(environment.Status());
replies.Insert("Next round: date " + ERR_EnvironmentService.Date(settings.Get("startDateCode")) + ", weather " + ERR_EnvironmentService.ProfileName(settings.Get("weatherProfile")) + ".");
return true;
}
int value;
bool valid;
string key = "startDateCode";
if (parts[1] == "weather") key = "weatherProfile";
if (parts.Count() == 4 && parts[2] == "set")
{
if (key == "startDateCode") valid = ERR_EnvironmentService.ParseDate(parts[3], value);
else valid = ERR_EnvironmentService.ParseProfile(parts[3], value);
}
if (valid && settings.Set(key, value))
replies.Insert("Saved for next round: date " + ERR_EnvironmentService.Date(settings.Get("startDateCode")) + ", weather " + ERR_EnvironmentService.ProfileName(settings.Get("weatherProfile")) + ". Current round unchanged.");
else replies.Insert("Invalid environment or settings could not be saved. Use mission date set YYYY-MM-DD (1900-2050) or authored; mission weather set authored|clear|overcast|rain. Previous setting retained.");
return true;
}
}
@@ -0,0 +1,72 @@
[BaseContainerProps()]
class ERR_EscapeGameOverScreenInfo : SCR_BaseGameOverScreenInfo
{
protected ERR_PersonalEscapeResult PersonalResult(int playerId)
{
SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
if (!controller || controller.GetPlayerId() != playerId) return ERR_PersonalEscapeResult.UNKNOWN;
return controller.ERR_EscapeResult();
}
override string GetTitle(int playerId, array<int> otherPlayerIds)
{
string title = "The helicopter escaped";
if (PersonalResult(playerId) == ERR_PersonalEscapeResult.ESCAPED) title = "You escaped Everon";
#ifdef WORKBENCH
PrintFormat("ERR RESULT UI: player=%1 title=%2", playerId, title);
#endif
return title;
}
override string GetDebriefing(int playerId, array<int> otherPlayerIds)
{
ERR_PersonalEscapeResult result = PersonalResult(playerId);
if (result == ERR_PersonalEscapeResult.ESCAPED)
return "You crossed the extraction boundary aboard the helicopter.";
if (result == ERR_PersonalEscapeResult.MISSED) return "You did not escape with the helicopter.";
return "Your personal escape result is not available.";
}
}
// End data and the controller replicate independently. Refresh an already-open
// native result screen when the identity-derived controller result arrives.
modded class SCR_GameOverScreenContentUIComponent
{
protected bool m_ERREscapeContent;
override void InitContent(SCR_GameOverScreenUIContentData endScreenUIContent)
{
SCR_PlayerController.ERR_OnEscapeResultChanged().Remove(ERR_RefreshEscapeContent);
super.InitContent(endScreenUIContent);
m_ERREscapeContent = ERR_EscapeGameOverScreenInfo.Cast(endScreenUIContent.m_GameOverInfo) != null;
if (!m_ERREscapeContent) return;
SCR_PlayerController.ERR_OnEscapeResultChanged().Insert(ERR_RefreshEscapeContent);
ERR_RefreshEscapeContent();
}
protected void ERR_RefreshEscapeContent()
{
if (!m_ERREscapeContent || !m_wRoot) return;
SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
int playerId = -1;
if (controller) playerId = controller.GetPlayerId();
ERR_EscapeGameOverScreenInfo info = new ERR_EscapeGameOverScreenInfo();
TextWidget title = TextWidget.Cast(m_wRoot.FindAnyWidget(m_sTileName));
TextWidget debrief = TextWidget.Cast(m_wRoot.FindAnyWidget(m_sDebriefingName));
if (title) title.SetText(info.GetTitle(playerId, null));
if (debrief) debrief.SetText(info.GetDebriefing(playerId, null));
}
override void HandlerDeattached(Widget w)
{
SCR_PlayerController.ERR_OnEscapeResultChanged().Remove(ERR_RefreshEscapeContent);
m_ERREscapeContent = false;
super.HandlerDeattached(w);
}
}
[BaseContainerProps()]
class ERR_FailureGameOverScreenInfo : SCR_BaseGameOverScreenInfo
{
override string GetDebriefing(int playerId, array<int> otherPlayerIds)
{
ERR_GameMode mode = ERR_GameMode.Get();
if (mode && !mode.EndReason().IsEmpty()) return mode.EndReason();
return "No surviving prisoners can complete the escape, or the extraction helicopter has been lost.";
}
}
@@ -0,0 +1,112 @@
// Initial preparation only. A newly spawned vehicle may start asleep above its
// landing gear contact plane. Wake once, then observe native gravity/contact;
// never correct its transform, apply an impulse, or replenish its supplies.
class ERR_ExtractionPlacement
{
protected ERR_GameMode m_Mode;
protected Vehicle m_Aircraft;
protected bool m_Stopped;
protected int m_WakeCount;
protected float m_Deadline;
protected float m_StableSince = -1;
protected float m_LastObservation = -1;
protected float m_NextDiagnostic;
protected ERR_PrepareResult m_Result = ERR_PrepareResult.PENDING;
protected string m_Failure;
void ERR_ExtractionPlacement(ERR_GameMode mode, Vehicle aircraft)
{
m_Mode = mode; m_Aircraft = aircraft;
m_Deadline = GetGame().GetWorld().GetWorldTime() + 30000;
}
static bool CanWake(bool initialized, int count, float now, float deadline)
{
return initialized && count == 0 && now < deadline;
}
static bool Fresh(float previous, float now)
{
return previous >= 0 && now >= previous && now - previous <= 1500;
}
static bool QualificationAllowed(bool previouslyReady, float now, float deadline)
{
return previouslyReady || now < deadline;
}
static bool Stable(float since, float previous, float now)
{
return since >= 0 && previous >= since && now >= previous && now - previous <= 1500 && now - since >= 1000;
}
int WakeCount() { return m_WakeCount; }
bool Ready() { return !m_Stopped && m_Result == ERR_PrepareResult.READY; }
string FailureReason() { return m_Failure; }
void Stop() { m_Stopped = true; }
protected ERR_PrepareResult Fail(string reason)
{
m_Failure = reason; m_Result = ERR_PrepareResult.FAILED;
Print("Rereintroduced [extraction placement]: " + reason, LogLevel.ERROR);
return m_Result;
}
protected void Diagnostic(bool ready)
{
if (!m_Aircraft) return;
Physics physics = m_Aircraft.GetPhysics();
HelicopterControllerComponent controller = HelicopterControllerComponent.Cast(m_Aircraft.FindComponent(HelicopterControllerComponent));
vector entity[4]; m_Aircraft.GetWorldTransform(entity);
PrintFormat("ERR EXTRACTION PLACEMENT: wakes=%1 alive=%2 ready=%3 origin=%4 up=%5", m_WakeCount, ERR_Actors.Alive(m_Aircraft), ready, entity[3], entity[1][1]);
if (physics) PrintFormat("ERR EXTRACTION PHYSICS: dynamic=%1 awake=%2 speed=%3 angularSpeed=%4", physics.IsDynamic(), physics.IsActive(), physics.GetVelocity().Length(), physics.GetAngularVelocity().Length());
if (controller && controller.GetSimulation())
{
vector nativeTransform[4]; controller.GetSimulation().GetWorldTransform(nativeTransform);
PrintFormat("ERR EXTRACTION NATIVE: valid=%1 contact=%2 engine=%3 origin=%4 up=%5 entityDifference=%6", controller.GetSimulation().IsValid(), controller.GetSimulation().HasAnyGroundContact(), controller.GetSimulation().EngineIsOn(), nativeTransform[3], nativeTransform[1][1], vector.Distance(nativeTransform[3], entity[3]));
}
// Diagnostics read every wheel even while physics is awake. The strict parked
// fallback itself still requires sleep and never alters the vehicle.
vector front, left, right;
if (ERR_CasualtyGroundSupport.WheelCenter(m_Aircraft, "v_wheel_F", front, true)) ERR_CasualtyGroundSupport.WheelSupported(m_Aircraft, front, 0.30, true);
if (ERR_CasualtyGroundSupport.WheelCenter(m_Aircraft, "v_wheel_bL", left, true)) ERR_CasualtyGroundSupport.WheelSupported(m_Aircraft, left, 0.45, true);
if (ERR_CasualtyGroundSupport.WheelCenter(m_Aircraft, "v_wheel_bR", right, true)) ERR_CasualtyGroundSupport.WheelSupported(m_Aircraft, right, 0.45, true);
}
ERR_PrepareResult Poll(float now)
{
if (m_Stopped || m_Result == ERR_PrepareResult.FAILED) return ERR_PrepareResult.FAILED;
if (!Replication.IsServer() || !m_Mode || m_Mode.Phase() != ERR_Phase.PREPARING || m_Mode.ExtractionVehicle() != m_Aircraft) return Fail("initial aircraft ownership/phase changed");
if (!ERR_Actors.Alive(m_Aircraft) || !m_Aircraft.GetPrefabData() || !m_Aircraft.GetPrefabData().GetPrefabName().Contains("/Mi8MT/")) return Fail("registered initial Mi8 is missing, destroyed or unsupported");
Physics physics = m_Aircraft.GetPhysics();
HelicopterControllerComponent controller = HelicopterControllerComponent.Cast(m_Aircraft.FindComponent(HelicopterControllerComponent));
bool initialized = physics && physics.IsDynamic() && controller && controller.GetSimulation() && controller.GetSimulation().IsValid();
if (CanWake(initialized, m_WakeCount, now, m_Deadline))
{
// Production preparation owns the empty registered aircraft. The count is
// latched BEFORE the native call, preventing repeated wakes on any callback.
m_WakeCount = 1;
physics.SetActive(ActiveState.ACTIVE);
m_LastObservation = now;
Diagnostic(false);
m_NextDiagnostic = now + 1000;
return ERR_PrepareResult.PENDING; // never accept in the mutation frame
}
FuelManagerComponent fuel = FuelManagerComponent.Cast(m_Aircraft.FindComponent(FuelManagerComponent));
bool ready = initialized && m_WakeCount == 1 && fuel && fuel.HasFuel() && ERR_CasualtyLoadingRules.AircraftReady(m_Aircraft);
if (now >= m_NextDiagnostic)
{
Diagnostic(ready);
PrintFormat("ERR EXTRACTION FUEL: manager=%1 hasFuel=%2", fuel != null, fuel && fuel.HasFuel());
m_NextDiagnostic = now + 1000;
}
if (!ready || !Fresh(m_LastObservation, now)) m_StableSince = -1;
if (ready)
{
if (m_StableSince < 0) m_StableSince = now;
if (Stable(m_StableSince, m_LastObservation, now))
{
if (!QualificationAllowed(m_Result == ERR_PrepareResult.READY, now, m_Deadline)) return Fail("initial aircraft stable qualification missed the 30-second preparation deadline");
if (m_Result != ERR_PrepareResult.READY) Print("Rereintroduced [extraction placement]: native supported aircraft stable for one second, fuel present, exactly one initial wake");
m_Result = ERR_PrepareResult.READY;
m_LastObservation = now;
return m_Result;
}
}
m_Result = ERR_PrepareResult.PENDING;
m_LastObservation = now;
if (now >= m_Deadline) return Fail("initial aircraft did not become alive, fueled and physically supported/stable within 30 seconds; no replacement or repositioning requested");
return m_Result;
}
}

Some files were not shown because too many files have changed in this diff Show More