Build independent base gameplay and source-bound native verification
This commit is contained in:
@@ -4,7 +4,7 @@ An independently authored replacement for the abandoned Escapists base mission,
|
||||
|
||||
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.
|
||||
|
||||
The [original responsibility inventory](docs/original-feature-coverage.md) tracks all 299 original script entries across 18 unfinished areas. It is a filename-based coverage map, not proof of behavioral equivalence. Additional mission content, full support/logistics, manual gameplay, multiplayer, performance and release qualification remain unfinished. Native vehicle-resource errors and intermittent inherited catalog cleanup errors also remain.
|
||||
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
|
||||
|
||||
@@ -25,10 +25,8 @@ Run source/resource isolation and production-policy regressions with Python 3 an
|
||||
python3 tools/check.py
|
||||
```
|
||||
|
||||
For bounded hidden, muted local native tests, see [runtime testing](docs/runtime-testing.md). The expanded Core-only cache-loss fixture completes two escape/restart rounds with 148 assertions, including independent radio-clue routes, finite inventory, colliding outpost cover, blocked/clear discovery, catalog/admin checks and unconsciousness/recovery. The expanded full-companion fixture completes one primary-route escape with 48 assertions, including the existing HQ/Intel command aliases. A separate deliberate startup-failure fixture verifies that no population spawns and the mission cannot advance after invalid setup.
|
||||
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.
|
||||
|
||||
The Core radio/admission/objective-widget escape-and-restart checkpoint passes 374 checks across two rounds; the separate native admission fixture passes 54 and finite ground transport passes 23. The final isolated objective close/deletion test passes 30, and the companion death/spectator run passes 32. A historical clock run passes 194 checks with saved 06:15 / 4× settings; companion integration checkpoints pass 48 checks. The extraction/clock fixture passes 100 checks using twelve physical occupants, partial results, recycled connection IDs, local native end-screen updates, settings migration and native clock advancement. Separate negative setup fixtures reject unsuitable transport and invalid boundaries, rolling back authored content before player spawning. See [extraction](docs/extraction.md) and [mission clock](docs/mission-time.md) for their scope.
|
||||
|
||||
These fixtures teleport actors and the helicopter and manipulate native controller states. They do not prove manual escape/piloting, medical treatment, real remote reconnects, twelve-player correctness or improved FPS. [Validation evidence](docs/validation.md) preserves failed iterations and remaining engine errors. `docs/acceptance.json` keeps unverified release requirements pending.
|
||||
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.
|
||||
|
||||
@@ -209,6 +209,7 @@ class ERR_MortarBattery
|
||||
if (!Group)
|
||||
return 0;
|
||||
int count;
|
||||
array<IEntity> items = {};
|
||||
array<AIAgent> agents = {};
|
||||
Group.GetAgents(agents);
|
||||
foreach (AIAgent agent : agents)
|
||||
@@ -218,14 +219,10 @@ class ERR_MortarBattery
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(agent.GetControlledEntity().FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory)
|
||||
continue;
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == SHELL)
|
||||
count++;
|
||||
}
|
||||
ERR_Inventory.AppendUnique(inventory, items);
|
||||
}
|
||||
foreach (IEntity item : items)
|
||||
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == SHELL) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -246,7 +243,7 @@ class ERR_MortarBattery
|
||||
return 0;
|
||||
int count;
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
ERR_Inventory.Items(inventory, items);
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == SHELL)
|
||||
@@ -315,6 +312,7 @@ class ERR_MortarBattery
|
||||
if (InventoryShells(destination) > 0)
|
||||
return true;
|
||||
int nearbyDonors, donorShells, storageRejected, moveRejected;
|
||||
array<IEntity> consideredShells = {};
|
||||
foreach (AIAgent bearer : agents)
|
||||
{
|
||||
if (!bearer || !ERR_Actors.CanFight(bearer.GetControlledEntity()))
|
||||
@@ -327,11 +325,13 @@ class ERR_MortarBattery
|
||||
continue;
|
||||
nearbyDonors++;
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
ERR_Inventory.Items(inventory, items);
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (!item || !item.GetPrefabData() || item.GetPrefabData().GetPrefabName() != SHELL)
|
||||
continue;
|
||||
if (consideredShells.Contains(item)) continue;
|
||||
consideredShells.Insert(item);
|
||||
donorShells++;
|
||||
BaseInventoryStorageComponent storage = destination.FindStorageForItem(item, EStoragePurpose.PURPOSE_DEPOSIT);
|
||||
if (!storage) { storageRejected++; continue; }
|
||||
|
||||
@@ -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
|
||||
@@ -12,7 +12,6 @@ modded class ERR_AdminService
|
||||
if (section == "intel")
|
||||
{
|
||||
if (option == "carrying") return "aiIntelChancePercent";
|
||||
if (option == "reveal") return "intelRevealChancePercent";
|
||||
}
|
||||
return super.Setting(section, option);
|
||||
}
|
||||
@@ -32,6 +31,6 @@ modded class ERR_AdminService
|
||||
}
|
||||
protected override string Help()
|
||||
{
|
||||
return super.Help() + " | hq show|log | hq interval|squads|radius show|set N | intel carrying|reveal show|set N";
|
||||
return super.Help() + " | hq show|log | hq interval|squads|radius show|set N | intel carrying show|set N";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#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;
|
||||
@@ -28,8 +31,11 @@ modded class ERR_GameMode
|
||||
m_ERRTestRadioNetwork = outcome == "radio-network";
|
||||
m_ERRTestHQResponse = outcome == "hq-response";
|
||||
m_ERRTestMortar = outcome == "mortar-inventory";
|
||||
m_ERRTestPatrolHQ = outcome == "patrol-hq";
|
||||
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar;
|
||||
m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000;
|
||||
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");
|
||||
@@ -38,11 +44,17 @@ modded class ERR_GameMode
|
||||
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_ERRHQPatrolMovement) m_ERRHQPatrolMovement.Stop();
|
||||
if (m_ERRHQPatrolOrder) m_ERRHQPatrolOrder.Stop();
|
||||
}
|
||||
protected void ERR_MovePlayer(vector position)
|
||||
{
|
||||
vector transform[4];
|
||||
@@ -75,6 +87,14 @@ modded class ERR_GameMode
|
||||
protected void ERR_SmokePhase(ERR_Phase previous, ERR_Phase current)
|
||||
{
|
||||
if (m_ERRSmokeDone || !ERR_MissionRules.Terminal(current)) 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;
|
||||
@@ -129,6 +149,24 @@ modded class ERR_GameMode
|
||||
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 == 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 = {};
|
||||
@@ -136,6 +174,13 @@ modded class ERR_GameMode
|
||||
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_ERRTestMortar)
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
@@ -192,7 +237,7 @@ modded class ERR_GameMode
|
||||
lock.PerformAction(lock.GetOwner(), m_ERRSmokePlayer);
|
||||
if (!ERR_Check(Phase() == ERR_Phase.RADIO_SEARCH, "lock action advances mission")) return;
|
||||
array<IEntity> cacheStock = {};
|
||||
InventoryStorageManagerComponent.Cast(Sites().Find("everon-supply-1").Container.FindComponent(InventoryStorageManagerComponent)).GetItems(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);
|
||||
@@ -270,7 +315,7 @@ modded class ERR_GameMode
|
||||
{
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(agent.GetControlledEntity().FindComponent(InventoryStorageManagerComponent));
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
ERR_Inventory.Items(inventory, items);
|
||||
foreach (IEntity item : items)
|
||||
if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == ERR_MortarBattery.SHELL) SCR_EntityHelper.DeleteEntityAndChildren(item);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -38,6 +38,7 @@ ERR_ScenarioDefinition {
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-radio-1"
|
||||
Label "Radio station"
|
||||
DiscoverRadius 8
|
||||
Kind 1
|
||||
Prefab "{F7E7E3D6ACF0C860}Prefabs/ERR/Radio.et"
|
||||
Position 6500 0 7200
|
||||
@@ -46,7 +47,7 @@ ERR_ScenarioDefinition {
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-extraction-1"
|
||||
Label "Extraction helicopter"
|
||||
Label "Initial helicopter pickup site"
|
||||
Kind 2
|
||||
Prefab "{033503110AC34EAC}Prefabs/ERR/Extraction.et"
|
||||
Position 7000 0 7500
|
||||
@@ -61,6 +62,12 @@ ERR_ScenarioDefinition {
|
||||
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
|
||||
@@ -104,6 +111,12 @@ ERR_ScenarioDefinition {
|
||||
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
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
ERR_FactionCatalog {
|
||||
PlayerFactionKey "US"
|
||||
EnemyFactionKey "USSR"
|
||||
PrisonerPrefab "{2F912ED6E399FF47}Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Unarmed.et"
|
||||
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,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,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 {}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,12 @@
|
||||
// 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;
|
||||
@@ -15,8 +21,7 @@ class ERR_AdminService
|
||||
{
|
||||
protected string Setting(string section, string option)
|
||||
{
|
||||
if (section == "mission" && option == "radio") return "radioDefenceSeconds";
|
||||
return "";
|
||||
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)
|
||||
@@ -42,9 +47,30 @@ class ERR_AdminService
|
||||
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 radio show|set N | mission time show|set HH:MM | mission speed show|set N | spectate next|previous";
|
||||
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)
|
||||
{
|
||||
@@ -54,6 +80,12 @@ class ERR_AdminService
|
||||
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")
|
||||
{
|
||||
@@ -63,17 +95,14 @@ class ERR_AdminService
|
||||
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())
|
||||
{
|
||||
if (parts.Count() == 3 && parts[2] == "show") { replies.Insert(key + "=" + mode.Settings().Get(key).ToString()); return; }
|
||||
int value;
|
||||
if (parts.Count() == 4 && parts[2] == "set" && ERR_CommandArguments.Integer(parts[3], value) && mode.Settings().Set(key, value))
|
||||
replies.Insert(key + "=" + value.ToString() + " saved");
|
||||
else replies.Insert("Invalid value or settings could not be saved; previous setting retained.");
|
||||
SettingCommand(mode.Settings(), key, parts, replies);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ modded class ERR_LocationComponent
|
||||
{
|
||||
if (!Label().IsEmpty()) label = Label();
|
||||
else if (Kind() == ERR_LocationKind.RADIO) label = "Radio station";
|
||||
else if (Kind() == ERR_LocationKind.EXTRACTION) label = "Extraction helicopter";
|
||||
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();
|
||||
|
||||
@@ -10,12 +10,15 @@ class ERR_DiscoveryService
|
||||
folders.Clear();
|
||||
SCR_PrefabNamePredicate predicate = new SCR_PrefabNamePredicate();
|
||||
predicate.prefabName = ERR_Resources.IntelFolder();
|
||||
inventory.FindItems(folders, predicate, EStoragePurpose.PURPOSE_ANY);
|
||||
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 (!folders.Contains(objective)) folders.Insert(objective);
|
||||
if (objective && !folders.Contains(objective)) folders.Insert(objective);
|
||||
}
|
||||
|
||||
void Tick(float now)
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
protected ref ERR_FactionCatalog m_Factions;
|
||||
protected ref ERR_Settings m_Settings;
|
||||
protected ref ERR_TimeService m_Time = new ERR_TimeService();
|
||||
protected ref ERR_EnvironmentService m_Environment = new ERR_EnvironmentService();
|
||||
protected ref ERR_DiscoveryService m_Discovery;
|
||||
protected ref ERR_Objectives m_Objectives;
|
||||
protected ref ERR_PlayerRoster m_Roster = new ERR_PlayerRoster();
|
||||
@@ -27,6 +28,11 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
[RplProp()]
|
||||
protected string m_EndReason;
|
||||
protected ref ERR_RadioDefenceService m_RadioDefence;
|
||||
[RplProp()]
|
||||
protected ERR_RadioFeedback m_RadioFeedback;
|
||||
protected ref ERR_RecoveryService m_Recovery;
|
||||
[RplProp()]
|
||||
protected string m_RecoveryStatus;
|
||||
protected bool m_StartedPlayers;
|
||||
protected bool m_Stopped;
|
||||
protected float m_NoSurvivorsSince = -1;
|
||||
@@ -46,7 +52,10 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
ERR_AdminService Admin() { return m_Admin; }
|
||||
ERR_Settings Settings() { return m_Settings; }
|
||||
ERR_TimeService Time() { return m_Time; }
|
||||
ERR_EnvironmentService Environment() { return m_Environment; }
|
||||
ERR_RadioDefenceService RadioDefence() { return m_RadioDefence; }
|
||||
ERR_RecoveryService Recovery() { return m_Recovery; }
|
||||
string RecoveryStatus() { return m_RecoveryStatus; }
|
||||
ERR_CommandService Command() { return m_Command; }
|
||||
ERR_Objectives Objectives() { return m_Objectives; }
|
||||
ERR_ExtractionService Extraction() { return m_Extraction; }
|
||||
@@ -57,6 +66,18 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
return m_Extraction.VehicleEntity();
|
||||
}
|
||||
float EscapeRadius() { return m_EscapeRadius; }
|
||||
ERR_RadioFeedback RadioFeedback() { return m_RadioFeedback; }
|
||||
// Called only from existing authority transition/tick paths; no extra timer.
|
||||
protected bool RefreshRadioFeedback()
|
||||
{
|
||||
if (!Replication.IsServer()) return false;
|
||||
bool defending = m_Phase == ERR_Phase.RADIO_DEFENCE && m_RadioDefence != null && m_RadioDefence.State() == ERR_RadioDefenceState.DEFENDING;
|
||||
bool occupied = defending && m_RadioDefence.Occupied();
|
||||
ERR_RadioFeedback next = ERR_RadioFeedbackRules.Next(m_RadioFeedback, defending, occupied);
|
||||
if (next == m_RadioFeedback) return false;
|
||||
m_RadioFeedback = next;
|
||||
return true;
|
||||
}
|
||||
bool DefenceOccupied() { return m_RadioDefence && m_RadioDefence.Occupied(); }
|
||||
int DefenceSecondsRemaining()
|
||||
{
|
||||
@@ -97,8 +118,22 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
else if (m_Phase == ERR_Phase.EXTRACTION) phase = "Helicopter extraction";
|
||||
else if (m_Phase == ERR_Phase.VICTORY) phase = "Escape complete";
|
||||
else phase = "Mission lost";
|
||||
if (!m_RecoveryStatus.IsEmpty()) phase += " " + m_RecoveryStatus;
|
||||
return phase;
|
||||
}
|
||||
protected void RecoveryChanged(string message)
|
||||
{
|
||||
if (!Replication.IsServer() || m_RecoveryStatus == message) return;
|
||||
m_RecoveryStatus = message;
|
||||
Replication.BumpMe();
|
||||
}
|
||||
bool AbandonRound()
|
||||
{
|
||||
if (!Replication.IsServer() || !Active() || m_Stopped || !m_PreparationError.IsEmpty()) return false;
|
||||
if (!ERR_MissionRules.CanTransition(m_Phase, ERR_Phase.DEFEAT)) return false;
|
||||
m_EndReason = "An administrator abandoned this round.";
|
||||
return Transition(ERR_Phase.DEFEAT);
|
||||
}
|
||||
protected void FailPreparation(string detail)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Phase != ERR_Phase.PREPARING || !m_PreparationError.IsEmpty()) return;
|
||||
@@ -175,6 +210,7 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
if (!Replication.IsServer() || !m_PreparationError.IsEmpty() || !ERR_MissionRules.CanTransition(m_Phase, phase)) return false;
|
||||
ERR_Phase previous = m_Phase;
|
||||
m_Phase = phase;
|
||||
RefreshRadioFeedback();
|
||||
if (ERR_MissionRules.Terminal(phase)) PublishEscapeResults();
|
||||
Replication.BumpMe();
|
||||
PrintFormat("Rereintroduced [mission]: phase %1 -> %2", previous, phase);
|
||||
@@ -223,6 +259,8 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
m_NoSurvivorsSince = -1;
|
||||
}
|
||||
|
||||
protected string SettingsPath() { return ERR_Settings.PATH; }
|
||||
|
||||
protected override void EOnInit(IEntity owner)
|
||||
{
|
||||
super.EOnInit(owner);
|
||||
@@ -230,7 +268,11 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
m_Factions = ERR_FactionCatalog.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab(m_FactionDefinition));
|
||||
if (!System.IsConsoleApp()) GetGame().GetCallqueue().CallLater(BindLocalObserver, 250, true);
|
||||
if (!Replication.IsServer()) return;
|
||||
m_Settings = new ERR_Settings();
|
||||
m_Settings = new ERR_Settings(SettingsPath());
|
||||
OnStop().Insert(m_Environment.Stop);
|
||||
m_Recovery = new ERR_RecoveryService(this);
|
||||
m_Recovery.OnChanged().Insert(RecoveryChanged);
|
||||
OnStop().Insert(m_Recovery.Stop);
|
||||
m_RadioDefence = new ERR_RadioDefenceService(this);
|
||||
m_RadioDefence.OnStarted().Insert(RadioStarted);
|
||||
m_RadioDefence.OnCompleted().Insert(RadioCompleted);
|
||||
@@ -285,6 +327,7 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
FailPreparation("The extraction vehicle must be a helicopter with a pilot position and at least twelve pilot/passenger seats, with a valid escape boundary.");
|
||||
return;
|
||||
}
|
||||
if (!m_Environment.Start(this)) { FailPreparation("The selected date or vanilla weather profile could not be initialized."); return; }
|
||||
if (!m_Time.Start(this)) { FailPreparation("The world clock could not be initialized."); return; }
|
||||
Transition(ERR_Phase.PRISON);
|
||||
}
|
||||
@@ -311,6 +354,8 @@ class ERR_GameMode : SCR_BaseGameMode
|
||||
m_Extraction.Tick(m_Phase);
|
||||
if (!Active()) return;
|
||||
m_RadioDefence.Tick(now);
|
||||
if (RefreshRadioFeedback()) Replication.BumpMe();
|
||||
m_Recovery.Tick();
|
||||
if (!Active()) return;
|
||||
if (GetGame().GetPlayerManager().GetPlayerCount() == 0)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Initial preparation only. A READY site service never consults this rule again.
|
||||
class ERR_InitialGuardRules
|
||||
{
|
||||
static float TimeoutMilliseconds() { return 90000; }
|
||||
static ERR_PrepareResult State(int requested, int physical, int conscious, bool queueComplete, bool expired)
|
||||
{
|
||||
if (requested <= 0 || physical > requested || conscious > physical || conscious < 0 || physical < 0) return ERR_PrepareResult.FAILED;
|
||||
if (expired) return ERR_PrepareResult.FAILED;
|
||||
if (physical == requested && conscious == requested && queueComplete) return ERR_PrepareResult.READY;
|
||||
return ERR_PrepareResult.PENDING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// GetItems may enumerate the same physical entity through multiple storages.
|
||||
// Identity is the entity reference, never its prefab: distinct rounds still count.
|
||||
class ERR_Inventory
|
||||
{
|
||||
static int AppendUnique(InventoryStorageManagerComponent inventory, notnull array<IEntity> items)
|
||||
{
|
||||
if (!inventory) return items.Count();
|
||||
array<IEntity> raw = {};
|
||||
inventory.GetItems(raw);
|
||||
foreach (IEntity item : raw)
|
||||
if (item && !items.Contains(item)) items.Insert(item);
|
||||
return items.Count();
|
||||
}
|
||||
static int Items(InventoryStorageManagerComponent inventory, out array<IEntity> items)
|
||||
{
|
||||
items.Clear();
|
||||
return AppendUnique(inventory, items);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Attach only to a successor-owned prisoner prefab, with a native action duration.
|
||||
class ERR_LoadCasualtyAction : ScriptedUserAction
|
||||
{
|
||||
override bool CanBeShownScript(IEntity user)
|
||||
{
|
||||
return ERR_CasualtyLoadingRules.Nearby(ERR_GameMode.Get(), user, GetOwner());
|
||||
}
|
||||
override bool CanBePerformedScript(IEntity user)
|
||||
{
|
||||
ERR_GameMode mode = ERR_GameMode.Get();
|
||||
if (!ERR_CasualtyLoadingRules.Nearby(mode, user, GetOwner())) return false;
|
||||
// Clients do not own the authoritative roster. Server always checks again.
|
||||
if (!Replication.IsServer()) return true;
|
||||
return mode.CasualtyLoading() && mode.CasualtyLoading().CanLoad(user, GetOwner());
|
||||
}
|
||||
override bool HasLocalEffectOnlyScript() { return false; }
|
||||
override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
|
||||
{
|
||||
if (!Replication.IsServer() || pOwnerEntity != GetOwner()) return;
|
||||
ERR_GameMode mode = ERR_GameMode.Get();
|
||||
if (mode && mode.CasualtyLoading()) mode.CasualtyLoading().Begin(pUserEntity, pOwnerEntity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#ifdef WORKBENCH
|
||||
// Test adapter exercises the production setting handler with a disposable file.
|
||||
// Actual mode.Admin below still tests its server authorization and alias dispatch.
|
||||
class ERR_NativeAdminSettingsAdapter : ERR_AdminService
|
||||
{
|
||||
void Probe(ERR_Settings settings, string arguments, array<string> replies)
|
||||
{
|
||||
replies.Clear();
|
||||
arguments = arguments.Trim(); arguments.ToLower();
|
||||
array<string> parts = {};
|
||||
arguments.Split(" ", parts, true);
|
||||
if (parts.Count() != 3 && parts.Count() != 4) return;
|
||||
string key = Setting(parts[0], parts[1]);
|
||||
if (!key.IsEmpty()) SettingCommand(settings, key, parts, replies);
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_NativeAdminSettingsProbe
|
||||
{
|
||||
protected static bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: admin settings " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: admin settings " + detail, LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
protected static bool Storage(string path)
|
||||
{
|
||||
ERR_Settings settings = new ERR_Settings(path);
|
||||
ERR_NativeAdminSettingsAdapter adapter = new ERR_NativeAdminSettingsAdapter();
|
||||
array<string> replies = {};
|
||||
map<string, int> initial = new map<string, int>();
|
||||
foreach (string key : ERR_Settings.Keys()) initial.Set(key, settings.Get(key));
|
||||
array<int> values = {0, 100, 15};
|
||||
foreach (int value : values)
|
||||
{
|
||||
adapter.Probe(settings, " INTEL REVEAL SET " + value.ToString() + " ", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0] == "intelRevealChancePercent=" + value.ToString() + " saved" && settings.Get("intelRevealChancePercent") == value, "authorized setting handler accepts normalized value " + value.ToString())) return false;
|
||||
ERR_Settings reloaded = new ERR_Settings(path);
|
||||
if (!Check(reloaded.Get("intelRevealChancePercent") == value, "discovery probability survives native JSON reload")) return false;
|
||||
foreach (string key, int original : initial)
|
||||
if (key != "intelRevealChancePercent" && !Check(reloaded.Get(key) == original, "unrelated setting preserved: " + key)) return false;
|
||||
}
|
||||
array<string> invalid = {"-1", "101", "1.5", "100junk", "999999"};
|
||||
foreach (string argument : invalid)
|
||||
{
|
||||
adapter.Probe(settings, "intel reveal set " + argument, replies);
|
||||
ERR_Settings reloaded = new ERR_Settings(path);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("Invalid") && replies[0].Contains("0-100") && settings.Get("intelRevealChancePercent") == 15 && reloaded.Get("intelRevealChancePercent") == 15, "invalid input preserves live and stored value: " + argument)) return false;
|
||||
}
|
||||
adapter.Probe(settings, "intel reveal help", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("second document") && replies[0].Contains("newly recovered") && replies[0].Contains("remain unchanged"), "help explains exact versus rough discovery and apply timing")) return false;
|
||||
adapter.Probe(settings, "mission radio show", replies);
|
||||
return Check(replies.Count() == 1 && replies[0] == "radioDefenceSeconds=" + initial.Get("radioDefenceSeconds").ToString(), "existing radio alias and response remain intact");
|
||||
}
|
||||
static bool Run(ERR_GameMode mode)
|
||||
{
|
||||
if (!Check(Replication.IsServer() && mode && mode.Admin() && mode.Settings(), "native Core command service and settings ready")) return false;
|
||||
int original = mode.Settings().Get("intelRevealChancePercent");
|
||||
array<string> replies = {};
|
||||
mode.Admin().Execute(mode, false, "intel reveal set 100", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0] == "Administrator access required." && mode.Settings().Get("intelRevealChancePercent") == original, "actual unauthorized command cannot mutate discovery")) return false;
|
||||
mode.Admin().Execute(mode, true, " INTEL REVEAL SHOW ", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0] == "intelRevealChancePercent=" + original.ToString(), "actual Core alias dispatches without Chat")) return false;
|
||||
mode.Admin().Execute(mode, true, "intel reveal set 101", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("0-100") && mode.Settings().Get("intelRevealChancePercent") == original, "actual dispatch rejects out-of-range value with guidance")) return false;
|
||||
mode.Admin().Execute(mode, true, "intel reveal help", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("second document"), "actual Core help describes physical document progression")) return false;
|
||||
string path = "$profile:erri-native-admin-settings-probe.json";
|
||||
if (!Check(!FileIO.FileExists(path) && !FileIO.FileExists(path + ".bak") && !FileIO.FileExists(path + ".tmp"), "disposable fixture filenames are unused")) return false;
|
||||
bool result = Storage(path);
|
||||
FileIO.DeleteFile(path); FileIO.DeleteFile(path + ".bak"); FileIO.DeleteFile(path + ".tmp");
|
||||
if (!result) return false;
|
||||
return Check(mode.Settings().Get("intelRevealChancePercent") == original && !FileIO.FileExists(path) && !FileIO.FileExists(path + ".bak") && !FileIO.FileExists(path + ".tmp"), "fixture removed its files and never changed actual mission settings");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2,6 +2,28 @@
|
||||
#ifdef WORKBENCH
|
||||
modded class ERR_GameMode
|
||||
{
|
||||
protected ref ERR_NativeEnvironmentRestartProbe m_ERRBaseEnvironmentRestartProbe;
|
||||
protected override string SettingsPath()
|
||||
{
|
||||
string enabled, outcome;
|
||||
if (System.GetCLIParam("errBaseSmoke", enabled) && enabled == "1" && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "environment-restart")
|
||||
{
|
||||
m_ERRBaseEnvironmentRestartProbe = new ERR_NativeEnvironmentRestartProbe(this);
|
||||
return ERR_NativeEnvironmentRestartProbe.PATH;
|
||||
}
|
||||
return super.SettingsPath();
|
||||
}
|
||||
|
||||
protected ref ERR_NativeCasualtyServiceProbe m_ERRCasualtyServiceProbe;
|
||||
protected ref ERR_NativePrisonerProbe m_ERRPrisonerProbe;
|
||||
protected ref ERR_NativeGuardCancelProbe m_ERRGuardCancelProbe;
|
||||
protected ref ERR_NativeObjectiveLossProbe m_ERRObjectiveLossProbe;
|
||||
protected ref ERR_NativeMedicalProbe m_ERRBaseMedicalProbe;
|
||||
protected ref ERR_NativeCasualtyLoadProbe m_ERRCasualtyLoadProbe;
|
||||
protected ref ERR_NativeEnvironmentProbe m_ERRBaseEnvironmentProbe;
|
||||
protected bool m_ERRCatalogChecked;
|
||||
protected ref ERR_NativePatrolProbe m_ERRPatrolEast;
|
||||
protected ref ERR_NativePatrolProbe m_ERRPatrolWest;
|
||||
protected int m_ERRBaseStep;
|
||||
protected bool m_ERRObjectiveCloseChecked;
|
||||
protected bool m_ERRStartupFailure;
|
||||
@@ -10,6 +32,7 @@ modded class ERR_GameMode
|
||||
protected ref ERR_NativeExtractionProbe m_ERRExtractionProbe;
|
||||
protected ref ERR_NativeTransportProbe m_ERRTransportProbe;
|
||||
protected ref ERR_NativeLifecycleProbe m_ERRLifecycleProbe;
|
||||
protected ref ERR_NativeRecoveryProbe m_ERRRecoveryProbe;
|
||||
protected ref ERR_NativeRadioDefenceProbe m_ERRBaseRadioProbe;
|
||||
protected string m_ERRActiveCacheId = "everon-supply-1";
|
||||
protected int m_ERRMedicalDiscoveries;
|
||||
@@ -36,8 +59,10 @@ modded class ERR_GameMode
|
||||
OnLocationDiscovered().Insert(ERR_BaseDiscovered);
|
||||
OnStop().Insert(ERR_NativeObjectiveProbe.Stop);
|
||||
OnStop().Insert(ERR_StopRadioProbe);
|
||||
OnStop().Insert(ERR_StopHealthProbes);
|
||||
if (m_ERRStartupFailure && m_Factions) m_Factions.EnemyFactionKey = m_Factions.PlayerFactionKey;
|
||||
m_ERRBaseDeadline = GetWorld().GetWorldTime() + 210000;
|
||||
if (outcome == "patrols") m_ERRBaseDeadline = GetWorld().GetWorldTime() + 330000;
|
||||
OnPhaseChanged().Insert(ERR_BaseResult);
|
||||
GetGame().GetCallqueue().CallLater(ERR_BaseTick, 500, true);
|
||||
Print("ERR BASE SMOKE: core-only scripted escape; not manual or multiplayer acceptance");
|
||||
@@ -47,10 +72,25 @@ modded class ERR_GameMode
|
||||
if (condition) { Print("ERR SMOKE PASS: base " + detail); return true; }
|
||||
ERR_NativeObjectiveProbe.Stop();
|
||||
ERR_StopRadioProbe();
|
||||
ERR_StopHealthProbes();
|
||||
Print("ERR SMOKE FAIL: base " + detail, LogLevel.ERROR);
|
||||
GetGame().GetCallqueue().Remove(ERR_BaseTick);
|
||||
return false;
|
||||
}
|
||||
protected void ERR_StopHealthProbes()
|
||||
{
|
||||
if (m_ERRPatrolEast) m_ERRPatrolEast.Stop();
|
||||
if (m_ERRPatrolWest) m_ERRPatrolWest.Stop();
|
||||
if (m_ERRBaseEnvironmentRestartProbe) m_ERRBaseEnvironmentRestartProbe.Stop();
|
||||
if (m_ERRBaseEnvironmentProbe) m_ERRBaseEnvironmentProbe.Stop();
|
||||
if (m_ERRPrisonerProbe) m_ERRPrisonerProbe.Stop();
|
||||
if (m_ERRGuardCancelProbe) m_ERRGuardCancelProbe.Stop();
|
||||
if (m_ERRCasualtyServiceProbe) m_ERRCasualtyServiceProbe.Stop();
|
||||
if (m_ERRObjectiveLossProbe) m_ERRObjectiveLossProbe.Stop();
|
||||
if (m_ERRBaseMedicalProbe) m_ERRBaseMedicalProbe.Stop();
|
||||
if (m_ERRCasualtyLoadProbe) m_ERRCasualtyLoadProbe.Cleanup();
|
||||
if (m_ERRRecoveryProbe) m_ERRRecoveryProbe.Stop();
|
||||
}
|
||||
protected void ERR_StopRadioProbe() { if (m_ERRBaseRadioProbe) m_ERRBaseRadioProbe.Stop(); }
|
||||
protected void ERR_BaseMove(vector position)
|
||||
{
|
||||
@@ -124,6 +164,69 @@ modded class ERR_GameMode
|
||||
Print("ERR SMOKE COMPLETE: early extraction vehicle loss");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "casualty-service")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1402, "casualty service fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native casualty service with helper-only identity adapter; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "radio-document-loss" || m_ERRExtractionCase == "radio-document-loss-partial")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1302, "radio document-loss fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native " + m_ERRExtractionCase + "; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRExtractionCase == "guard-cancel")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1502, "guard cancellation fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native guard-cancel; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRExtractionCase == "prisoner-kit")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 702, "prisoner-kit fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native prisoner-kit; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "medical")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 602, "medical fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native medical; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if ((m_ERRExtractionCase == "casualty-load" || m_ERRExtractionCase == "casualty-direct" || m_ERRExtractionCase == "casualty-bench" || m_ERRExtractionCase == "casualty-remove"))
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 802, "casualty-load fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native " + m_ERRExtractionCase + "; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "environment-restart")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1202, "environment restart round finished before explicit test reset")) return;
|
||||
PrintFormat("ERR SMOKE COMPLETE: environment restart round %1; reset requested by fixture", m_ERRBaseEnvironmentRestartProbe.Round());
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "environment")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1002, "environment fixture finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native environment; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "patrols")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 1102, "both patrol routes finished before explicit test reset")) return;
|
||||
Print("ERR SMOKE COMPLETE: native finite patrol routes and cleanup; reset requested by fixture");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "recovery")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 502 && EndReason().Contains("administrator abandoned"), "explicit authorized abandonment uses normal defeat result")) return;
|
||||
if (!ERR_BaseCheck(!RecoveryStatus().IsEmpty() && !AbandonRound(), "terminal event observes active warning and rejects repeated abandonment")) return;
|
||||
Print("ERR SMOKE COMPLETE: recovery status and explicit administrator abandonment");
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "objective-ui")
|
||||
{
|
||||
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 902, "objective UI fixture finished before explicit test reset")) return;
|
||||
@@ -182,6 +285,89 @@ modded class ERR_GameMode
|
||||
Print("ERR SMOKE COMPLETE: expected startup-failure");
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 1400)
|
||||
{
|
||||
int result = m_ERRCasualtyServiceProbe.Tick(now);
|
||||
if (result < 0) { ERR_BaseCheck(false, "casualty service fixture failed"); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 1402; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 1300)
|
||||
{
|
||||
int result = m_ERRObjectiveLossProbe.Tick(now);
|
||||
if (result < 0) { ERR_StopHealthProbes(); GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 1302; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRBaseStep == 1500)
|
||||
{
|
||||
int result = m_ERRGuardCancelProbe.Tick(now);
|
||||
if (result < 0) { ERR_StopHealthProbes(); GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 1502; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRBaseStep == 700)
|
||||
{
|
||||
int result = m_ERRPrisonerProbe.Tick(now);
|
||||
if (result < 0) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 702; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 600)
|
||||
{
|
||||
int result = m_ERRBaseMedicalProbe.Tick(now);
|
||||
if (result < 0) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 602; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 800)
|
||||
{
|
||||
int result = m_ERRCasualtyLoadProbe.Tick(now);
|
||||
if (result < 0) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 802; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 1200)
|
||||
{
|
||||
int result = m_ERRBaseEnvironmentRestartProbe.Tick(now);
|
||||
if (result < 0) { ERR_BaseCheck(false, "environment restart fixture failed"); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 1202; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 1000)
|
||||
{
|
||||
int result = m_ERRBaseEnvironmentProbe.Tick(now);
|
||||
if (result < 0) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1) { m_ERRBaseStep = 1002; Transition(ERR_Phase.DEFEAT); }
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 1100)
|
||||
{
|
||||
int east = m_ERRPatrolEast.Tick(now);
|
||||
int west = m_ERRPatrolWest.Tick(now);
|
||||
if (east < 0 || west < 0) { ERR_StopHealthProbes(); GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (east == 1 && west == 1)
|
||||
{
|
||||
if (!ERR_NativePatrolProbe.StopChecks(this)) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
m_ERRBaseStep = 1102; Transition(ERR_Phase.DEFEAT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 500)
|
||||
{
|
||||
int result = m_ERRRecoveryProbe.Tick(now);
|
||||
if (result < 0) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 1)
|
||||
{
|
||||
m_ERRBaseStep = 502;
|
||||
array<string> replies = {};
|
||||
Admin().Execute(this, true, "mission abandon", replies);
|
||||
ERR_BaseCheck(Phase() == ERR_Phase.DEFEAT && replies.Count() == 1 && replies[0].Contains("Round abandoned") && RecoveryStatus().IsEmpty() && Recovery().Conscious() == 0 && Recovery().Incapacitated() == 0, "administrator command returns accepted outcome after recovery cleanup");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (m_ERRBaseStep == 400)
|
||||
{
|
||||
int result = m_ERRLifecycleProbe.Tick(now);
|
||||
@@ -232,6 +418,83 @@ modded class ERR_GameMode
|
||||
ERR_Actors.Players(players, true);
|
||||
if (players.Count() != 1 || Phase() != ERR_Phase.PRISON) return;
|
||||
m_ERRBasePlayer = players[0];
|
||||
if (!m_ERRCatalogChecked)
|
||||
{
|
||||
if (!ERR_NativeFactionCatalogProbe.Run(this)) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
m_ERRCatalogChecked = true;
|
||||
}
|
||||
if (m_ERRExtractionCase == "casualty-service")
|
||||
{
|
||||
m_ERRCasualtyServiceProbe = new ERR_NativeCasualtyServiceProbe(this);
|
||||
m_ERRBaseStep = 1400;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "radio-document-loss" || m_ERRExtractionCase == "radio-document-loss-partial")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRObjectiveLossProbe = new ERR_NativeObjectiveLossProbe(this, m_ERRBasePlayer, m_ERRExtractionCase == "radio-document-loss-partial");
|
||||
m_ERRBaseStep = 1300;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRExtractionCase == "guard-cancel")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRGuardCancelProbe = new ERR_NativeGuardCancelProbe(this);
|
||||
m_ERRBaseStep = 1500;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ERRExtractionCase == "prisoner-kit")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRPrisonerProbe = new ERR_NativePrisonerProbe(this, m_ERRBasePlayer);
|
||||
m_ERRBaseStep = 700;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "medical")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRBaseMedicalProbe = new ERR_NativeMedicalProbe(this);
|
||||
m_ERRBaseStep = 600;
|
||||
return;
|
||||
}
|
||||
if ((m_ERRExtractionCase == "casualty-load" || m_ERRExtractionCase == "casualty-direct" || m_ERRExtractionCase == "casualty-bench" || m_ERRExtractionCase == "casualty-remove"))
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
if (m_ERRExtractionCase == "casualty-remove") m_ERRCasualtyLoadProbe = new ERR_NativeCasualtyRemoveProbe(this);
|
||||
else m_ERRCasualtyLoadProbe = new ERR_NativeCasualtyLoadProbe(this, m_ERRExtractionCase != "casualty-load", m_ERRExtractionCase == "casualty-bench");
|
||||
m_ERRBaseStep = 800;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "environment-restart")
|
||||
{
|
||||
if (!ERR_BaseCheck(m_ERRBaseEnvironmentRestartProbe != null, "environment restart selected isolated settings before mode initialization")) return;
|
||||
m_ERRBaseStep = 1200;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "environment")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRBaseEnvironmentProbe = new ERR_NativeEnvironmentProbe(this);
|
||||
m_ERRBaseStep = 1000;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "patrols")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRPatrolEast = new ERR_NativePatrolProbe(this, "everon-outpost-1");
|
||||
m_ERRPatrolWest = new ERR_NativePatrolProbe(this, "everon-supply-2");
|
||||
m_ERRBaseStep = 1100;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "recovery")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRRecoveryProbe = new ERR_NativeRecoveryProbe(this, m_ERRBasePlayer);
|
||||
m_ERRBaseStep = 500;
|
||||
return;
|
||||
}
|
||||
if (m_ERRExtractionCase == "lifecycle")
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
@@ -279,14 +542,14 @@ modded class ERR_GameMode
|
||||
m_ERRBaseStep = 901;
|
||||
return;
|
||||
}
|
||||
if (!ERR_NativeDefinitionProbe.Run() || !ERR_NativeContractsProbe.Run(this, m_ERRBasePlayer) || !ERR_BaseCover() || !ERR_NativeTimeProbe.Run(this)) return;
|
||||
if (!ERR_NativeAdminSettingsProbe.Run(this) || !ERR_NativeDefinitionProbe.Run() || !ERR_NativeContractsProbe.Run(this, m_ERRBasePlayer) || !ERR_BaseCover() || !ERR_NativeTimeProbe.Run(this)) return;
|
||||
DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
if (!ERR_BaseCheck(Objectives() && Objectives().Current() && Objectives().Current().GetTaskName() == "Escape the prison", "native prison objective exists")) return;
|
||||
if (!ERR_NativeObjectiveProbe.Observe(this)) return;
|
||||
ERR_SiteRuntime cache = Sites().Find(m_ERRActiveCacheId);
|
||||
if (!ERR_BaseCheck(Sites().Count() == 7 && cache && cache.Container && vector.DistanceXZ(cache.Container.GetOrigin(), PrisonPosition()) > 100, "authored supply cache is a separate scavenging location")) return;
|
||||
array<IEntity> stock = {};
|
||||
InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)).GetItems(stock);
|
||||
ERR_Inventory.Items(InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)), stock);
|
||||
PrintFormat("ERR BASE STOCK: cache items=%1", stock.Count());
|
||||
int expectedStock;
|
||||
foreach (ERR_SiteStock entry : cache.Definition.Stock) expectedStock += entry.Count;
|
||||
@@ -360,7 +623,7 @@ modded class ERR_GameMode
|
||||
{
|
||||
ERR_SiteRuntime medical = Sites().Find("everon-medical-1");
|
||||
if (!ERR_BaseCheck(medical.Location.Knowledge() == 2 && medical.Location.Label() == "Medical stash" && m_ERRMedicalDiscoveries == 1, "conscious nearby player visually discovers named medical stash once")) return;
|
||||
if (!ERR_BaseCheck(!Sites().CanObserve(m_ERRBasePlayer, Sites().Find("everon-radio-1")), "proximity cannot bypass radio documents")) return;
|
||||
if (!ERR_BaseCheck(!Sites().CanObserve(m_ERRBasePlayer, Sites().Find("everon-radio-1")), "distant medical-site discovery does not reveal the radio")) return;
|
||||
m_ERRBaseStep = 1;
|
||||
}
|
||||
else if (m_ERRBaseStep == 1 || m_ERRBaseStep == 2)
|
||||
@@ -375,11 +638,11 @@ modded class ERR_GameMode
|
||||
}
|
||||
else if (m_ERRBaseStep == 3)
|
||||
{
|
||||
if (!ERR_BaseCheck(Objectives().Current().GetTaskDescription().Contains("identify the radio station on your map. Reach"), "objective guidance reacts to discovered radio")) return;
|
||||
if (!ERR_BaseCheck(Objectives().Current().GetTaskDescription().Contains("The radio station is identified on your map. Reach"), "objective guidance reacts to discovered radio")) return;
|
||||
if (!ERR_NativeObjectiveProbe.Observe(this)) return;
|
||||
ERR_SiteRuntime cache = Sites().Find(m_ERRActiveCacheId);
|
||||
array<IEntity> stock = {};
|
||||
InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)).GetItems(stock);
|
||||
ERR_Inventory.Items(InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)), stock);
|
||||
foreach (IEntity item : stock) if (item) SCR_EntityHelper.DeleteEntityAndChildren(item);
|
||||
if (!ERR_BaseCheck(m_ERRMedicalDiscoveries == 1, "discovery ticks do not repeat the location event")) return;
|
||||
if (m_ERRCacheLoss && !ERR_BaseCheck(!Sites().Find("everon-supply-1").Container, "lost primary cache stays absent while alternate documents identify the radio")) return;
|
||||
@@ -398,7 +661,9 @@ modded class ERR_GameMode
|
||||
int result = m_ERRBaseRadioProbe.Tick(now);
|
||||
if (result < 0) { ERR_StopRadioProbe(); GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
|
||||
if (result == 0) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.INACTIVE, "radio feedback remains inactive before tuning")) return;
|
||||
if (!ERR_BaseCheck(TuneRadio(m_ERRBasePlayer, m_ERRBaseRadio), "identified radio accepts transmission")) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.WAITING && ERR_ObjectiveText.Description(this, false).Contains("Waiting for"), "radio feedback publishes waiting before first occupancy sample")) return;
|
||||
m_ERRBaseStep = 31;
|
||||
m_ERRBaseWait = now + 5000;
|
||||
}
|
||||
@@ -406,10 +671,11 @@ modded class ERR_GameMode
|
||||
{
|
||||
ERR_SiteRuntime cache = Sites().Find(m_ERRActiveCacheId);
|
||||
array<IEntity> stock = {};
|
||||
InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)).GetItems(stock);
|
||||
ERR_Inventory.Items(InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent)), stock);
|
||||
if (!ERR_BaseCheck(stock.IsEmpty() && Sites().Prepare() == ERR_PrepareResult.READY, "depleted stock stays empty when preparation is queried again")) return;
|
||||
ERR_Actors.DeleteSpawned(cache.Container);
|
||||
if (!ERR_BaseCheck(DefenceOccupied() && DefenceSecondsRemaining() > 0 && DefenceSecondsRemaining() < 30 && Objectives().Current().GetTaskDescription().Contains("seconds remaining"), "native objective reports advancing radio progress")) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.TRANSMITTING && ERR_ObjectiveText.Description(this, false).Contains("Transmission in progress"), "radio guide reports transmitting without querying a countdown")) return;
|
||||
if (!ERR_NativeObjectiveProbe.Observe(this)) return;
|
||||
CharacterControllerComponent.Cast(m_ERRBasePlayer.FindComponent(CharacterControllerComponent)).SetUnconscious(true);
|
||||
m_ERRBaseStep = 310;
|
||||
@@ -420,6 +686,7 @@ modded class ERR_GameMode
|
||||
CharacterControllerComponent controller = CharacterControllerComponent.Cast(m_ERRBasePlayer.FindComponent(CharacterControllerComponent));
|
||||
if (!ERR_BaseCheck(controller.IsUnconscious() && ERR_Actors.Alive(m_ERRBasePlayer) && Players().HasSurvivor() && Phase() == ERR_Phase.RADIO_DEFENCE, "unconscious survivor does not trigger defeat after the full grace period")) return;
|
||||
if (!ERR_BaseCheck(!DefenceOccupied() && DefenceSecondsRemaining() == 30, "unconscious radio defender cannot advance transmission")) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.INTERRUPTED && ERR_ObjectiveText.Description(this, false).Contains("Progress has reset"), "radio guide reports interruption after unconsciousness")) return;
|
||||
SCR_PlayerController playerController = SCR_PlayerController.Cast(GetGame().GetPlayerController());
|
||||
if (!ERR_BaseCheck(playerController.GetControlledEntity() == m_ERRBasePlayer && playerController.ERR_ObserverState() == ERR_ObserverReason.NONE && !playerController.ERR_HasObserverCamera(), "unconscious player retains their body and camera")) return;
|
||||
controller.SetUnconscious(false);
|
||||
@@ -429,6 +696,7 @@ modded class ERR_GameMode
|
||||
else if (m_ERRBaseStep == 311)
|
||||
{
|
||||
if (!ERR_BaseCheck(ERR_Actors.CanFight(m_ERRBasePlayer) && DefenceOccupied() && DefenceSecondsRemaining() < 30, "regaining consciousness resumes transmission from zero")) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.TRANSMITTING && ERR_ObjectiveText.Description(this, false).Contains("Transmission in progress"), "radio guide returns to transmitting after recovery")) return;
|
||||
int playerId = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(m_ERRBasePlayer);
|
||||
if (!ERR_BaseCheck(!Players().CanEnter(playerId, Phase()), "regaining consciousness does not grant another life")) return;
|
||||
ERR_BaseMove(m_ERRBaseRadio.Position() + "90 0 0");
|
||||
@@ -439,6 +707,7 @@ modded class ERR_GameMode
|
||||
{
|
||||
if (!ERR_BaseCheck(!Sites().Find(m_ERRActiveCacheId).Container, "lost supply cache is not replaced")) return;
|
||||
if (!ERR_BaseCheck(!DefenceOccupied() && DefenceSecondsRemaining() == 30 && Objectives().Current().GetTaskDescription().Contains("interrupted"), "objective reports interruption and reset")) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.INTERRUPTED && ERR_ObjectiveText.Description(this, false).Contains("Return a conscious survivor"), "radio guide reports interruption after leaving the area")) return;
|
||||
if (!ERR_NativeObjectiveProbe.Observe(this)) return;
|
||||
ERR_BaseMove(m_ERRBaseRadio.Position() + "2 0 0");
|
||||
m_ERRBaseStep = 4;
|
||||
@@ -447,6 +716,7 @@ modded class ERR_GameMode
|
||||
else if (m_ERRBaseStep == 4)
|
||||
{
|
||||
if (!ERR_BaseCheck(Phase() == ERR_Phase.EXTRACTION, "radio defence reveals extraction") || !ERR_NativeTimeProbe.VerifyProgression(this)) return;
|
||||
if (!ERR_BaseCheck(RadioFeedback() == ERR_RadioFeedback.INACTIVE, "radio feedback clears after completion")) return;
|
||||
if (!ERR_NativeObjectiveProbe.Observe(this)) return;
|
||||
CompartmentAccessComponent access = CompartmentAccessComponent.Cast(m_ERRBasePlayer.FindComponent(CompartmentAccessComponent));
|
||||
BaseCompartmentSlot slot = access.FindFreeCompartment(ExtractionVehicle(), ECompartmentType.PILOT);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifdef WORKBENCH
|
||||
// Positive check observes production initial placement; the fixture never wakes
|
||||
// the mission helicopter. Negative transforms
|
||||
// and velocity are applied only to an independent, disposable empty aircraft.
|
||||
class ERR_NativeCasualtyGroundProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected Vehicle m_Negative;
|
||||
protected float m_Wait;
|
||||
protected float m_Deadline;
|
||||
protected int m_Step;
|
||||
protected bool m_Stopped;
|
||||
void ERR_NativeCasualtyGroundProbe(ERR_GameMode mode) { m_Mode = mode; }
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
ERR_Actors.DeleteSpawned(m_Negative); m_Negative = null;
|
||||
}
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: casualty ground " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: casualty ground " + detail, LogLevel.ERROR); Stop(); return false;
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Stopped) return -1;
|
||||
if (m_Deadline > 0 && now > m_Deadline) { Check(false, "bounded ground-support probe deadline"); return -1; }
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
Vehicle parked = m_Mode.ExtractionVehicle();
|
||||
ERR_SiteService sites = m_Mode.Sites();
|
||||
ERR_ExtractionPlacement placement;
|
||||
if (sites) placement = sites.ExtractionPlacement();
|
||||
if (!Check(placement && placement.Ready() && placement.WakeCount() == 1, "production initial placement completed with exactly one wake before player spawn")) return -1;
|
||||
bool support = ERR_CasualtyGroundSupport.Parked(parked, true);
|
||||
HelicopterControllerComponent controller = HelicopterControllerComponent.Cast(parked.FindComponent(HelicopterControllerComponent));
|
||||
bool nativeContact = controller && controller.GetSimulation() && controller.GetSimulation().HasAnyGroundContact();
|
||||
if (!Check((nativeContact || support) && ERR_CasualtyLoadingRules.AircraftReady(parked), "naturally settled mission aircraft has native landing contact or three strict wheel supports")) return -1;
|
||||
vector raised = parked.GetOrigin() + "0 20 0";
|
||||
m_Negative = Vehicle.Cast(ERR_Actors.Spawn(m_Mode.Factions().ExtractionPrefab, raised));
|
||||
if (!Check(m_Negative != null, "separate empty airborne aircraft created for rejection checks")) return -1;
|
||||
m_Mode.Own(m_Negative);
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(m_Negative.FindComponent(DamageManagerComponent));
|
||||
if (!Check(damage != null, "negative aircraft damage manager available")) return -1;
|
||||
damage.EnableDamageHandling(false);
|
||||
m_Deadline = now + 10000; m_Wait = now + 500; m_Step = 1; return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
vector position = m_Negative.GetOrigin();
|
||||
float height = position[1] - GetGame().GetWorld().GetSurfaceY(position[0], position[2]);
|
||||
bool support = ERR_CasualtyGroundSupport.Parked(m_Negative, true);
|
||||
PrintFormat("ERR GROUND NEGATIVE: raisedPosition=%1 terrainClearance=%2", position, height);
|
||||
if (!Check(ERR_Actors.Alive(m_Negative) && height > 5 && !support && !ERR_CasualtyLoadingRules.AircraftReady(m_Negative), "living aircraft above terrain is rejected even if stationary or sleeping")) return -1;
|
||||
vector tilted[4]; Math3D.AnglesToMatrix("0 0 90", tilted); tilted[3] = position;
|
||||
m_Negative.SetWorldTransform(tilted);
|
||||
m_Wait = now + 500; m_Step = 2; return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
vector actual[4]; m_Negative.GetWorldTransform(actual);
|
||||
Physics physics = m_Negative.GetPhysics();
|
||||
if (!Check(physics != null, "negative aircraft has actual native physics")) return -1;
|
||||
PrintFormat("ERR GROUND NEGATIVE: tiltedUp=%1 position=%2", actual[1][1], actual[3]);
|
||||
if (!Check(ERR_Actors.Alive(m_Negative) && actual[1][1] < 0.85 && !ERR_CasualtyLoadingRules.AircraftMotion(true, actual[1][1], 0, 0) && !ERR_CasualtyLoadingRules.AircraftReady(m_Negative), "actual tilted aircraft is rejected independently by upright policy")) return -1;
|
||||
// Read back an actual native velocity on the disposable clone. No mission
|
||||
// aircraft activation, simulation state, engine or velocity is changed.
|
||||
physics.SetVelocity("2 0 0");
|
||||
float speed = physics.GetVelocity().Length();
|
||||
PrintFormat("ERR GROUND NEGATIVE: nativeSpeed=%1", speed);
|
||||
if (!Check(speed > 0.5 && !ERR_CasualtyLoadingRules.AircraftMotion(true, 1, speed, 0) && !ERR_CasualtyLoadingRules.AircraftReady(m_Negative), "actual native velocity is rejected independently by movement policy")) return -1;
|
||||
if (!Check(ERR_Actors.Alive(m_Mode.ExtractionVehicle()) && ERR_CasualtyLoadingRules.AircraftReady(m_Mode.ExtractionVehicle()), "mission aircraft remains untouched and eligible after negative checks")) return -1;
|
||||
Stop(); return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,255 @@
|
||||
#ifdef WORKBENCH
|
||||
// Native mechanism experiment, NOT proof of an available player load/drag action.
|
||||
// Caller must explicitly opt in and tick this independently of medical fixtures.
|
||||
class ERR_NativeCasualtyLoadProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Caller;
|
||||
protected IEntity m_Casualty;
|
||||
protected Vehicle m_Vehicle;
|
||||
protected SCR_CompartmentAccessComponent m_Access;
|
||||
protected SCR_CharacterDamageManagerComponent m_Damage;
|
||||
protected BaseCompartmentSlot m_Seat;
|
||||
protected vector m_CallerTransform[4];
|
||||
protected vector m_GroundPosition;
|
||||
protected bool m_CallerMoved;
|
||||
protected bool m_Direct;
|
||||
protected bool m_Bench;
|
||||
protected float m_DownSettledAt;
|
||||
protected float m_NextDiagnostic;
|
||||
protected int m_Entered;
|
||||
protected int m_Left;
|
||||
protected int m_Step;
|
||||
protected float m_Deadline;
|
||||
protected float m_Wait;
|
||||
|
||||
void ERR_NativeCasualtyLoadProbe(ERR_GameMode mode, bool direct = false, bool bench = false) { m_Mode = mode; m_Direct = direct; m_Bench = bench; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: casualty-load " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: casualty-load " + detail, LogLevel.ERROR);
|
||||
Cleanup();
|
||||
return false;
|
||||
}
|
||||
void Cleanup()
|
||||
{
|
||||
if (m_Access)
|
||||
{
|
||||
if (m_Access.GetOnCompartmentEntered(false)) m_Access.GetOnCompartmentEntered(false).Remove(Entered);
|
||||
if (m_Access.GetOnCompartmentLeft(false)) m_Access.GetOnCompartmentLeft(false).Remove(Left);
|
||||
}
|
||||
// Restore only the same living local body, never a replacement/reconnected actor.
|
||||
PlayerController controller = GetGame().GetPlayerController();
|
||||
if (m_CallerMoved && m_Caller && controller && controller.GetControlledEntity() == m_Caller && ERR_Actors.Alive(m_Caller) && !CompartmentAccessComponent.GetVehicleIn(m_Caller))
|
||||
ChimeraCharacter.Cast(m_Caller).Teleport(m_CallerTransform);
|
||||
m_CallerMoved = false;
|
||||
ERR_Actors.DeleteSpawned(m_Casualty);
|
||||
m_Casualty = null;
|
||||
}
|
||||
protected void Entered(IEntity target, BaseCompartmentManagerComponent manager, int managerId, int slotId, bool move)
|
||||
{
|
||||
m_Entered++;
|
||||
PrintFormat("ERR CASUALTY ENTER EVENT: manager=%1 slot=%2 move=%3 targetRoot=%4 count=%5", managerId, slotId, move, target == m_Vehicle, m_Entered);
|
||||
}
|
||||
protected void Left(IEntity target, BaseCompartmentManagerComponent manager, int managerId, int slotId, bool move)
|
||||
{
|
||||
m_Left++;
|
||||
PrintFormat("ERR CASUALTY EXIT EVENT: manager=%1 slot=%2 move=%3 targetRoot=%4 count=%5", managerId, slotId, move, target == m_Vehicle, m_Left);
|
||||
}
|
||||
protected bool BelongsToAircraft(IEntity entity)
|
||||
{
|
||||
while (entity)
|
||||
{
|
||||
if (entity == m_Vehicle) return true;
|
||||
entity = entity.GetParent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected BaseCompartmentSlot FindTransportBench()
|
||||
{
|
||||
array<BaseCompartmentSlot> seats = {};
|
||||
m_Mode.Extraction().Seats(seats);
|
||||
foreach (BaseCompartmentSlot seat : seats)
|
||||
{
|
||||
if (!seat || seat.GetType() != ECompartmentType.CARGO || SCR_PatientCompartmentSlot.Cast(seat)) continue;
|
||||
IEntity owner = seat.GetOwner();
|
||||
if (!owner || owner == m_Vehicle || !BelongsToAircraft(owner) || !owner.GetPrefabData()) continue;
|
||||
ResourceName prefab = owner.GetPrefabData().GetPrefabName();
|
||||
// These installed Mi8 seat-part prefabs own the real transport benches.
|
||||
// No compartment class, animation, accessibility or health setting is changed.
|
||||
if (!prefab.Contains("VehPart_MI8_seats")) continue;
|
||||
if (!seat.IsCompartmentAccessible() || seat.IsGetInLockedFor(m_Casualty) || seat.GetOccupant()) continue;
|
||||
return seat;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected void Trace(string stage)
|
||||
{
|
||||
if (!m_Casualty || !m_Access) return;
|
||||
CharacterControllerComponent controller = CharacterControllerComponent.Cast(m_Casualty.FindComponent(CharacterControllerComponent));
|
||||
CharacterAnimationComponent animation = CharacterAnimationComponent.Cast(m_Casualty.FindComponent(CharacterAnimationComponent));
|
||||
if (controller && animation)
|
||||
PrintFormat("ERR CASUALTY STATE: stage=%1 life=%2 ragdoll=%3 falling=%4 physicsLinked=%5 gettingIn=%6 gettingOut=%7", stage, controller.GetLifeState(), animation.IsRagdollActive(), animation.PhysicsIsFalling(), animation.PhysicsIsLinked(), m_Access.IsGettingIn(), m_Access.IsGettingOut());
|
||||
if (m_Seat)
|
||||
{
|
||||
IEntity owner = m_Seat.GetOwner();
|
||||
string prefab;
|
||||
if (owner && owner.GetPrefabData()) prefab = owner.GetPrefabData().GetPrefabName();
|
||||
PrintFormat("ERR CASUALTY SEAT: stage=%1 name=%2 ownerPrefab=%3 rootOwner=%4 hierarchyValid=%5 slotId=%6 managerId=%7", stage, m_Seat.GetCompartmentUniqueName(), prefab, owner == m_Vehicle, BelongsToAircraft(owner), m_Seat.GetCompartmentSlotID(), m_Seat.GetCompartmentMgrID());
|
||||
PrintFormat("ERR CASUALTY OCCUPANCY: stage=%1 inCompartment=%2 actualSlot=%3 targetOccupant=%4 vehicleRoot=%5 enterEvents=%6 exitEvents=%7", stage, m_Access.IsInCompartment(), m_Access.GetCompartment() == m_Seat, m_Seat.GetOccupant() == m_Casualty, CompartmentAccessComponent.GetVehicleIn(m_Casualty) == m_Vehicle, m_Entered, m_Left);
|
||||
}
|
||||
}
|
||||
protected bool DownOnGround()
|
||||
{
|
||||
CharacterControllerComponent controller = CharacterControllerComponent.Cast(m_Casualty.FindComponent(CharacterControllerComponent));
|
||||
return ERR_Actors.Alive(m_Casualty) && controller && controller.GetLifeState() == ECharacterLifeState.INCAPACITATED && !CompartmentAccessComponent.GetVehicleIn(m_Casualty);
|
||||
}
|
||||
protected bool IncapacitateGroundCasualty()
|
||||
{
|
||||
if (!Check(m_Damage && ERR_Actors.Alive(m_Casualty), "living fixture casualty has native damage manager before incapacitation")) return false;
|
||||
HitZone resilience = m_Damage.GetResilienceHitZone();
|
||||
if (!Check(resilience != null, "fixture casualty has actual native resilience hit zone")) return false;
|
||||
float beforeResilience = resilience.GetHealth();
|
||||
bool damageWasEnabled = m_Damage.IsDamageHandlingEnabled();
|
||||
// ForceUnconsciousness uses HandleDamage(TRUE), which damage protection can
|
||||
// suppress. Permit only this synchronous operation, then restore the flag
|
||||
// before any assertion/cleanup path. Never restore health or life state.
|
||||
m_Damage.EnableDamageHandling(true);
|
||||
m_Damage.ForceUnconsciousness();
|
||||
float afterResilience = resilience.GetHealth();
|
||||
m_Damage.EnableDamageHandling(damageWasEnabled);
|
||||
PrintFormat("ERR CASUALTY INCAPACITATION: resilienceBefore=%1 resilienceAfter=%2 damageOriginallyEnabled=%3 restored=%4", beforeResilience, afterResilience, damageWasEnabled, m_Damage.IsDamageHandlingEnabled() == damageWasEnabled);
|
||||
return Check(afterResilience < beforeResilience && ERR_Actors.Alive(m_Casualty) && m_Damage.IsDamageHandlingEnabled() == damageWasEnabled, "single native incapacitation reduces actual resilience, preserves life and restores damage-protection flag");
|
||||
}
|
||||
protected bool BeginExit()
|
||||
{
|
||||
// Native unloading is a separate mechanism check, not a user-action claim.
|
||||
vector exitTransform[4];
|
||||
m_Casualty.GetWorldTransform(exitTransform);
|
||||
exitTransform[3] = m_GroundPosition;
|
||||
return Check(m_Access.GetOutVehicle_NoDoor(exitTransform, true, false), "unconscious cargo occupant accepts native ground exit");
|
||||
}
|
||||
protected bool ExitSettled()
|
||||
{
|
||||
return ERR_Actors.Alive(m_Casualty) && vector.Distance(m_Casualty.GetOrigin(), m_GroundPosition) < 4 && m_Seat.IsCompartmentAccessible();
|
||||
}
|
||||
protected vector ExpectedExit() { return m_GroundPosition; }
|
||||
protected string ExitResultDetail() { return "unloaded survivor on ground and seat accessible"; }
|
||||
// now is world milliseconds, matching the other native probes. Returns -1/0/1.
|
||||
int Tick(float now)
|
||||
{
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
PlayerController controller = GetGame().GetPlayerController();
|
||||
if (!Check(Replication.IsServer() && controller && m_Mode, "server and local real caller available")) return -1;
|
||||
m_Caller = controller.GetControlledEntity();
|
||||
m_Vehicle = m_Mode.ExtractionVehicle();
|
||||
if (!Check(ERR_Actors.CanFight(m_Caller) && !CompartmentAccessComponent.GetVehicleIn(m_Caller) && ERR_Actors.Alive(m_Vehicle), "caller on foot and authored helicopter intact")) return -1;
|
||||
m_GroundPosition = ERR_Actors.Ground(m_Vehicle.GetOrigin() + "6 0 6");
|
||||
m_Casualty = ERR_Actors.Spawn(m_Mode.Factions().PrisonerPrefab, m_GroundPosition);
|
||||
if (!Check(m_Casualty != null, "independent casualty spawned on ground")) return -1;
|
||||
m_Mode.Own(m_Casualty);
|
||||
m_Access = SCR_CompartmentAccessComponent.Cast(m_Casualty.FindComponent(SCR_CompartmentAccessComponent));
|
||||
m_Damage = SCR_CharacterDamageManagerComponent.Cast(m_Casualty.FindComponent(SCR_CharacterDamageManagerComponent));
|
||||
if (!Check(m_Access && m_Damage, "native casualty components present")) return -1;
|
||||
m_Access.GetOnCompartmentEntered().Insert(Entered);
|
||||
m_Access.GetOnCompartmentLeft().Insert(Left);
|
||||
m_Caller.GetWorldTransform(m_CallerTransform);
|
||||
vector helperTransform[4];
|
||||
m_Caller.GetWorldTransform(helperTransform);
|
||||
helperTransform[3] = ERR_Actors.Ground(m_GroundPosition + "2 0 0");
|
||||
ChimeraCharacter.Cast(m_Caller).Teleport(helperTransform);
|
||||
m_CallerMoved = true;
|
||||
m_Step = 1;
|
||||
m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
if (!IncapacitateGroundCasualty()) return -1;
|
||||
m_Deadline = now + 8000;
|
||||
m_Step = 2;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (!DownOnGround())
|
||||
{
|
||||
if (now >= m_Deadline) { Check(false, "native health-driven ground incapacitation before boarding deadline"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
if (m_Bench)
|
||||
{
|
||||
if (m_DownSettledAt == 0)
|
||||
{
|
||||
m_DownSettledAt = now + 5000;
|
||||
m_Deadline = now + 13000;
|
||||
Trace("incapacitated; begin five-second bench settling interval");
|
||||
return 0;
|
||||
}
|
||||
if (now < m_DownSettledAt) return 0;
|
||||
}
|
||||
PrintFormat("ERR CASUALTY POSITIONS: caller=%1 casualty=%2 helicopter=%3", m_Caller.GetOrigin(), m_Casualty.GetOrigin(), m_Vehicle.GetOrigin());
|
||||
if (!Check(ERR_Actors.CanFight(m_Caller) && vector.Distance(m_Caller.GetOrigin(), m_Casualty.GetOrigin()) < 4, "conscious real caller physically beside ground casualty")) return -1;
|
||||
if (m_Bench) m_Seat = FindTransportBench();
|
||||
else m_Seat = m_Access.FindFreeAndAccessibleCompartment(m_Vehicle, ECompartmentType.CARGO);
|
||||
if (!Check(m_Seat && !SCR_PatientCompartmentSlot.Cast(m_Seat) && !m_Seat.GetOccupant(), "ordinary free cargo seat selected without patient-seat substitution")) return -1;
|
||||
if (m_Bench) Print("ERR CASUALTY BENCH SOURCE: VehPart_MI8_seats_base.et sha256=1b9a2e55a9a1cb884886488b6e170f437b6c1a615b584449819b96a6c78ad973");
|
||||
Trace("before selected boarding request");
|
||||
PrintFormat("ERR CASUALTY LOAD: CanGetInVehicle=%1 state=%2 targetType=%3", m_Access.CanGetInVehicle(m_Seat.GetOwner()), CharacterControllerComponent.Cast(m_Casualty.FindComponent(CharacterControllerComponent)).GetLifeState(), m_Seat.GetType());
|
||||
// Exactly the public server-to-owner primitive used by vanilla ambulance loading.
|
||||
bool accepted;
|
||||
if (m_Direct) accepted = m_Access.GetInVehicle(m_Seat.GetOwner(), m_Seat, true, -1, ECloseDoorAfterActions.INVALID, false);
|
||||
else accepted = m_Access.MoveInVehicle(m_Vehicle, ECompartmentType.CARGO, false, m_Seat);
|
||||
PrintFormat("ERR CASUALTY MECHANISM: direct=%1 bench=%2 accepted=%3", m_Direct, m_Bench, accepted);
|
||||
Trace("immediately after selected boarding request");
|
||||
m_NextDiagnostic = now + 1000;
|
||||
if (!Check(accepted, "selected loading request accepted while already unconscious")) return -1;
|
||||
m_Deadline = now + 8000;
|
||||
m_Step = 3;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (now >= m_NextDiagnostic) { Trace("awaiting physical occupancy"); m_NextDiagnostic = now + 1000; }
|
||||
if (CompartmentAccessComponent.GetVehicleIn(m_Casualty) != m_Vehicle || m_Seat.GetOccupant() != m_Casualty)
|
||||
{
|
||||
if (now >= m_Deadline) { Check(false, "physical cargo occupancy after selected mechanism before deadline"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
if (!Check(ERR_Actors.Alive(m_Casualty) && !ERR_Actors.CanFight(m_Casualty), "living unconscious ground casualty now physically aboard")) return -1;
|
||||
if (!Check(!m_Access.MoveInVehicle(m_Vehicle, ECompartmentType.CARGO, false, m_Seat), "occupied target seat rejects repeated request")) return -1;
|
||||
ERR_PlayerRoster roster = new ERR_PlayerRoster();
|
||||
UUID account = "00e77200-0000-0000-0000-000000000201";
|
||||
if (!Check(roster.Bind(10201, account), "isolated casualty identity registered")) return -1;
|
||||
roster.Spawned(10201, m_Casualty);
|
||||
ERR_ExtractionService service = new ERR_ExtractionService(roster);
|
||||
if (!Check(service.Assign(m_Vehicle) && service.Begin(m_Vehicle.GetOrigin() + "100 0 0", 50), "isolated boundary service initialized without moving mission helicopter")) return -1;
|
||||
service.Tick(ERR_Phase.EXTRACTION);
|
||||
if (!Check(service.DidEscape(account) && service.EscapedCount() == 1, "loaded unconscious identity satisfies physical extraction rule")) return -1;
|
||||
if (!BeginExit()) return -1;
|
||||
m_Deadline = now + 8000;
|
||||
m_Step = 4;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
if (now >= m_NextDiagnostic) { Trace("awaiting ground exit"); m_NextDiagnostic = now + 1000; }
|
||||
if (CompartmentAccessComponent.GetVehicleIn(m_Casualty) || m_Seat.GetOccupant())
|
||||
{
|
||||
if (now >= m_Deadline) { Check(false, "native exit clears physical vehicle and seat before deadline"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
bool settled = ExitSettled();
|
||||
if (!settled && now < m_Deadline) return 0;
|
||||
PrintFormat("ERR CASUALTY EXIT POSITION: actual=%1 requested=%2 alive=%3 accessible=%4", m_Casualty.GetOrigin(), ExpectedExit(), ERR_Actors.Alive(m_Casualty), m_Seat.IsCompartmentAccessible());
|
||||
if (!Check(settled, ExitResultDetail())) return -1;
|
||||
Cleanup();
|
||||
m_Step = 5;
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
#ifdef WORKBENCH
|
||||
// Opt-in completion-boundary test of the REAL inherited stock remove action.
|
||||
// It does not simulate held input, replace the action, or prove remote ownership.
|
||||
class ERR_NativeCasualtyRemoveProbe : ERR_NativeCasualtyLoadProbe
|
||||
{
|
||||
protected SCR_RemoveCasualtyUserAction m_Remove;
|
||||
protected UserActionContext m_Context;
|
||||
protected int m_SavedDoor;
|
||||
protected int m_SelectedDoor;
|
||||
protected bool m_DoorChanged;
|
||||
protected bool m_PendingAction;
|
||||
protected bool m_TestBodyProtected;
|
||||
protected bool m_RemoveStopped;
|
||||
protected bool m_RemoveComplete;
|
||||
protected vector m_AuthoredExit;
|
||||
protected vector m_SeatedPosition;
|
||||
protected vector m_HelperPosition;
|
||||
protected float m_RemoveDeadline;
|
||||
protected float m_RemoveDiagnostic;
|
||||
void ERR_NativeCasualtyRemoveProbe(ERR_GameMode mode, bool direct = false, bool bench = false)
|
||||
{
|
||||
m_Mode = mode; m_Direct = true; m_Bench = true;
|
||||
}
|
||||
override void Cleanup()
|
||||
{
|
||||
if (m_Remove && m_DoorChanged) m_Remove.SetCompartmentDoorInfoIndex(m_SavedDoor);
|
||||
m_DoorChanged = false; m_PendingAction = false; m_RemoveStopped = true;
|
||||
super.Cleanup();
|
||||
}
|
||||
protected void FindAction(IEntity entity)
|
||||
{
|
||||
if (!entity || m_Remove) return;
|
||||
BaseActionsManagerComponent manager = BaseActionsManagerComponent.Cast(entity.FindComponent(BaseActionsManagerComponent));
|
||||
if (manager)
|
||||
{
|
||||
array<BaseUserAction> actions = {}; manager.GetActionsList(actions);
|
||||
foreach (BaseUserAction action : actions)
|
||||
{
|
||||
SCR_RemoveCasualtyUserAction remove = SCR_RemoveCasualtyUserAction.Cast(action);
|
||||
if (remove && remove.GetCompartmentSlot() == m_Seat && remove.GetContextIndex("door_l01_door") >= 0)
|
||||
{
|
||||
m_Remove = remove; return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (IEntity child = entity.GetChildren(); child; child = child.GetSibling()) FindAction(child);
|
||||
}
|
||||
protected void FindContext(IEntity entity)
|
||||
{
|
||||
if (!entity || m_Context) return;
|
||||
BaseActionsManagerComponent manager = BaseActionsManagerComponent.Cast(entity.FindComponent(BaseActionsManagerComponent));
|
||||
if (manager)
|
||||
{
|
||||
UserActionContext context = manager.GetContext("door_l01_door");
|
||||
if (context)
|
||||
{
|
||||
array<BaseUserAction> actions = {}; context.GetActionsList(actions);
|
||||
if (actions.Contains(m_Remove)) { m_Context = context; return; }
|
||||
}
|
||||
}
|
||||
for (IEntity child = entity.GetChildren(); child; child = child.GetSibling()) FindContext(child);
|
||||
}
|
||||
protected CompartmentDoorInfo ResolveDoor()
|
||||
{
|
||||
BaseCompartmentManagerComponent manager = m_Seat.GetManager();
|
||||
if (!manager) return null;
|
||||
CompartmentDoorInfo info = manager.GetDoorInfo(m_SelectedDoor);
|
||||
if (info) return info;
|
||||
CompartmentDoorReference doorReference = manager.GetDoorReference(m_SelectedDoor);
|
||||
if (!doorReference) return null;
|
||||
BaseCompartmentManagerComponent referenced = doorReference.GetReferencedDoorCompartmentManager();
|
||||
int referencedIndex = doorReference.GetAnimDoorIndex();
|
||||
PrintFormat("ERR CASUALTY REMOVE DOOR REFERENCE: selected=%1 referencedIndex=%2 manager=%3", m_SelectedDoor, referencedIndex, referenced != null);
|
||||
if (!referenced || referencedIndex < 0) return null;
|
||||
return referenced.GetDoorInfo(referencedIndex);
|
||||
}
|
||||
protected override bool BeginExit()
|
||||
{
|
||||
FindAction(m_Vehicle);
|
||||
if (!Check(m_Remove && BelongsToAircraft(m_Remove.GetOwner()) && m_Remove.GetActionDuration() == 1 && !m_Remove.HasLocalEffectOnly(), "stock bench RemoveCasualty action exists, duration one second, nonlocal effect")) return false;
|
||||
FindContext(m_Vehicle);
|
||||
if (!Check(m_Context && m_Context.GetContextName() == "door_l01_door", "actual exterior context contains selected stock seat action")) return false;
|
||||
// Same native point-to-door selection used by SCR_CompartmentUserAction.
|
||||
// Explicit cached index substitutes only for selecting a UI context, not input.
|
||||
m_SelectedDoor = m_Seat.PickDoorIndexForPoint(m_Context.GetOrigin());
|
||||
if (!Check(m_SelectedDoor >= 0, "actual action context resolves a relevant native compartment door")) return false;
|
||||
CompartmentDoorInfo door = ResolveDoor();
|
||||
if (!Check(door && door.GetExitTeleportPointInfo(), "selected native door exposes its authored teleport exit")) return false;
|
||||
vector exitTransform[4]; door.GetExitTeleportPointInfo().GetWorldTransform(exitTransform);
|
||||
m_AuthoredExit = exitTransform[3]; m_SeatedPosition = m_Casualty.GetOrigin();
|
||||
if (!Check(vector.Distance(m_AuthoredExit, m_Vehicle.GetOrigin()) < 15, "authored exit resolves beside this physical helicopter")) return false;
|
||||
m_SavedDoor = m_Remove.GetCompartmentDoorInfoIndex();
|
||||
m_Remove.SetCompartmentDoorInfoIndex(m_SelectedDoor); m_DoorChanged = true;
|
||||
vector outside = m_Context.GetOrigin() - m_Vehicle.GetOrigin(); outside[1] = 0;
|
||||
if (!Check(outside.Length() > 0.1, "exterior context has a distinct outward direction")) return false;
|
||||
outside.Normalize();
|
||||
m_HelperPosition = ERR_Actors.Ground(m_Context.GetOrigin() + outside * 0.75);
|
||||
vector helper[4]; m_Caller.GetWorldTransform(helper); helper[3] = m_HelperPosition;
|
||||
ChimeraCharacter.Cast(m_Caller).Teleport(helper);
|
||||
PrintFormat("ERR CASUALTY REMOVE SETUP: action=%1 context=%2 door=%3 contextOrigin=%4 exit=%5 seatedOrigin=%6 helperRequested=%7", m_Remove.GetActionID(), m_Context.GetContextName(), m_SelectedDoor, m_Context.GetOrigin(), m_AuthoredExit, m_SeatedPosition, m_HelperPosition);
|
||||
m_PendingAction = true;
|
||||
m_Wait = GetGame().GetWorld().GetWorldTime() + 1000;
|
||||
return true;
|
||||
}
|
||||
static bool SafeExit(float horizontalDistance, float terrainClearance)
|
||||
{
|
||||
return horizontalDistance >= 0 && horizontalDistance <= 1.25 && terrainClearance >= -0.25 && terrainClearance <= 1.5;
|
||||
}
|
||||
protected override vector ExpectedExit() { return m_AuthoredExit; }
|
||||
protected override string ExitResultDetail() { return "stock removal leaves a living incapacitated body beside authored door exit, outside compartment, on terrain, and seat accessible"; }
|
||||
protected override bool ExitSettled()
|
||||
{
|
||||
if (!m_Casualty || !m_Access || !m_Seat) return false;
|
||||
vector actual = m_Casualty.GetOrigin();
|
||||
float height = actual[1] - GetGame().GetWorld().GetSurfaceY(actual[0], actual[2]);
|
||||
CharacterAnimationComponent animation = CharacterAnimationComponent.Cast(m_Casualty.FindComponent(CharacterAnimationComponent));
|
||||
bool safe = DownOnGround() && !m_Access.IsGettingOut() && !m_Access.IsInCompartment() && !m_Seat.GetOccupant() && m_Seat.IsCompartmentAccessible() && animation && !animation.PhysicsIsFalling() && SafeExit(vector.DistanceXZ(actual, m_AuthoredExit), height);
|
||||
float now = GetGame().GetWorld().GetWorldTime();
|
||||
if (now >= m_RemoveDiagnostic || safe)
|
||||
{
|
||||
PrintFormat("ERR CASUALTY REMOVE POSITION: actual=%1 aiming=%2 authored=%3 seated=%4 horizontalError=%5 terrainClearance=%6 safe=%7", actual, ChimeraCharacter.Cast(m_Casualty).AimingPosition(), m_AuthoredExit, m_SeatedPosition, vector.DistanceXZ(actual, m_AuthoredExit), height, safe);
|
||||
Trace("stock door removal observation"); m_RemoveDiagnostic = now + 1000;
|
||||
}
|
||||
return safe;
|
||||
}
|
||||
override int Tick(float now)
|
||||
{
|
||||
if (m_RemoveComplete) return 1;
|
||||
if (m_RemoveStopped) return -1;
|
||||
if (m_RemoveDeadline == 0)
|
||||
{
|
||||
if (!Check(m_Mode && ERR_CasualtyLoadingRules.AircraftReady(m_Mode.ExtractionVehicle()), "production mission helicopter is physically grounded and stable before fixture")) return -1;
|
||||
m_RemoveDeadline = now + 45000;
|
||||
}
|
||||
if (now > m_RemoveDeadline) { Check(false, "bounded 45-second stock removal fixture deadline"); return -1; }
|
||||
if (m_Step == 4 && m_PendingAction)
|
||||
{
|
||||
if (now < m_Wait) return 0;
|
||||
if (!Check(ERR_Actors.CanFight(m_Caller) && !CompartmentAccessComponent.GetVehicleIn(m_Caller) && vector.Distance(m_Caller.GetOrigin(), m_HelperPosition) < 1.5, "real conscious rescuer settled outside selected native door")) return -1;
|
||||
bool shown = m_Remove.CanBeShown(m_Caller);
|
||||
bool permitted = m_Remove.CanBePerformed(m_Caller);
|
||||
PrintFormat("ERR CASUALTY REMOVE ACTION: shown=%1 performedAllowed=%2 reason=%3 cachedDoor=%4 caller=%5", shown, permitted, m_Remove.GetCannotPerformReason(), m_Remove.GetCompartmentDoorInfoIndex(), m_Caller.GetOrigin());
|
||||
if (!Check(shown && permitted && m_Seat.GetOccupant() == m_Casualty && m_Remove.GetCompartmentDoorInfoIndex() == m_SelectedDoor, "stock native action visibility and permission accept actual rescuer and occupied casualty bench")) return -1;
|
||||
m_PendingAction = false; // exactly one completion invocation, no native retry
|
||||
m_Remove.PerformAction(m_Remove.GetOwner(), m_Caller);
|
||||
Print("ERR CASUALTY REMOVE: invoked existing stock action completion once; held input and network dispatch not exercised");
|
||||
m_Deadline = now + 8000;
|
||||
}
|
||||
int result = super.Tick(now);
|
||||
if (!m_TestBodyProtected && m_Casualty && m_Damage)
|
||||
{
|
||||
// Only the fixture-owned casualty is protected from nearby initial guards.
|
||||
// ForceUnconsciousness still uses its actual native health/life transition.
|
||||
m_Damage.EnableDamageHandling(false); m_TestBodyProtected = true;
|
||||
}
|
||||
if (result == 1) m_RemoveComplete = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,293 @@
|
||||
#ifdef WORKBENCH
|
||||
// Only the helper's membership is synthetic. The casualty keeps its real native
|
||||
// player controller/account/body and exercises the ordinary owner handshake.
|
||||
class ERR_NativeCasualtyHelperAdapter : ERR_CasualtyLoadingService
|
||||
{
|
||||
protected ref ERR_PlayerLife m_HelperLife;
|
||||
protected bool m_HelperEnabled;
|
||||
void ERR_NativeCasualtyHelperAdapter(ERR_GameMode mode) { m_Mode = mode; }
|
||||
void Helper(IEntity actor)
|
||||
{
|
||||
m_HelperLife = new ERR_PlayerLife();
|
||||
m_HelperLife.Actor = actor; m_HelperLife.Connected = true; m_HelperLife.UsedLife = true;
|
||||
m_HelperLife.ConnectionId = 15401;
|
||||
m_HelperLife.AccountId = "00e77200-0000-0000-0000-000000001401";
|
||||
}
|
||||
void EnableHelper() { m_HelperEnabled = true; }
|
||||
bool StrictParticipant(IEntity actor) { return super.CurrentLife(actor) != null; }
|
||||
bool StoppedForProbe() { return m_Stopped; }
|
||||
protected override ERR_PlayerLife CurrentLife(IEntity actor)
|
||||
{
|
||||
if (m_HelperEnabled && m_HelperLife && actor && actor == m_HelperLife.Actor) return m_HelperLife;
|
||||
return super.CurrentLife(actor);
|
||||
}
|
||||
}
|
||||
class ERR_NativeCasualtyServiceProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Player;
|
||||
protected IEntity m_Helper;
|
||||
protected IEntity m_Blocker;
|
||||
protected Vehicle m_Aircraft;
|
||||
protected ERR_LoadCasualtyAction m_Action;
|
||||
protected ref ERR_NativeCasualtyHelperAdapter m_Service;
|
||||
protected ref ERR_NativeCasualtyGroundProbe m_GroundProbe;
|
||||
protected bool m_GroundChecked;
|
||||
protected ref array<BaseCompartmentSlot> m_Reserved = {};
|
||||
protected BaseCompartmentSlot m_LoadedSeat;
|
||||
protected float m_Deadline;
|
||||
protected float m_Wait;
|
||||
protected float m_PositionDeadline;
|
||||
protected float m_NextDiagnostic;
|
||||
protected vector m_RequestedPlayer;
|
||||
protected vector m_RequestedHelper;
|
||||
protected bool m_PlayerDamageSnapshot;
|
||||
protected bool m_PlayerDamageOriginallyEnabled;
|
||||
protected int m_SettleStart;
|
||||
protected int m_Step;
|
||||
protected int m_Resolutions;
|
||||
protected bool m_Loaded;
|
||||
protected bool m_Observing;
|
||||
protected bool m_Stopped;
|
||||
void ERR_NativeCasualtyServiceProbe(ERR_GameMode mode) { m_Mode = mode; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: casualty service " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: casualty service " + detail, LogLevel.ERROR);
|
||||
Stop(); return false;
|
||||
}
|
||||
protected void Resolved(IEntity actor, bool loaded)
|
||||
{
|
||||
m_Resolutions++;
|
||||
m_Loaded = actor == m_Player && loaded;
|
||||
}
|
||||
protected void ReleaseFixtureReservations()
|
||||
{
|
||||
foreach (BaseCompartmentSlot seat : m_Reserved)
|
||||
if (seat && m_Helper && seat.IsReservedBy(m_Helper)) seat.SetReserved(null);
|
||||
m_Reserved.Clear();
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
if (m_GroundProbe) m_GroundProbe.Stop();
|
||||
if (m_Service) { m_Service.Stop(); m_Service.OnResolved().Remove(Resolved); }
|
||||
if (m_Mode) m_Mode.ERR_UseCasualtyFixture(null);
|
||||
ReleaseFixtureReservations();
|
||||
// Restore the original damage-handling flag only on this exact still-owned
|
||||
// living player body. This never restores health or changes another actor.
|
||||
if (m_PlayerDamageSnapshot && GetGame() && GetGame().GetPlayerController() && GetGame().GetPlayerController().GetControlledEntity() == m_Player && ERR_Actors.Alive(m_Player))
|
||||
{
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(m_Player.FindComponent(DamageManagerComponent));
|
||||
if (damage) damage.EnableDamageHandling(m_PlayerDamageOriginallyEnabled);
|
||||
}
|
||||
m_PlayerDamageSnapshot = false;
|
||||
ERR_Actors.DeleteSpawned(m_Blocker); m_Blocker = null;
|
||||
ERR_Actors.DeleteSpawned(m_Helper); m_Helper = null;
|
||||
// This opt-in case ends by ordinary round reset. Never restore arbitrary
|
||||
// health, force recovery, teleport the seated player, or delete its body.
|
||||
}
|
||||
protected ERR_LoadCasualtyAction FindAction()
|
||||
{
|
||||
BaseActionsManagerComponent manager = BaseActionsManagerComponent.Cast(m_Player.FindComponent(BaseActionsManagerComponent));
|
||||
if (!manager) return null;
|
||||
array<BaseUserAction> actions = {}; manager.GetActionsList(actions);
|
||||
bool medical;
|
||||
ERR_LoadCasualtyAction load;
|
||||
foreach (BaseUserAction action : actions)
|
||||
{
|
||||
if (SCR_BandageUserAction.Cast(action)) medical = true;
|
||||
ERR_LoadCasualtyAction candidate = ERR_LoadCasualtyAction.Cast(action);
|
||||
if (candidate) load = candidate;
|
||||
}
|
||||
if (!Check(medical, "successor prisoner retains inherited native medicine actions")) return null;
|
||||
return load;
|
||||
}
|
||||
protected void Diagnose()
|
||||
{
|
||||
if (!m_Player || !m_Helper || !m_Aircraft || !m_Service) return;
|
||||
HelicopterControllerComponent aircraftController = HelicopterControllerComponent.Cast(m_Aircraft.FindComponent(HelicopterControllerComponent));
|
||||
Physics physics = m_Aircraft.GetPhysics();
|
||||
bool groundContact;
|
||||
bool simulationAvailable;
|
||||
float speed = -1;
|
||||
float angularSpeed = -1;
|
||||
if (aircraftController && aircraftController.GetSimulation())
|
||||
{
|
||||
simulationAvailable = true;
|
||||
groundContact = aircraftController.GetSimulation().HasAnyGroundContact();
|
||||
}
|
||||
if (physics) { speed = physics.GetVelocity().Length(); angularSpeed = physics.GetAngularVelocity().Length(); }
|
||||
vector transform[4]; m_Aircraft.GetWorldTransform(transform);
|
||||
PrintFormat("ERR CASUALTY AIRCRAFT READINESS: alive=%1 controller=%2 simulation=%3 physics=%4 groundContact=%5 up=%6 speed=%7 angularSpeed=%8 position=%9", ERR_Actors.Alive(m_Aircraft), aircraftController != null, simulationAvailable, physics != null, groundContact, transform[1][1], speed, angularSpeed, m_Aircraft.GetOrigin());
|
||||
CharacterControllerComponent playerController = CharacterControllerComponent.Cast(m_Player.FindComponent(CharacterControllerComponent));
|
||||
CharacterControllerComponent helperController = CharacterControllerComponent.Cast(m_Helper.FindComponent(CharacterControllerComponent));
|
||||
int playerLife = -1;
|
||||
int helperLife = -1;
|
||||
if (playerController) playerLife = playerController.GetLifeState();
|
||||
if (helperController) helperLife = helperController.GetLifeState();
|
||||
PrintFormat("ERR CASUALTY ACTOR READINESS: playerAlive=%1 playerConscious=%2 playerLife=%3 helperAlive=%4 helperConscious=%5 helperLife=%6 pairRange=%7 playerAircraftRange=%8 helperAircraftRange=%9", ERR_Actors.Alive(m_Player), ERR_Actors.CanFight(m_Player), playerLife, ERR_Actors.Alive(m_Helper), ERR_Actors.CanFight(m_Helper), helperLife, vector.Distance(m_Player.GetOrigin(), m_Helper.GetOrigin()), vector.Distance(m_Player.GetOrigin(), m_Aircraft.GetOrigin()), vector.Distance(m_Helper.GetOrigin(), m_Aircraft.GetOrigin()));
|
||||
PrintFormat("ERR CASUALTY POSITION READINESS: playerRequested=%1 playerActual=%2 playerError=%3 helperRequested=%4 helperActual=%5 helperError=%6", m_RequestedPlayer, m_Player.GetOrigin(), vector.Distance(m_RequestedPlayer, m_Player.GetOrigin()), m_RequestedHelper, m_Helper.GetOrigin(), vector.Distance(m_RequestedHelper, m_Helper.GetOrigin()));
|
||||
ERR_CasualtyGroundSupport.Parked(m_Aircraft, true);
|
||||
PrintFormat("ERR CASUALTY SERVICE STATE: step=%1 player=%2 helper=%3 groundedTarget=%4 aircraftReady=%5 sight=%6 pending=%7 resolutions=%8 loaded=%9", m_Step, m_Player.GetOrigin(), m_Helper.GetOrigin(), ERR_CasualtyLoadingRules.GroundSettled(m_Player), ERR_CasualtyLoadingRules.AircraftReady(m_Aircraft), ERR_CasualtyLoadingRules.LineOfSight(m_Helper, m_Player), m_Service.PendingCount(), m_Resolutions, m_Loaded);
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Stopped) return -1;
|
||||
if (m_Deadline > 0 && now > m_Deadline) { if (m_Player && m_Helper && m_Service) Diagnose(); Check(false, "bounded native fixture deadline"); return -1; }
|
||||
if (m_Service && m_Observing) m_Service.Tick(now);
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
PlayerController controller = GetGame().GetPlayerController();
|
||||
if (!Check(Replication.IsServer() && controller && m_Mode.Phase() == ERR_Phase.PRISON, "explicit local server fixture starts with real prisoner")) return -1;
|
||||
m_Player = controller.GetControlledEntity(); m_Aircraft = m_Mode.ExtractionVehicle();
|
||||
if (!Check(ERR_Actors.CanFight(m_Player) && m_Aircraft && !CompartmentAccessComponent.GetVehicleIn(m_Player), "real controlled casualty starts conscious on foot")) return -1;
|
||||
m_Action = FindAction();
|
||||
if (!Check(m_Action && m_Action.GetOwner() == m_Player && m_Action.GetActionDuration() == 5 && !m_Action.HasLocalEffectOnly(), "real successor prisoner owns five-second server action")) return -1;
|
||||
DamageManagerComponent playerDamage = DamageManagerComponent.Cast(m_Player.FindComponent(DamageManagerComponent));
|
||||
if (!Check(playerDamage != null, "fixture player damage manager available")) return -1;
|
||||
m_PlayerDamageOriginallyEnabled = playerDamage.IsDamageHandlingEnabled();
|
||||
m_PlayerDamageSnapshot = true;
|
||||
playerDamage.EnableDamageHandling(false);
|
||||
m_RequestedPlayer = ERR_Actors.Ground(m_Aircraft.GetOrigin() + "6 0 6");
|
||||
m_RequestedHelper = ERR_Actors.Ground(m_RequestedPlayer + "0 0 2");
|
||||
m_Helper = ERR_Actors.Spawn(m_Mode.Factions().PrisonerPrefab, m_RequestedHelper);
|
||||
if (!Check(m_Helper != null, "separate physical helper spawned")) return -1;
|
||||
m_Mode.Own(m_Helper);
|
||||
DamageManagerComponent helperDamage = DamageManagerComponent.Cast(m_Helper.FindComponent(DamageManagerComponent));
|
||||
if (!Check(helperDamage != null, "fixture helper damage manager available")) return -1;
|
||||
helperDamage.EnableDamageHandling(false);
|
||||
vector transform[4]; m_Player.GetWorldTransform(transform); transform[3] = m_RequestedPlayer;
|
||||
ChimeraCharacter.Cast(m_Player).Teleport(transform);
|
||||
m_Service = new ERR_NativeCasualtyHelperAdapter(m_Mode); m_Service.Helper(m_Helper);
|
||||
m_Service.OnResolved().Insert(Resolved);
|
||||
if (!Check(m_Service.StrictParticipant(m_Player) && !m_Service.StrictParticipant(m_Helper), "actual target passes strict native membership; synthetic helper does not")) return -1;
|
||||
if (!Check(!m_Mode.CasualtyLoading().Begin(m_Helper, m_Player) && !m_Service.Begin(m_Helper, m_Player), "production and unadapted sample reject out-of-phase helper request")) return -1;
|
||||
// Deliberate fixture phase setup, not evidence of a completed radio objective.
|
||||
if (!Check(m_Mode.Transition(ERR_Phase.RADIO_SEARCH) && m_Mode.Transition(ERR_Phase.RADIO_DEFENCE) && m_Mode.Transition(ERR_Phase.EXTRACTION), "fixture enters extraction through explicit legal phase transitions")) return -1;
|
||||
m_Deadline = now + 45000;
|
||||
m_PositionDeadline = now + 10000;
|
||||
m_NextDiagnostic = now;
|
||||
m_Wait = now + 500; m_Step = 1; return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
if (now >= m_NextDiagnostic) { Diagnose(); m_NextDiagnostic = now + 1000; }
|
||||
bool actorsReady = ERR_Actors.CanFight(m_Player) && ERR_Actors.CanFight(m_Helper) && vector.Distance(m_RequestedPlayer, m_Player.GetOrigin()) <= 1.5 && vector.Distance(m_RequestedHelper, m_Helper.GetOrigin()) <= 1.5 && vector.Distance(m_Player.GetOrigin(), m_Helper.GetOrigin()) <= 3;
|
||||
bool aircraftReady = ERR_CasualtyLoadingRules.AircraftReady(m_Aircraft);
|
||||
if ((!actorsReady || !aircraftReady) && now < m_PositionDeadline) return 0;
|
||||
if (!Check(actorsReady, "actual living conscious actors reached requested nearby ground positions before deadline")) return -1;
|
||||
if (!Check(aircraftReady, "actual aircraft satisfies unchanged production grounded-motion safety before deadline")) return -1;
|
||||
if (!m_GroundChecked)
|
||||
{
|
||||
if (!m_GroundProbe) m_GroundProbe = new ERR_NativeCasualtyGroundProbe(m_Mode);
|
||||
int groundResult = m_GroundProbe.Tick(now);
|
||||
if (groundResult < 0) { Check(false, "native ground-support qualification failed"); return -1; }
|
||||
if (groundResult == 0) return 0;
|
||||
m_GroundChecked = true;
|
||||
}
|
||||
if (!Check(!m_Service.Begin(m_Helper, m_Player), "conscious target is rejected before native incapacitation")) return -1;
|
||||
SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_Player.FindComponent(SCR_CharacterDamageManagerComponent));
|
||||
if (!Check(damage != null, "real casualty has native health manager")) return -1;
|
||||
HitZone resilience = damage.GetResilienceHitZone();
|
||||
if (!Check(resilience && damage.GetPermitUnconsciousness(), "native resilience and unconsciousness policy available")) return -1;
|
||||
float beforeResilience = resilience.GetHealth();
|
||||
// Protection must not swallow the fixture's own true-damage request. Keep
|
||||
// this synchronous interval limited to that one native health operation.
|
||||
damage.EnableDamageHandling(true);
|
||||
damage.ForceUnconsciousness();
|
||||
float afterResilience = resilience.GetHealth();
|
||||
damage.EnableDamageHandling(false);
|
||||
PrintFormat("ERR CASUALTY INCAPACITATION: resilienceBefore=%1 resilienceAfter=%2", beforeResilience, afterResilience);
|
||||
if (!Check(afterResilience < beforeResilience && ERR_Actors.Alive(m_Player), "single native resilience damage applied before restoring fixture protection")) return -1;
|
||||
m_Step = 2; m_Wait = now + 500; return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (!ERR_CasualtyLoadingRules.GroundSettled(m_Player))
|
||||
{
|
||||
if (now >= m_NextDiagnostic) { Diagnose(); m_NextDiagnostic = now + 1000; }
|
||||
return 0;
|
||||
}
|
||||
if (!Check(ERR_CasualtyLoadingRules.Nearby(m_Mode, m_Helper, m_Player), "actual incapacitated target is settled with clear line of sight")) return -1;
|
||||
if (!Check(!m_Mode.CasualtyLoading().CanLoad(m_Helper, m_Player) && !m_Service.Begin(m_Helper, m_Player) && m_Service.PendingCount() == 0, "strict production authorization rejects nonparticipant helper even in valid physical state")) return -1;
|
||||
m_Service.EnableHelper();
|
||||
if (!Check(m_Mode.ERR_UseCasualtyFixture(m_Service), "explicit fixture installs helper-only membership adapter")) return -1;
|
||||
m_Observing = true; m_Service.Tick(now); m_SettleStart = System.GetTickCount();
|
||||
if (!Check(!m_Service.CanLoad(m_Helper, m_Player), "new observation cannot bypass five-second settling window")) return -1;
|
||||
m_Step = 3; return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (System.GetTickCount() - m_SettleStart < 5500) return 0;
|
||||
Diagnose();
|
||||
if (!Check(m_Service.CanLoad(m_Helper, m_Player), "settled real casualty is eligible with only helper membership adapted")) return -1;
|
||||
array<BaseCompartmentSlot> seats = {}; m_Mode.Extraction().Seats(seats);
|
||||
foreach (BaseCompartmentSlot seat : seats)
|
||||
{
|
||||
if (!ERR_CasualtyLoadingRules.TransportBench(seat, m_Aircraft) || seat.GetOccupant() || seat.IsReserved()) continue;
|
||||
seat.SetReserved(m_Helper); m_Reserved.Insert(seat);
|
||||
}
|
||||
if (!Check(!m_Reserved.IsEmpty() && !m_Service.CanLoad(m_Helper, m_Player) && !m_Service.Begin(m_Helper, m_Player), "native external reservations prevent loading when all child benches are reserved")) return -1;
|
||||
ReleaseFixtureReservations();
|
||||
vector middle = (ChimeraCharacter.Cast(m_Helper).AimingPosition() + ChimeraCharacter.Cast(m_Player).AimingPosition()) * 0.5;
|
||||
m_Blocker = ERR_Actors.Spawn("{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et", middle);
|
||||
if (!Check(m_Blocker != null, "successor-owned physical line-of-sight obstacle spawned")) return -1;
|
||||
m_Mode.Own(m_Blocker);
|
||||
vector low, high; m_Blocker.GetWorldBounds(low, high);
|
||||
vector wall[4]; m_Blocker.GetWorldTransform(wall); wall[3] = wall[3] + middle - (low + high) * 0.5;
|
||||
m_Blocker.SetWorldTransform(wall);
|
||||
m_Step = 4; m_Wait = now + 500; return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
if (!Check(!ERR_CasualtyLoadingRules.LineOfSight(m_Helper, m_Player) && !m_Service.CanLoad(m_Helper, m_Player) && !m_Service.Begin(m_Helper, m_Player) && m_Service.PendingCount() == 0, "physical wall blocks completion-time rescue authorization")) return -1;
|
||||
ERR_Actors.DeleteSpawned(m_Blocker); m_Blocker = null;
|
||||
m_Step = 5; m_Wait = now + 500; return 0;
|
||||
}
|
||||
if (m_Step == 5)
|
||||
{
|
||||
if (!Check(m_Action.CanBePerformedScript(m_Helper) && m_Service.PendingCount() == 0, "real action becomes performable after obstruction removal")) return -1;
|
||||
// Invoke the real completion boundary. This does not simulate holding input
|
||||
// for five seconds or claim a second authenticated network player.
|
||||
m_Action.PerformAction(m_Player, m_Helper);
|
||||
if (!Check(m_Service.PendingCount() == 1 && m_Resolutions == 0, "real owner handshake commits one pending physical load")) return -1;
|
||||
array<BaseCompartmentSlot> seats = {}; m_Mode.Extraction().Seats(seats);
|
||||
foreach (BaseCompartmentSlot seat : seats)
|
||||
if (ERR_CasualtyLoadingRules.TransportBench(seat, m_Aircraft) && seat.IsReservedBy(m_Player)) m_LoadedSeat = seat;
|
||||
if (!Check(m_LoadedSeat != null, "service reserves the actual selected child bench for the casualty")) return -1;
|
||||
m_Action.PerformAction(m_Player, m_Helper);
|
||||
if (!Check(m_Service.PendingCount() == 1 && m_Resolutions == 0, "duplicate completion cannot issue a second ticket")) return -1;
|
||||
m_Step = 6; return 0;
|
||||
}
|
||||
if (m_Step == 6)
|
||||
{
|
||||
if (m_Service.PendingCount() > 0) return 0;
|
||||
Diagnose();
|
||||
if (!Check(m_Loaded && m_Resolutions == 1 && ERR_Actors.Alive(m_Player) && ERR_CasualtyLoadingRules.Down(m_Player) && CompartmentAccessComponent.GetVehicleIn(m_Player) == m_Aircraft && m_LoadedSeat.GetOccupant() == m_Player, "production owner handshake physically loads real living incapacitated player exactly once")) return -1;
|
||||
if (!Check(!m_LoadedSeat.IsReserved() && m_Service.StrictParticipant(m_Player), "successful loading releases reservation and preserves actual player identity")) return -1;
|
||||
m_Service.Stop(); m_Service.Stop(); m_Service.Tick(now);
|
||||
if (!Check(m_Service.StoppedForProbe() && m_Service.PendingCount() == 0 && m_Resolutions == 1 && !m_Service.Begin(m_Helper, m_Player), "Stop is latched, idempotent and cannot repeat completion or restart loading")) return -1;
|
||||
Stop(); return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
modded class ERR_GameMode
|
||||
{
|
||||
protected ref ERR_NativeCasualtyHelperAdapter m_ERRNativeCasualtyAdapter;
|
||||
bool ERR_UseCasualtyFixture(ERR_NativeCasualtyHelperAdapter service)
|
||||
{
|
||||
string enabled, outcome;
|
||||
if (!Replication.IsServer() || !System.GetCLIParam("errBaseSmoke", enabled) || enabled != "1" || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "casualty-service") return false;
|
||||
m_ERRNativeCasualtyAdapter = service; return true;
|
||||
}
|
||||
override ERR_CasualtyLoadingService CasualtyLoading()
|
||||
{
|
||||
if (m_ERRNativeCasualtyAdapter) return m_ERRNativeCasualtyAdapter;
|
||||
return super.CasualtyLoading();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -40,9 +40,12 @@ class ERR_NativeDefinitionProbe
|
||||
if (!Check(!definition.Valid(), "unnamed location rejected")) return false;
|
||||
alternate.Label = label;
|
||||
ERR_SiteDefinition radio = definition.Find("everon-radio-1");
|
||||
radio.DiscoverRadius = 25;
|
||||
if (!Check(!definition.Valid(), "proximity discovery cannot reveal progression sites")) return false;
|
||||
radio.DiscoverRadius = 0;
|
||||
float radioRadius = radio.DiscoverRadius;
|
||||
radio.DiscoverRadius = 9;
|
||||
if (!Check(!definition.Valid(), "radio identification beyond eight metres rejected")) return false;
|
||||
radio.DiscoverRadius = 8;
|
||||
if (!Check(definition.Valid(), "close physical radio identification allowed")) return false;
|
||||
radio.DiscoverRadius = radioRadius;
|
||||
radio.RevealOnEscape = true;
|
||||
if (!Check(!definition.Valid(), "escape cannot reveal the radio directly")) return false;
|
||||
radio.RevealOnEscape = false;
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
#ifdef WORKBENCH
|
||||
class ERR_NativeEnvironmentSample : ERR_EnvironmentService
|
||||
{
|
||||
bool Apply(TimeAndWeatherManagerEntity manager, int dateCode, int profile) { return StartOn(manager, dateCode, profile); }
|
||||
}
|
||||
// Explicit isolated environment smoke outcome. It temporarily changes the private
|
||||
// native world, restores date/weather family/looping, then requests a round reset.
|
||||
class ERR_NativeEnvironmentProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected TimeAndWeatherManagerEntity m_Manager;
|
||||
protected ref ERR_NativeEnvironmentSample m_Sample;
|
||||
protected ref ERR_Settings m_TestSettings;
|
||||
protected bool m_Snapshot;
|
||||
protected bool m_Restored;
|
||||
protected bool m_Stopped;
|
||||
protected bool m_OwnsSettings;
|
||||
protected bool m_RestoreDateAccepted;
|
||||
protected int m_Year;
|
||||
protected int m_Month;
|
||||
protected int m_Day;
|
||||
protected string m_Weather;
|
||||
protected bool m_Looping;
|
||||
protected float m_Clock;
|
||||
protected float m_DayDuration;
|
||||
protected bool m_DayAdvances;
|
||||
protected float m_Wait;
|
||||
protected float m_Deadline;
|
||||
protected int m_Step;
|
||||
protected int m_Result;
|
||||
void ERR_NativeEnvironmentProbe(ERR_GameMode mode) { m_Mode = mode; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: environment " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: environment " + detail, LogLevel.ERROR);
|
||||
m_Result = -1;
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
protected string CurrentWeather()
|
||||
{
|
||||
if (!m_Manager || !m_Manager.GetCurrentWeatherState()) return "";
|
||||
return m_Manager.GetCurrentWeatherState().GetStateName();
|
||||
}
|
||||
protected void Restore()
|
||||
{
|
||||
if (!m_Snapshot || m_Restored || !m_Manager) return;
|
||||
m_Restored = true;
|
||||
if (m_Sample) m_Sample.Stop();
|
||||
m_RestoreDateAccepted = m_Manager.SetDate(m_Year, m_Month, m_Day, true);
|
||||
m_Manager.ForceWeatherTo(m_Looping, m_Weather, 0, 24);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
Restore();
|
||||
m_Stopped = true;
|
||||
if (m_OwnsSettings)
|
||||
{
|
||||
string path = "$profile:erri-native-environment-probe.json";
|
||||
FileIO.DeleteFile(path); FileIO.DeleteFile(path + ".bak"); FileIO.DeleteFile(path + ".tmp");
|
||||
m_OwnsSettings = false;
|
||||
}
|
||||
}
|
||||
protected bool SettingsChecks()
|
||||
{
|
||||
string path = "$profile:erri-native-environment-probe.json";
|
||||
if (!Check(!FileIO.FileExists(path) && !FileIO.FileExists(path + ".bak") && !FileIO.FileExists(path + ".tmp"), "environment fixture filenames are unused")) return false;
|
||||
m_OwnsSettings = true;
|
||||
JsonSaveContext json = new JsonSaveContext();
|
||||
json.EnableTypeDiscriminator(false);
|
||||
foreach (string key : ERR_Settings.Keys())
|
||||
if (key != "startDateCode" && key != "weatherProfile") json.WriteValue(key, m_Mode.Settings().Get(key));
|
||||
if (!Check(json.SaveToFile(path), "owned legacy settings fixture written")) return false;
|
||||
m_TestSettings = new ERR_Settings(path);
|
||||
JsonLoadContext unchanged = new JsonLoadContext();
|
||||
if (!Check(m_TestSettings.Get("startDateCode") == 0 && m_TestSettings.Get("weatherProfile") == 0 && unchanged.LoadFromFile(path) && !unchanged.DoesKeyExist("startDateCode") && !unchanged.DoesKeyExist("weatherProfile"), "missing environment settings preserve authored defaults without rewriting legacy file")) return false;
|
||||
if (!Check(m_TestSettings.Set("startDateCode", 1501231) && m_TestSettings.Set("weatherProfile", 2), "date and weather persist in owned fixture settings")) return false;
|
||||
ERR_Settings reloaded = new ERR_Settings(path);
|
||||
if (!Check(reloaded.Get("startDateCode") == 1501231 && reloaded.Get("weatherProfile") == 2 && reloaded.Get("radioDefenceSeconds") == m_Mode.Settings().Get("radioDefenceSeconds"), "odd maximum date code round-trips exactly and old settings survive")) return false;
|
||||
if (!Check(!m_TestSettings.Set("startDateCode", 229) && !m_TestSettings.Set("weatherProfile", 4), "non-leap-century date and unknown profile cannot be saved")) return false;
|
||||
int originalDate = m_Mode.Settings().Get("startDateCode");
|
||||
int originalProfile = m_Mode.Settings().Get("weatherProfile");
|
||||
array<string> replies = {};
|
||||
m_Mode.Admin().Execute(m_Mode, false, "mission weather set rain", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("Administrator") && m_Mode.Settings().Get("startDateCode") == originalDate && m_Mode.Settings().Get("weatherProfile") == originalProfile, "unauthorized environment command preserves real settings")) return false;
|
||||
replies.Clear();
|
||||
ERR_EnvironmentCommands.Execute(m_TestSettings, m_Mode.Environment(), {"mission", "date", "set", "2000-02-29"}, replies);
|
||||
if (!Check(m_TestSettings.Get("startDateCode") == 1000229 && replies.Count() == 1 && replies[0].Contains("next round"), "natural leap-date command saves only next-round settings")) return false;
|
||||
replies.Clear();
|
||||
ERR_EnvironmentCommands.Execute(m_TestSettings, m_Mode.Environment(), {"mission", "weather", "set", "clear"}, replies);
|
||||
if (!Check(m_TestSettings.Get("weatherProfile") == 1 && replies.Count() == 1 && replies[0].Contains("Current round unchanged"), "named weather command saves only next-round settings")) return false;
|
||||
replies.Clear();
|
||||
ERR_EnvironmentCommands.Execute(m_TestSettings, m_Mode.Environment(), {"mission", "date", "set", "1900-00-00"}, replies);
|
||||
if (!Check(m_TestSettings.Get("startDateCode") == 1000229 && replies[0].Contains("Invalid"), "zero month/day cannot masquerade as authored date")) return false;
|
||||
return true;
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Result != 0) return m_Result;
|
||||
if (m_Stopped) return -1;
|
||||
if (!Replication.IsServer() || !m_Mode || !m_Mode.Active()) { Check(false, "requires active server authority"); return -1; }
|
||||
if (m_Deadline > 0 && now > m_Deadline) { Check(false, "native environment request timed out"); return -1; }
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
ChimeraWorld world = ChimeraWorld.CastFrom(m_Mode.GetWorld());
|
||||
if (world) m_Manager = world.GetTimeAndWeatherManager();
|
||||
if (!Check(m_Manager && m_Manager.GetCurrentWeatherState() && m_Mode.Environment().Started(), "native environment manager and round service available")) return -1;
|
||||
m_Manager.GetDate(m_Year, m_Month, m_Day);
|
||||
m_Weather = CurrentWeather(); m_Looping = m_Manager.IsWeatherLooping();
|
||||
m_Clock = m_Manager.GetTimeOfTheDay(); m_DayDuration = m_Manager.GetDayDuration(); m_DayAdvances = m_Manager.GetIsDayAutoAdvanced();
|
||||
m_Snapshot = true;
|
||||
m_Deadline = now + 15000;
|
||||
if (!SettingsChecks()) return -1;
|
||||
if (!Check(CurrentWeather() == m_Weather && m_Manager.GetYear() == m_Year && m_Manager.GetMonth() == m_Month && m_Manager.GetDay() == m_Day, "saving fixture environment settings does not mutate native world")) return -1;
|
||||
for (int profile = 1; profile <= 3; profile++)
|
||||
if (!Check(ERR_EnvironmentService.HasWeatherState(m_Manager, ERR_EnvironmentService.WeatherStateName(profile)), "selected vanilla weather family exists: " + ERR_EnvironmentService.ProfileName(profile))) return -1;
|
||||
m_Sample = new ERR_NativeEnvironmentSample();
|
||||
if (!Check(!m_Sample.Apply(m_Manager, 229, 1) && !m_Sample.Apply(m_Manager, 1000229, 4) && !m_Sample.Started(), "invalid date/profile rejected before native changes")) return -1;
|
||||
if (!Check(m_Sample.Apply(m_Manager, 890601, 1), "clear profile and specific date requested once")) return -1;
|
||||
m_Step = 1; m_Wait = now + 500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
if (!Check(CurrentWeather() == "Clear" && m_Manager.IsWeatherLooping() && m_Manager.GetYear() == 1989 && m_Manager.GetMonth() == 6 && m_Manager.GetDay() == 1, "native clear weather and requested date applied after frame")) return -1;
|
||||
if (!Check(m_Sample.Apply(m_Manager, 1000229, 3) && m_Sample.DateCode() == 890601 && m_Sample.Profile() == 1 && CurrentWeather() == "Clear", "repeated start cannot apply another date or profile")) return -1;
|
||||
m_Sample.Stop();
|
||||
if (!Check(!m_Sample.Apply(m_Manager, 1000229, 3), "stopped environment cannot restart")) return -1;
|
||||
m_Sample = new ERR_NativeEnvironmentSample();
|
||||
if (!Check(m_Sample.Apply(m_Manager, 1000229, 2), "overcast and leap date requested on fresh service")) return -1;
|
||||
m_Step = 2; m_Wait = now + 500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (!Check(CurrentWeather() == "Overcast" && m_Manager.GetYear() == 2000 && m_Manager.GetMonth() == 2 && m_Manager.GetDay() == 29, "native overcast and leap date accepted")) return -1;
|
||||
m_Sample.Stop(); m_Sample = new ERR_NativeEnvironmentSample();
|
||||
if (!Check(m_Sample.Apply(m_Manager, 0, 3), "rain profile preserves authored/current date when date override is disabled")) return -1;
|
||||
m_Step = 3; m_Wait = now + 500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (!Check(CurrentWeather() == "Rainy" && m_Manager.GetYear() == 2000 && m_Manager.GetMonth() == 2 && m_Manager.GetDay() == 29, "native rainy family applied without changing date")) return -1;
|
||||
float clockAdvance = m_Manager.GetTimeOfTheDay() - m_Clock;
|
||||
if (clockAdvance < 0) clockAdvance += 24;
|
||||
if (!Check(m_Manager.GetDayDuration() == m_DayDuration && m_Manager.GetIsDayAutoAdvanced() == m_DayAdvances && clockAdvance < 0.1, "environment does not reset clock or progression")) return -1;
|
||||
Restore();
|
||||
m_Step = 4; m_Wait = now + 500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
if (!Check(m_RestoreDateAccepted && m_Manager.GetYear() == m_Year && m_Manager.GetMonth() == m_Month && m_Manager.GetDay() == m_Day && CurrentWeather() == m_Weather && m_Manager.IsWeatherLooping() == m_Looping, "fixture restores original native date, weather family and looping")) return -1;
|
||||
m_Result = 1; Stop();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
#ifdef WORKBENCH
|
||||
// Only environment-restart opts into this fixed private path. The runner must
|
||||
// refuse all preexisting fixture files and require exactly two real rounds.
|
||||
class ERR_NativeEnvironmentRestartProbe
|
||||
{
|
||||
static const string PATH = "$profile:erri-environment-restart.json";
|
||||
static const string MARKER = "$profile:erri-environment-restart-round.json";
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected TimeAndWeatherManagerEntity m_Manager;
|
||||
protected bool m_Failed;
|
||||
protected bool m_Stopped;
|
||||
protected bool m_Complete;
|
||||
protected int m_Round = 1;
|
||||
protected int m_InitialDate;
|
||||
protected string m_InitialWeather;
|
||||
protected bool m_InitialLoop;
|
||||
protected float m_Wait;
|
||||
protected float m_Hour;
|
||||
protected float m_Duration;
|
||||
|
||||
void ERR_NativeEnvironmentRestartProbe(ERR_GameMode mode)
|
||||
{
|
||||
m_Mode = mode;
|
||||
ChimeraWorld world = ChimeraWorld.CastFrom(mode.GetWorld());
|
||||
if (world) m_Manager = world.GetTimeAndWeatherManager();
|
||||
if (!Check(m_Manager && m_Manager.GetCurrentWeatherState(), "world environment exists before production settings and service initialization")) return;
|
||||
m_InitialDate = DateCode();
|
||||
m_InitialWeather = Weather();
|
||||
m_InitialLoop = m_Manager.IsWeatherLooping();
|
||||
if (FileIO.FileExists(MARKER))
|
||||
{
|
||||
JsonLoadContext marker = new JsonLoadContext();
|
||||
int stage;
|
||||
if (!Check(marker.LoadFromFile(MARKER) && marker.ReadValue("completedRound", stage) && stage == 1 && FileIO.FileExists(PATH), "second instance sees first round's completed marker and saved settings")) return;
|
||||
m_Round = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Check(!FileIO.FileExists(PATH) && !FileIO.FileExists(PATH + ".bak") && !FileIO.FileExists(PATH + ".tmp"), "first instance owns previously unused fixture settings paths")) return;
|
||||
}
|
||||
PrintFormat("ERR ENVIRONMENT RESTART INSTANCE: round=%1 authoredDate=%2 authoredWeather=%3", m_Round, m_InitialDate, m_InitialWeather);
|
||||
}
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: environment restart " + detail); return true; }
|
||||
m_Failed = true;
|
||||
Print("ERR SMOKE FAIL: environment restart " + detail, LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
protected int DateCode() { return (m_Manager.GetYear() - 1900) * 10000 + m_Manager.GetMonth() * 100 + m_Manager.GetDay(); }
|
||||
protected string Weather()
|
||||
{
|
||||
WeatherState state = m_Manager.GetCurrentWeatherState();
|
||||
if (!state) return "unavailable";
|
||||
return state.GetStateName();
|
||||
}
|
||||
int Round() { return m_Round; }
|
||||
void Stop() { m_Stopped = true; }
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Failed || m_Stopped) return -1;
|
||||
if (m_Complete) return 1;
|
||||
if (m_Wait == 0)
|
||||
{
|
||||
if (!Check(m_Mode.Environment().Started() && m_Mode.Time().Started(), "production round services started")) return -1;
|
||||
if (!Check(m_Mode.Settings().Get("startTimeMinutes") == 840 && m_Mode.Settings().Get("timeMultiplier") == 1 && m_Mode.Time().StartMinutes() == 840 && m_Mode.Time().Multiplier() == 1, "both rounds retain original clock defaults and active progression settings")) return -1;
|
||||
m_Hour = m_Manager.GetTimeOfTheDay();
|
||||
m_Duration = m_Manager.GetDayDuration();
|
||||
if (m_Round == 1)
|
||||
{
|
||||
if (!Check(m_Mode.Settings().Get("startDateCode") == 0 && m_Mode.Settings().Get("weatherProfile") == 0 && m_Mode.Environment().DateCode() == 0 && m_Mode.Environment().Profile() == 0, "first instance uses authored environment defaults")) return -1;
|
||||
if (!Check(DateCode() == m_InitialDate && Weather() == m_InitialWeather && m_Manager.IsWeatherLooping() == m_InitialLoop, "default production startup preserves authored date and weather")) return -1;
|
||||
array<string> replies = {};
|
||||
if (!Check(ERR_EnvironmentCommands.Execute(m_Mode.Settings(), m_Mode.Environment(), {"mission", "date", "set", "2000-02-29"}, replies), "production date command handled")) return -1;
|
||||
if (!Check(ERR_EnvironmentCommands.Execute(m_Mode.Settings(), m_Mode.Environment(), {"mission", "weather", "set", "overcast"}, replies), "production weather command handled")) return -1;
|
||||
if (!Check(replies.Count() == 2 && replies[0].Contains("Saved for next round") && replies[1].Contains("Saved for next round"), "both commands report durable next-round saves")) return -1;
|
||||
// This is the actual mode's settings owner, not a detached sample service.
|
||||
ERR_Settings disk = new ERR_Settings(PATH);
|
||||
if (!Check(disk.Get("startDateCode") == 1000229 && disk.Get("weatherProfile") == 2 && disk.Get("radioDefenceSeconds") == 180 && disk.Get("timeMultiplier") == 1, "production saves persist environment and preserve unrelated defaults")) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Check(m_Mode.Settings().Get("startDateCode") == 1000229 && m_Mode.Settings().Get("weatherProfile") == 2 && m_Mode.Environment().DateCode() == 1000229 && m_Mode.Environment().Profile() == 2, "second real mode loads saved date and weather into production services")) return -1;
|
||||
}
|
||||
m_Wait = now + 2500;
|
||||
return 0;
|
||||
}
|
||||
if (now < m_Wait) return 0;
|
||||
if (!Check(m_Mode.Settings().Get("startDateCode") == 1000229 && m_Mode.Settings().Get("weatherProfile") == 2, "saved next-round settings remain intact")) return -1;
|
||||
if (m_Round == 1)
|
||||
{
|
||||
if (!Check(m_Mode.Environment().DateCode() == 0 && m_Mode.Environment().Profile() == 0 && DateCode() == m_InitialDate && Weather() == m_InitialWeather && m_Manager.IsWeatherLooping() == m_InitialLoop, "saving real mode settings leaves current environment unchanged across native ticks")) return -1;
|
||||
}
|
||||
else if (!Check(DateCode() == 1000229 && Weather() == "Overcast" && m_Manager.IsWeatherLooping(), "second round applies exact leap date and selected native weather family")) return -1;
|
||||
float advance = m_Manager.GetTimeOfTheDay() - m_Hour;
|
||||
if (advance < 0) advance += 24;
|
||||
if (!Check(advance > 0 && advance < 0.02 && m_Manager.GetIsDayAutoAdvanced() && m_Duration == ERR_TimeService.DayDuration(1) && m_Manager.GetDayDuration() == m_Duration, "native clock continues advancing without an environment-induced reset or rate change")) return -1;
|
||||
if (m_Round == 1)
|
||||
{
|
||||
JsonSaveContext marker = new JsonSaveContext();
|
||||
marker.EnableTypeDiscriminator(false);
|
||||
marker.WriteValue("completedRound", 1);
|
||||
if (!Check(marker.SaveToFile(MARKER), "first completed round leaves restart handoff marker")) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FileIO.FileExists(PATH)) FileIO.DeleteFile(PATH);
|
||||
if (FileIO.FileExists(PATH + ".bak")) FileIO.DeleteFile(PATH + ".bak");
|
||||
if (FileIO.FileExists(PATH + ".tmp")) FileIO.DeleteFile(PATH + ".tmp");
|
||||
if (FileIO.FileExists(MARKER)) FileIO.DeleteFile(MARKER);
|
||||
if (!Check(!FileIO.FileExists(PATH) && !FileIO.FileExists(PATH + ".bak") && !FileIO.FileExists(PATH + ".tmp") && !FileIO.FileExists(MARKER), "successful second round removes only fixture settings and marker files")) return -1;
|
||||
}
|
||||
m_Complete = true;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifdef WORKBENCH
|
||||
// Read-only native assertions. Run after site preparation and faction init,
|
||||
// before destructive vehicle fixtures. Does not load legacy full faction configs.
|
||||
class ERR_NativeFactionCatalogProbe
|
||||
{
|
||||
protected static ResourceName UAZ() { return "{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et"; }
|
||||
protected static ResourceName Mi8() { return "{DF5CCB7C0FF049F4}Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et"; }
|
||||
protected static bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: faction-catalog " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: faction-catalog " + detail, LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
protected static bool Catalogs(SCR_Faction faction)
|
||||
{
|
||||
array<SCR_EntityCatalog> catalogs = {};
|
||||
if (!Check(faction.GetAllFactionEntityCatalogs(catalogs) == 6, faction.GetFactionKey() + " retains all six catalog types")) return false;
|
||||
SCR_EntityCatalog vehicles = faction.GetFactionEntityCatalogOfType(EEntityCatalogType.VEHICLE);
|
||||
array<SCR_EntityCatalogEntry> entries = {};
|
||||
if (!Check(vehicles && vehicles.GetEntityList(entries) == 2, faction.GetFactionKey() + " has exactly two supported vehicle entries")) return false;
|
||||
bool uaz, mi8;
|
||||
foreach (SCR_EntityCatalogEntry entry : entries)
|
||||
{
|
||||
if (!Check(entry != null, "vehicle entry exists")) return false;
|
||||
ResourceName prefab = entry.GetPrefab();
|
||||
PrintFormat("ERR FACTION VEHICLE: faction=%1 prefab=%2", faction.GetFactionKey(), prefab);
|
||||
if (prefab == UAZ()) uaz = true;
|
||||
else if (prefab == Mi8()) mi8 = true;
|
||||
else return Check(false, "unexpected vehicle catalog entry " + prefab);
|
||||
}
|
||||
if (!Check(uaz && mi8 && vehicles.GetEntryWithPrefab(UAZ()) && vehicles.GetEntryWithPrefab(Mi8()), "catalog lookup resolves both unique mission vehicles")) return false;
|
||||
array<EEntityCatalogType> retained = {EEntityCatalogType.CHARACTER, EEntityCatalogType.GROUP, EEntityCatalogType.WEAPONS_TRIPOD, EEntityCatalogType.ITEM, EEntityCatalogType.SUPPLY_CONTAINER_ITEM};
|
||||
foreach (EEntityCatalogType kind : retained)
|
||||
{
|
||||
SCR_EntityCatalog catalog = faction.GetFactionEntityCatalogOfType(kind);
|
||||
if (!Check(catalog != null, faction.GetFactionKey() + " non-vehicle catalog exists " + typename.EnumToString(EEntityCatalogType, kind))) return false;
|
||||
catalog.GetEntityList(entries);
|
||||
PrintFormat("ERR FACTION RETAINED: faction=%1 type=%2 entries=%3", faction.GetFactionKey(), typename.EnumToString(EEntityCatalogType, kind), entries.Count());
|
||||
// Installed US/USSR supply-container catalogs are intentionally empty.
|
||||
if (kind != EEntityCatalogType.SUPPLY_CONTAINER_ITEM && !Check(!entries.IsEmpty(), "retained native content catalog is initialized and nonempty")) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected static bool Items(SCR_Faction faction, ResourceName dressing, ResourceName saline, ResourceName radio)
|
||||
{
|
||||
SCR_EntityCatalog items = faction.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM);
|
||||
return Check(items && items.GetEntryWithPrefab(dressing) && items.GetEntryWithPrefab(saline) && items.GetEntryWithPrefab(radio), faction.GetFactionKey() + " native dressing saline and backpack radio remain catalogued");
|
||||
}
|
||||
static bool Run(ERR_GameMode mode)
|
||||
{
|
||||
if (!Check(Replication.IsServer() && mode && mode.Active(), "active authority available")) return false;
|
||||
FactionManager manager = GetGame().GetFactionManager();
|
||||
if (!Check(manager != null, "native faction manager exists")) return false;
|
||||
SCR_Faction us = SCR_Faction.Cast(manager.GetFactionByKey("US"));
|
||||
SCR_Faction ussr = SCR_Faction.Cast(manager.GetFactionByKey("USSR"));
|
||||
if (!Check(us && ussr && mode.PlayerFaction() == us && mode.EnemyFaction() == ussr, "mission retains US and USSR faction identities")) return false;
|
||||
if (!Check(us.IsFactionEnemy(ussr) && ussr.IsFactionEnemy(us) && !us.IsFactionEnemy(us) && !ussr.IsFactionEnemy(ussr), "mutual enemy and same-faction relations preserved")) return false;
|
||||
if (!Check(us.GetFactionRadioEncryptionKey() == "chickenNuggets" && ussr.GetFactionRadioEncryptionKey() == "coldBorscht" && us.GetFactionRadioFrequency() == 48000 && ussr.GetFactionRadioFrequency() == 42000, "native radio encryption and frequencies preserved")) return false;
|
||||
if (!Check(us.GetCallsignInfo() && ussr.GetCallsignInfo(), "native faction callsign configurations resolve")) return false;
|
||||
if (!Catalogs(us) || !Catalogs(ussr)) return false;
|
||||
if (!Items(us, "{A81F501D3EF6F38E}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et", "{00E36F41CA310E2A}Prefabs/Items/Medicine/SalineBag_01/SalineBag_US_01.et", "{9B6B61BB3FE3DFB0}Prefabs/Items/Equipment/Radios/Radio_ANPRC77.et")) return false;
|
||||
if (!Items(ussr, "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et", "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et", "{54C68E438DD34265}Prefabs/Items/Equipment/Radios/Radio_R107M.et")) return false;
|
||||
SCR_EntityCatalogManagerComponent catalogManager = SCR_EntityCatalogManagerComponent.GetInstance();
|
||||
if (!Check(catalogManager && catalogManager.GetFactionEntityCatalogOfType(EEntityCatalogType.VEHICLE, "US") && catalogManager.GetFactionEntityCatalogOfType(EEntityCatalogType.ITEM, "USSR"), "global catalog manager retains faction vehicle and inventory access")) return false;
|
||||
ERR_SiteRuntime depot = mode.Sites().Find("everon-supply-2");
|
||||
Vehicle helicopter = mode.ExtractionVehicle();
|
||||
if (!Check(depot && depot.Transport && ERR_Actors.Alive(depot.Transport) && depot.Transport.GetPrefabData().GetPrefabName() == UAZ(), "physical finite depot vehicle is supported UAZ")) return false;
|
||||
if (!Check(helicopter && ERR_Actors.Alive(helicopter) && helicopter.GetPrefabData().GetPrefabName() == Mi8() && helicopter.FindComponent(HelicopterControllerComponent), "physical extraction aircraft is supported Mi8")) return false;
|
||||
array<BaseCompartmentSlot> seats = {};
|
||||
if (!Check(mode.Extraction().Seats(seats) >= 12, "physical aircraft still has required capacity")) return false;
|
||||
Print("ERR FACTION RESULT: successor faction catalog scope and retained native support; no driving or multiplayer claim");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,247 @@
|
||||
#ifdef WORKBENCH
|
||||
// Native queue length is not exposed: SCR_AIGroup.GetSpawnQueueSize() is a
|
||||
// compatibility stub returning zero. Observe dispatch on explicitly tagged
|
||||
// disposable groups instead; every engine call still reaches unchanged super.
|
||||
class ERR_NativeGuardDispatchTrace
|
||||
{
|
||||
static int Total;
|
||||
}
|
||||
modded class SCR_AIGroup
|
||||
{
|
||||
protected bool m_ERRGuardCancelTracked;
|
||||
protected int m_ERRGuardCancelDispatches;
|
||||
protected int m_ERRGuardCancelInitCalls;
|
||||
protected int m_ERRGuardCancelRequestCalls;
|
||||
void ERR_TrackGuardCancel()
|
||||
{
|
||||
m_ERRGuardCancelTracked = true;
|
||||
PrintFormat("ERR GUARD CANCEL TRACK: group=%1 initCalls=%2 requests=%3 agents=%4 spawnImmediately=%5 slots=%6 lifecycle=%7", this, m_ERRGuardCancelInitCalls, m_ERRGuardCancelRequestCalls, GetAgentsCount(), GetSpawnImmediately(), m_aUnitPrefabSlots.Count(), GetLifecyclePolicy());
|
||||
}
|
||||
override void EOnInit(IEntity owner)
|
||||
{
|
||||
m_ERRGuardCancelInitCalls++;
|
||||
if (m_ERRGuardCancelTracked) PrintFormat("ERR GUARD CANCEL LATE INIT: group=%1 initCalls=%2", this, m_ERRGuardCancelInitCalls);
|
||||
super.EOnInit(owner);
|
||||
}
|
||||
override void RequestSpawn(int slotsWanted = -1, float observerRange = 0)
|
||||
{
|
||||
m_ERRGuardCancelRequestCalls++;
|
||||
if (m_ERRGuardCancelTracked) PrintFormat("ERR GUARD CANCEL REQUEST: group=%1 request=%2 wanted=%3 range=%4 slots=%5", this, m_ERRGuardCancelRequestCalls, slotsWanted, observerRange, m_aUnitPrefabSlots.Count());
|
||||
super.RequestSpawn(slotsWanted, observerRange);
|
||||
}
|
||||
int ERR_GuardCancelDispatches() { return m_ERRGuardCancelDispatches; }
|
||||
// EOnInit assigns the cached utility before requesting members. The ignore-
|
||||
// spawning branch instead invokes all-members init immediately; exclude it.
|
||||
bool ERR_GuardCancelPendingInit() { return GetGroupUtilityComponent() && !m_bOnInitInvoked; }
|
||||
override bool ExpandOneMember()
|
||||
{
|
||||
if (m_ERRGuardCancelTracked)
|
||||
{
|
||||
m_ERRGuardCancelDispatches++;
|
||||
ERR_NativeGuardDispatchTrace.Total++;
|
||||
PrintFormat("ERR GUARD CANCEL DISPATCH: group=%1 dispatch=%2 agents=%3 slots=%4 complete=%5", this, m_ERRGuardCancelDispatches, GetAgentsCount(), m_aUnitPrefabSlots.Count(), IsExpandComplete());
|
||||
}
|
||||
return super.ExpandOneMember();
|
||||
}
|
||||
}
|
||||
|
||||
// Assemble only the owned-group portion of PENDING preparation. No authored
|
||||
// mission sites, stock, waypoints or live mission service are cloned or changed.
|
||||
class ERR_NativeGuardCancelOwner : ERR_SiteService
|
||||
{
|
||||
protected int m_Cancellations;
|
||||
void ERR_NativeGuardCancelOwner(ERR_GameMode mode) { m_Mode = mode; }
|
||||
int Cancellations() { return m_Cancellations; }
|
||||
protected override void CancelInitialGuardRequests()
|
||||
{
|
||||
m_Cancellations++;
|
||||
PrintFormat("ERR GUARD CANCEL OWNER: pendingState=%1 calls=%2 ownedSites=%3", m_State, m_Cancellations, m_Sites.Count());
|
||||
super.CancelInitialGuardRequests();
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
if (site.Group) PrintFormat("ERR GUARD CANCEL RETIRED: site=%1 group=%2 slots=%3 spawnImmediately=%4 agents=%5 complete=%6", site.Definition.Id, site.Group, site.Group.m_aUnitPrefabSlots.Count(), site.Group.GetSpawnImmediately(), site.Group.GetAgentsCount(), site.Group.IsExpandComplete());
|
||||
}
|
||||
bool Attach(SCR_AIGroup group, string label)
|
||||
{
|
||||
if (!group || m_Begun) return false;
|
||||
m_Begun = true;
|
||||
ERR_SiteRuntime site = new ERR_SiteRuntime();
|
||||
site.Definition = new ERR_SiteDefinition();
|
||||
site.Definition.Id = label;
|
||||
site.Definition.Guarded = true;
|
||||
site.Group = group;
|
||||
if (group.m_aUnitPrefabSlots) site.InitialGuardCount = group.m_aUnitPrefabSlots.Count();
|
||||
m_Sites.Insert(site);
|
||||
m_Entities.Insert(group);
|
||||
return site.InitialGuardCount == 6 && group.GetSpawnImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_NativeGuardCancelProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ref ERR_NativeGuardCancelOwner m_EmptyOwner;
|
||||
protected ref ERR_NativeGuardCancelOwner m_PartialOwner;
|
||||
protected ref ERR_NativeGuardCancelOwner m_ControlOwner;
|
||||
protected SCR_AIGroup m_Empty;
|
||||
protected SCR_AIGroup m_Partial;
|
||||
protected SCR_AIGroup m_Control;
|
||||
protected ref array<IEntity> m_PartialMembers = {};
|
||||
protected ref array<IEntity> m_DeletedMembers = {};
|
||||
protected ref array<SCR_AIGroup> m_MainGroups = {};
|
||||
protected int m_PartialDispatches;
|
||||
protected int m_TotalBeforeDelete;
|
||||
protected int m_Step;
|
||||
protected float m_Deadline;
|
||||
protected float m_ObserveUntil;
|
||||
protected bool m_RolledBack;
|
||||
void ERR_NativeGuardCancelProbe(ERR_GameMode mode) { m_Mode = mode; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: guard-cancel " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: guard-cancel " + detail, LogLevel.ERROR);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
protected int Members(SCR_AIGroup group, out array<IEntity> members)
|
||||
{
|
||||
members.Clear();
|
||||
if (!group) return 0;
|
||||
array<AIAgent> agents = {};
|
||||
group.GetAgents(agents);
|
||||
foreach (AIAgent agent : agents)
|
||||
{
|
||||
if (!agent) continue;
|
||||
IEntity actor = agent.GetControlledEntity();
|
||||
if (actor && !members.Contains(actor)) members.Insert(actor);
|
||||
}
|
||||
return members.Count();
|
||||
}
|
||||
protected SCR_AIGroup NewGroup(vector offset)
|
||||
{
|
||||
ERR_SiteRuntime outpost = m_Mode.Sites().Find("everon-outpost-1");
|
||||
if (!outpost || !outpost.Group) return null;
|
||||
SCR_AIGroup group = SCR_AIGroup.Cast(ERR_Actors.Spawn(m_Mode.Factions().GuardGroupPrefab, ERR_Actors.Ground(outpost.Group.GetOrigin() + offset)));
|
||||
if (group) group.ERR_TrackGuardCancel();
|
||||
return group;
|
||||
}
|
||||
protected bool OriginalSitesIntact()
|
||||
{
|
||||
if (!m_Mode.Sites() || m_Mode.Sites().Prepare() != ERR_PrepareResult.READY) return false;
|
||||
array<ERR_LocationComponent> locations = {};
|
||||
m_Mode.Locations(locations);
|
||||
array<SCR_AIGroup> groups = {};
|
||||
foreach (ERR_LocationComponent location : locations)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().Find(location.Id());
|
||||
if (site && site.Group) groups.Insert(site.Group);
|
||||
}
|
||||
if (groups.Count() != m_MainGroups.Count()) return false;
|
||||
foreach (SCR_AIGroup group : m_MainGroups)
|
||||
if (!group || !groups.Contains(group)) return false;
|
||||
return true;
|
||||
}
|
||||
protected bool CancelledStable()
|
||||
{
|
||||
array<IEntity> emptyMembers = {};
|
||||
array<IEntity> partialMembers = {};
|
||||
if (!m_Empty || Members(m_Empty, emptyMembers) != 0 || m_Empty.ERR_GuardCancelDispatches() != 0) return false;
|
||||
if (!m_Partial || Members(m_Partial, partialMembers) != m_PartialMembers.Count() || m_Partial.ERR_GuardCancelDispatches() != m_PartialDispatches) return false;
|
||||
foreach (IEntity actor : m_PartialMembers)
|
||||
if (!actor || !partialMembers.Contains(actor)) return false;
|
||||
return true;
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
// Each owner rolls back at most once. ERR_Actors.DeleteSpawned retains its
|
||||
// stock active-player protection; no player is assigned to these groups.
|
||||
if (m_RolledBack) return;
|
||||
m_RolledBack = true;
|
||||
if (m_EmptyOwner) m_EmptyOwner.Rollback();
|
||||
if (m_PartialOwner) m_PartialOwner.Rollback();
|
||||
if (m_ControlOwner) m_ControlOwner.Rollback();
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Deadline == 0) m_Deadline = now + 90000;
|
||||
if (now > m_Deadline || !m_Mode.Active()) { Check(false, "bounded fixture deadline or active mission lost"); return -1; }
|
||||
if (m_Step == 0)
|
||||
{
|
||||
array<ERR_LocationComponent> locations = {};
|
||||
m_Mode.Locations(locations);
|
||||
foreach (ERR_LocationComponent location : locations)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().Find(location.Id());
|
||||
if (site && site.Group) m_MainGroups.Insert(site.Group);
|
||||
}
|
||||
ERR_NativeGuardDispatchTrace.Total = 0;
|
||||
m_EmptyOwner = new ERR_NativeGuardCancelOwner(m_Mode);
|
||||
m_PartialOwner = new ERR_NativeGuardCancelOwner(m_Mode);
|
||||
m_ControlOwner = new ERR_NativeGuardCancelOwner(m_Mode);
|
||||
m_Empty = NewGroup("50 0 60");
|
||||
if (!Check(m_EmptyOwner.Attach(m_Empty, "guard-cancel-empty"), "empty case owns one six-slot automatic native group")) return -1;
|
||||
array<IEntity> initial = {};
|
||||
if (!Check(m_Empty.ERR_GuardCancelPendingInit() && Members(m_Empty, initial) == 0 && m_Empty.ERR_GuardCancelDispatches() == 0 && !m_Empty.IsExpandComplete(), "empty case is cancelled before its first native member dispatch")) return -1;
|
||||
m_EmptyOwner.Stop();
|
||||
m_EmptyOwner.Stop();
|
||||
if (!Check(m_EmptyOwner.Cancellations() == 1 && !m_Empty.GetSpawnImmediately() && m_Empty.m_aUnitPrefabSlots.IsEmpty(), "empty cancellation retires only this instance's spawn intent once")) return -1;
|
||||
if (!Check(m_Empty && m_EmptyOwner.Owns(m_Empty) && m_EmptyOwner.Prepare() == ERR_PrepareResult.FAILED && !m_Mode.Sites().Owns(m_Empty), "repeated actual preparation stop retains only the disposable empty group for observation")) return -1;
|
||||
m_Partial = NewGroup("-50 0 60");
|
||||
if (!Check(m_PartialOwner.Attach(m_Partial, "guard-cancel-partial"), "partial case owns a separate six-slot automatic native group")) return -1;
|
||||
m_Control = NewGroup("0 0 100");
|
||||
if (!Check(m_ControlOwner.Attach(m_Control, "guard-cancel-control"), "uncancelled six-slot control uses the same native queue")) return -1;
|
||||
m_Step = 1;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
array<IEntity> emptyMembers = {};
|
||||
if (!m_Empty || Members(m_Empty, emptyMembers) != 0 || m_Empty.ERR_GuardCancelDispatches() != 0)
|
||||
{ Check(false, "empty group received late dispatch or members after cancellation"); return -1; }
|
||||
if (!m_Partial || !m_Control) { Check(false, "disposable observation group disappeared before cancellation"); return -1; }
|
||||
if (Members(m_Partial, m_PartialMembers) == 0) return 0;
|
||||
if (!Check(m_PartialMembers.Count() < 6 && !m_Partial.IsExpandComplete() && m_Partial.ERR_GuardCancelDispatches() > 0, "native queue produced a real partial squad before cancellation")) return -1;
|
||||
// The fixture tick runs after native dispatch returns, so the queue has
|
||||
// finished re-enqueuing this partial fill. Do not purge from inside AddAgent.
|
||||
m_PartialOwner.Stop();
|
||||
m_PartialOwner.Stop();
|
||||
if (!Check(m_PartialOwner.Cancellations() == 1 && !m_Partial.GetSpawnImmediately() && m_Partial.m_aUnitPrefabSlots.IsEmpty(), "partial cancellation retires future spawn intent without deleting present actors")) return -1;
|
||||
m_PartialDispatches = m_Partial.ERR_GuardCancelDispatches();
|
||||
if (!Check(m_PartialOwner.Prepare() == ERR_PrepareResult.FAILED && m_PartialOwner.Owns(m_Partial), "partial preparation stops idempotently while existing members remain")) return -1;
|
||||
PrintFormat("ERR GUARD CANCEL: partialMembers=%1 dispatches=%2 observationSeconds=15", m_PartialMembers.Count(), m_PartialDispatches);
|
||||
m_ObserveUntil = now + 15000;
|
||||
m_Step = 2;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (!CancelledStable()) { Check(false, "cancelled groups changed member identity/count or received another native dispatch"); return -1; }
|
||||
array<IEntity> controlMembers = {};
|
||||
int controlCount = Members(m_Control, controlMembers);
|
||||
if (!m_Control || controlCount > 6) { Check(false, "uncancelled control vanished or exceeded its requested size"); return -1; }
|
||||
if (now < m_ObserveUntil || controlCount != 6 || !m_Control.IsExpandComplete()) return 0;
|
||||
if (!Check(m_Control.ERR_GuardCancelDispatches() >= 6 && m_Control.m_aUnitPrefabSlots.Count() == 6 && m_Control.GetSpawnImmediately(), "uncancelled native control reached six while cancelled groups stayed unchanged for at least fifteen seconds")) return -1;
|
||||
if (!Check(OriginalSitesIntact(), "original mission site groups and ready service remain intact")) return -1;
|
||||
foreach (IEntity partialMember : m_PartialMembers) m_DeletedMembers.Insert(partialMember);
|
||||
foreach (IEntity controlMember : controlMembers) m_DeletedMembers.Insert(controlMember);
|
||||
foreach (IEntity actor : m_DeletedMembers)
|
||||
if (!Check(!ERR_Actors.Player(actor), "rollback target is a disposable non-player character")) return -1;
|
||||
m_TotalBeforeDelete = ERR_NativeGuardDispatchTrace.Total;
|
||||
Stop();
|
||||
m_ObserveUntil = now + 6000;
|
||||
m_Step = 3;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (ERR_NativeGuardDispatchTrace.Total != m_TotalBeforeDelete) { Check(false, "native dispatch occurred after rollback"); return -1; }
|
||||
if (now < m_ObserveUntil) return 0;
|
||||
if (!Check(!m_Empty && !m_Partial && !m_Control, "each disposable group was deleted once by its real owner rollback")) return -1;
|
||||
foreach (IEntity deleted : m_DeletedMembers)
|
||||
if (!Check(!deleted, "each physical partial/control member is actually deleted after rollback")) return -1;
|
||||
if (!Check(OriginalSitesIntact(), "original mission groups remain intact after rollback and six-second observation")) return -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -117,7 +117,7 @@ class ERR_NativeLifecycleProbe
|
||||
reservations.Set(13, second);
|
||||
vector position;
|
||||
int count = 2;
|
||||
while (count < 25 && m_Placement.Prison(m_Mode.PrisonPosition(), reservations, position))
|
||||
while (count < 16 && m_Placement.Prison(m_Mode.PrisonPosition(), reservations, position))
|
||||
{
|
||||
reservations.Set(100 + count, position);
|
||||
count++;
|
||||
@@ -126,7 +126,7 @@ class ERR_NativeLifecycleProbe
|
||||
if (!Check(count >= 11 && !m_Placement.Prison(m_Mode.PrisonPosition(), reservations, position), "occupied and pending slots exhaust a bounded grid without overlap or outside fallback")) return -1;
|
||||
vector prison = m_Mode.PrisonPosition();
|
||||
foreach (int id, vector reserved : reservations)
|
||||
if (!Check(Math.AbsFloat(reserved[0] - prison[0]) <= 3.1 && Math.AbsFloat(reserved[2] - prison[2]) <= 3.1, "candidate remains inside authored prison")) return -1;
|
||||
if (!Check(Math.AbsFloat(reserved[0] - prison[0]) <= 4.6 && Math.AbsFloat(reserved[2] - prison[2]) <= 4.6, "candidate remains inside authored prison")) return -1;
|
||||
reservations.Remove(1);
|
||||
if (!Check(m_Placement.Prison(m_Mode.PrisonPosition(), reservations, position) && vector.DistanceXZ(position, first) < 0.1, "released pending reservation becomes available again")) return -1;
|
||||
m_Position = first;
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
#ifdef WORKBENCH
|
||||
// Opt-in native medical-effects fixture. Treatment enters at the real item's
|
||||
// completion boundary; manual user actions/animations and remote clients are not
|
||||
// simulated. Only fixture-owned characters are injured or deleted.
|
||||
class ERR_NativeMedicalProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Casualty;
|
||||
protected IEntity m_Healer;
|
||||
protected IEntity m_Dressing;
|
||||
protected IEntity m_Saline;
|
||||
protected IEntity m_SpareSaline;
|
||||
protected SCR_CharacterDamageManagerComponent m_Damage;
|
||||
protected CharacterControllerComponent m_Controller;
|
||||
protected SCR_CharacterBloodHitZone m_Blood;
|
||||
protected SCR_SalineStorageComponent m_SalineStorage;
|
||||
protected SCR_InventoryStorageManagerComponent m_Inventory;
|
||||
protected ref array<IEntity> m_Owned = {};
|
||||
protected int m_Step;
|
||||
protected int m_Result;
|
||||
protected bool m_Stopped;
|
||||
protected bool m_Recovered;
|
||||
protected float m_Wait;
|
||||
protected float m_Deadline;
|
||||
protected float m_InfusionStarted;
|
||||
protected float m_SeedBlood;
|
||||
protected float m_PreInfusionBlood;
|
||||
protected float m_RegenSpeed;
|
||||
protected float m_NextDiagnostic;
|
||||
|
||||
void ERR_NativeMedicalProbe(ERR_GameMode mode) { m_Mode = mode; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: medical " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: medical " + detail, LogLevel.ERROR);
|
||||
Trace("failure");
|
||||
m_Result = -1;
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
protected IEntity Spawn(ResourceName prefab, vector position)
|
||||
{
|
||||
IEntity entity = ERR_Actors.Spawn(prefab, ERR_Actors.Ground(position));
|
||||
if (entity) { m_Owned.Insert(entity); m_Mode.Own(entity); }
|
||||
return entity;
|
||||
}
|
||||
protected int SalineEffects()
|
||||
{
|
||||
if (!m_Damage) return 0;
|
||||
array<ref SCR_PersistentDamageEffect> effects = {};
|
||||
m_Damage.GetPersistentEffects(effects);
|
||||
int count;
|
||||
foreach (SCR_PersistentDamageEffect effect : effects)
|
||||
if (SCR_SalineDamageEffect.Cast(effect)) count++;
|
||||
return count;
|
||||
}
|
||||
protected int AttachedBags()
|
||||
{
|
||||
if (!m_SalineStorage) return 0;
|
||||
array<IEntity> items = {};
|
||||
m_SalineStorage.GetAll(items);
|
||||
return items.Count();
|
||||
}
|
||||
protected void Trace(string stage)
|
||||
{
|
||||
if (!m_Blood || !m_Controller || !m_Damage) return;
|
||||
PrintFormat("ERR MEDICAL STATE: stage=%1 blood=%2 bloodState=%3 unconscious=%4 bleeding=%5 salineEffects=%6 attachedBags=%7", stage, m_Blood.GetHealth(), m_Blood.GetDamageState(), m_Controller.IsUnconscious(), m_Damage.IsBleeding(), SalineEffects(), AttachedBags());
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
// Items first, then characters; native scheduled saline deletion is null-safe.
|
||||
for (int i = m_Owned.Count() - 1; i >= 0; i--) ERR_Actors.DeleteSpawned(m_Owned[i]);
|
||||
m_Owned.Clear();
|
||||
m_Casualty = null;
|
||||
m_Healer = null;
|
||||
m_Dressing = null;
|
||||
m_Saline = null;
|
||||
m_SpareSaline = null;
|
||||
m_Damage = null;
|
||||
m_Controller = null;
|
||||
m_Blood = null;
|
||||
m_SalineStorage = null;
|
||||
m_Inventory = null;
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Result != 0) return m_Result;
|
||||
if (m_Stopped) return -1;
|
||||
if (!Replication.IsServer() || !m_Mode || !m_Mode.Active())
|
||||
{
|
||||
Check(false, "fixture requires the active authority");
|
||||
return -1;
|
||||
}
|
||||
if (m_Deadline > 0 && now > m_Deadline)
|
||||
{
|
||||
Check(false, "native medical state timed out at step " + m_Step.ToString());
|
||||
return -1;
|
||||
}
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
// Keep fixture actors separate from the real prisoner spawn.
|
||||
vector anchor = m_Mode.PrisonPosition() + "100 0 100";
|
||||
m_Casualty = Spawn(m_Mode.Factions().PrisonerPrefab, anchor);
|
||||
m_Healer = Spawn(m_Mode.Factions().PrisonerPrefab, anchor + "3 0 0");
|
||||
m_Dressing = Spawn("{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et", anchor + "4 0 0");
|
||||
m_Saline = Spawn("{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et", anchor + "5 0 0");
|
||||
m_SpareSaline = Spawn("{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et", anchor + "6 0 0");
|
||||
if (!Check(m_Casualty && m_Healer && m_Dressing && m_Saline && m_SpareSaline, "two isolated characters and finite stock-type medicine spawned")) return -1;
|
||||
if (!Check(!ERR_Actors.Player(m_Casualty) && !ERR_Actors.Player(m_Healer), "neither medical actor is a real player")) return -1;
|
||||
m_Deadline = now + 120000;
|
||||
m_Wait = now + 1000;
|
||||
m_Step = 1;
|
||||
return 0;
|
||||
}
|
||||
if (!ERR_Actors.Alive(m_Casualty) || !ERR_Actors.Alive(m_Healer))
|
||||
{
|
||||
Check(false, "owned casualty or healer died unexpectedly");
|
||||
return -1;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
m_Damage = SCR_CharacterDamageManagerComponent.Cast(m_Casualty.FindComponent(SCR_CharacterDamageManagerComponent));
|
||||
m_Controller = CharacterControllerComponent.Cast(m_Casualty.FindComponent(CharacterControllerComponent));
|
||||
m_SalineStorage = SCR_SalineStorageComponent.Cast(m_Casualty.FindComponent(SCR_SalineStorageComponent));
|
||||
m_Inventory = SCR_InventoryStorageManagerComponent.Cast(m_Healer.FindComponent(SCR_InventoryStorageManagerComponent));
|
||||
if (!Check(m_Damage && m_Controller && m_SalineStorage && m_Inventory, "native health, controller and medical storage components available")) return -1;
|
||||
m_Blood = m_Damage.GetBloodHitZone();
|
||||
if (!Check(m_Blood && !m_Controller.IsUnconscious() && !m_Damage.IsBleeding(), "casualty begins healthy and conscious")) return -1;
|
||||
if (!Check(m_Inventory.TryInsertItem(m_Dressing) && m_Inventory.TryInsertItem(m_Saline) && m_Inventory.TryInsertItem(m_SpareSaline), "finite medical items enter healer inventory")) return -1;
|
||||
SCR_ConsumableItemComponent dressing = SCR_ConsumableItemComponent.Cast(m_Dressing.FindComponent(SCR_ConsumableItemComponent));
|
||||
SCR_ConsumableItemComponent saline = SCR_ConsumableItemComponent.Cast(m_Saline.FindComponent(SCR_ConsumableItemComponent));
|
||||
if (!Check(dressing && saline, "stock items contain actual native consumable components")) return -1;
|
||||
SCR_ConsumableBandage bandageEffect = SCR_ConsumableBandage.Cast(dressing.GetConsumableEffect());
|
||||
SCR_ConsumableSalineBag salineEffect = SCR_ConsumableSalineBag.Cast(saline.GetConsumableEffect());
|
||||
SCR_EConsumableFailReason reason;
|
||||
if (!Check(bandageEffect && salineEffect && !bandageEffect.CanApplyEffect(m_Casualty, m_Healer, reason) && !salineEffect.CanApplyEffect(m_Casualty, m_Healer, reason), "healthy casualty rejects bandage and saline")) return -1;
|
||||
array<HitZone> zones = {};
|
||||
m_Damage.GetHitZonesOfGroupFromOwner(ECharacterHitZoneGroup.LEFTARM, zones);
|
||||
SCR_CharacterHitZone wound;
|
||||
foreach (HitZone zone : zones)
|
||||
{
|
||||
SCR_CharacterHitZone candidate = SCR_CharacterHitZone.Cast(zone);
|
||||
if (candidate && candidate.GetMaxBleedingRate() > 0) { wound = candidate; break; }
|
||||
}
|
||||
if (!Check(wound != null, "native left-arm hit zone can bleed")) return -1;
|
||||
wound.SetHealthScaled(0.5);
|
||||
m_Damage.AddBleedingEffectOnHitZone(wound);
|
||||
float threshold = m_Blood.GetDamageStateThreshold(ECharacterBloodState.UNCONSCIOUS) * m_Blood.GetMaxHealth();
|
||||
float destroyed = m_Blood.GetDamageStateThreshold(ECharacterBloodState.DESTROYED) * m_Blood.GetMaxHealth();
|
||||
if (!Check(threshold - destroyed > 200, "native blood thresholds permit a survivable recovery fixture")) return -1;
|
||||
// Initial casualty condition only. All subsequent blood changes are native effects.
|
||||
m_Blood.SetHealth(threshold - 100);
|
||||
m_SeedBlood = m_Blood.GetHealth();
|
||||
m_Wait = now + 5000;
|
||||
m_Step = 2;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
Trace("untreated blood loss");
|
||||
if (!Check(m_Damage.IsBleeding() && m_Blood.GetHealth() < m_SeedBlood && m_Controller.IsUnconscious(), "native bleeding reduces real blood and causes unconsciousness")) return -1;
|
||||
SCR_ConsumableItemComponent dressing = SCR_ConsumableItemComponent.Cast(m_Dressing.FindComponent(SCR_ConsumableItemComponent));
|
||||
SCR_ConsumableBandage effect = SCR_ConsumableBandage.Cast(dressing.GetConsumableEffect());
|
||||
SCR_EConsumableFailReason reason;
|
||||
if (!Check(effect.CanApplyEffectToHZ(m_Casualty, m_Healer, ECharacterHitZoneGroup.LEFTARM, reason), "real dressing accepts bleeding arm")) return -1;
|
||||
ItemUseParameters parameters = effect.GetAnimationParameters(m_Dressing, m_Casualty, ECharacterHitZoneGroup.LEFTARM);
|
||||
if (!Check(parameters && effect.GetDeleteOnUse(), "native dressing parameters and finite consumption policy are valid")) return -1;
|
||||
dressing.ApplyItemEffect(m_Casualty, m_Healer, parameters, m_Dressing, effect.GetDeleteOnUse());
|
||||
m_Wait = now + 500;
|
||||
m_Step = 3;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (!Check(!m_Dressing && !m_Damage.IsBleeding() && m_Damage.GetGroupDamageOverTime(ECharacterHitZoneGroup.LEFTARM, EDamageType.BLEEDING) == 0, "dressing is consumed and native bleeding is stopped")) return -1;
|
||||
if (!Check(m_Controller.IsUnconscious(), "bandage alone has not fabricated blood recovery")) return -1;
|
||||
SCR_ConsumableItemComponent saline = SCR_ConsumableItemComponent.Cast(m_Saline.FindComponent(SCR_ConsumableItemComponent));
|
||||
SCR_ConsumableSalineBag effect = SCR_ConsumableSalineBag.Cast(saline.GetConsumableEffect());
|
||||
SCR_EConsumableFailReason reason;
|
||||
if (!Check(effect && effect.CanApplyEffect(m_Casualty, m_Healer, reason) && !effect.GetDeleteOnUse(), "native saline accepts real blood loss and retains bag for infusion")) return -1;
|
||||
ItemUseParameters parameters = effect.GetAnimationParameters(m_Saline, m_Casualty);
|
||||
if (!Check(parameters != null, "native saline item parameters available")) return -1;
|
||||
m_PreInfusionBlood = m_Blood.GetHealth();
|
||||
m_RegenSpeed = effect.GetItemRegenSpeed();
|
||||
saline.ApplyItemEffect(m_Casualty, m_Healer, parameters, m_Saline, effect.GetDeleteOnUse());
|
||||
m_InfusionStarted = now;
|
||||
m_Wait = now + 1000;
|
||||
m_Step = 4;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
array<IEntity> attached = {};
|
||||
m_SalineStorage.GetAll(attached);
|
||||
if (!Check(m_Saline && attached.Count() == 1 && attached.Contains(m_Saline) && m_Damage.GetGroupSalineBagged(ECharacterHitZoneGroup.RIGHTARM) && SalineEffects() == 1, "real saline bag occupies native treatment slot with one healing effect")) return -1;
|
||||
SCR_ConsumableItemComponent spare = SCR_ConsumableItemComponent.Cast(m_SpareSaline.FindComponent(SCR_ConsumableItemComponent));
|
||||
SCR_EConsumableFailReason reason;
|
||||
if (!Check(!spare.GetConsumableEffect().CanApplyEffect(m_Casualty, m_Healer, reason) && reason == SCR_EConsumableFailReason.ALREADY_APPLIED && m_SpareSaline, "occupied treatment slot rejects another bag without consuming spare")) return -1;
|
||||
m_NextDiagnostic = now;
|
||||
m_Step = 5;
|
||||
}
|
||||
if (m_Step == 5)
|
||||
{
|
||||
if (now >= m_NextDiagnostic) { Trace("native infusion"); m_NextDiagnostic = now + 10000; }
|
||||
if (!m_Controller.IsUnconscious()) m_Recovered = true;
|
||||
if (m_Saline || AttachedBags() != 0 || SalineEffects() != 0 || m_Damage.GetGroupSalineBagged(ECharacterHitZoneGroup.RIGHTARM)) return 0;
|
||||
float requiredGain = Math.Min(m_RegenSpeed * 60, (m_Blood.GetMaxHealth() - m_PreInfusionBlood) * 0.8);
|
||||
if (!Check(m_RegenSpeed > 0 && m_Blood.GetHealth() - m_PreInfusionBlood >= requiredGain, "native infusion restores substantial blood without setting health again")) return -1;
|
||||
if (!Check(m_Recovered && !m_Controller.IsUnconscious() && ERR_Actors.CanFight(m_Casualty), "casualty regains consciousness through native health recovery")) return -1;
|
||||
if (!Check(now - m_InfusionStarted >= 85000 && !m_Saline && AttachedBags() == 0 && SalineEffects() == 0, "finite saline expires after native duration and releases treatment state")) return -1;
|
||||
if (!Check(m_SpareSaline != null, "unused spare survives the completed infusion")) return -1;
|
||||
InventoryItemComponent spareItem = InventoryItemComponent.Cast(m_SpareSaline.FindComponent(InventoryItemComponent));
|
||||
if (!Check(spareItem && spareItem.GetParentSlot(), "rejected spare bag remains a physical inventory item")) return -1;
|
||||
m_Result = 1;
|
||||
Stop();
|
||||
Print("ERR MEDICAL RESULT: native blood loss, finite treatment and recovery; not manual action or multiplayer acceptance");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,183 @@
|
||||
#ifdef WORKBENCH
|
||||
// Explicit disposable-world fixture: destroy all four authored radio documents,
|
||||
// then move the real participant to the station. No replacement clues or actors
|
||||
// are used to grant discovery; the normal site tick must identify the station.
|
||||
class ERR_NativeObjectiveLossProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Player;
|
||||
protected ERR_SiteRuntime m_Radio;
|
||||
protected ref array<IEntity> m_Documents = {};
|
||||
protected IEntity m_NonParticipant;
|
||||
protected IEntity m_Blocker;
|
||||
protected bool m_Partial;
|
||||
protected bool m_SettingSaved;
|
||||
protected int m_RevealChance;
|
||||
protected int m_Step;
|
||||
protected int m_Identifications;
|
||||
protected float m_Wait;
|
||||
protected float m_Deadline;
|
||||
void ERR_NativeObjectiveLossProbe(ERR_GameMode mode, IEntity player, bool partial)
|
||||
{
|
||||
m_Mode = mode; m_Player = player; m_Partial = partial;
|
||||
m_Mode.OnLocationDiscovered().Insert(Discovered);
|
||||
}
|
||||
protected void Discovered(ERR_LocationComponent location, int previous, int current)
|
||||
{
|
||||
if (m_Radio && location == m_Radio.Location && current == 2) m_Identifications++;
|
||||
}
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: objective-loss " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: objective-loss " + detail, LogLevel.ERROR);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
protected void Move(vector position)
|
||||
{
|
||||
vector transform[4];
|
||||
m_Player.GetWorldTransform(transform);
|
||||
transform[3] = ERR_Actors.Ground(position);
|
||||
ChimeraCharacter.Cast(m_Player).Teleport(transform);
|
||||
}
|
||||
protected void CollectDocuments(out array<IEntity> documents)
|
||||
{
|
||||
documents.Clear();
|
||||
array<ERR_LocationComponent> locations = {};
|
||||
m_Mode.Locations(locations);
|
||||
array<IEntity> stock = {};
|
||||
foreach (ERR_LocationComponent location : locations)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().Find(location.Id());
|
||||
if (!site || !site.Container) continue;
|
||||
ERR_Inventory.AppendUnique(InventoryStorageManagerComponent.Cast(site.Container.FindComponent(InventoryStorageManagerComponent)), stock);
|
||||
}
|
||||
ERR_Inventory.AppendUnique(InventoryStorageManagerComponent.Cast(m_Player.FindComponent(InventoryStorageManagerComponent)), stock);
|
||||
foreach (IEntity item : stock)
|
||||
{
|
||||
ERR_DocumentComponent document = ERR_DocumentComponent.Cast(item.FindComponent(ERR_DocumentComponent));
|
||||
if (document && document.TargetId() == m_Radio.Location.Id()) documents.Insert(item);
|
||||
}
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Mode)
|
||||
{
|
||||
m_Mode.OnLocationDiscovered().Remove(Discovered);
|
||||
if (m_SettingSaved) m_Mode.Settings().Set("intelRevealChancePercent", m_RevealChance);
|
||||
}
|
||||
m_SettingSaved = false;
|
||||
ERR_Actors.DeleteSpawned(m_NonParticipant);
|
||||
ERR_Actors.DeleteSpawned(m_Blocker);
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Deadline == 0) m_Deadline = now + 60000;
|
||||
if (now > m_Deadline || !m_Mode.Active() || !ERR_Actors.CanFight(m_Player))
|
||||
{
|
||||
Check(false, "fixture lost its active conscious participant or exceeded its deadline");
|
||||
return -1;
|
||||
}
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
m_Radio = m_Mode.Sites().Find("everon-radio-1");
|
||||
if (!Check(m_Radio && m_Radio.Location && m_Radio.Location.Knowledge() == 0 && m_Radio.Definition.DiscoverRadius == 8, "authored station is initially unknown with bounded eight-metre discovery")) return -1;
|
||||
CollectDocuments(m_Documents);
|
||||
if (!Check(m_Documents.Count() == 4, "four distinct physical documents exist before deliberate loss")) return -1;
|
||||
if (!Check(m_Mode.UnlockPrison(m_Player) && m_Mode.Phase() == ERR_Phase.RADIO_SEARCH, "real prisoner enters radio search through ordinary mission interface")) return -1;
|
||||
if (m_Partial)
|
||||
{
|
||||
m_RevealChance = m_Mode.Settings().Get("intelRevealChancePercent");
|
||||
m_SettingSaved = true;
|
||||
if (!Check(m_Mode.Settings().Set("intelRevealChancePercent", 0), "isolated first document produces only partial knowledge")) return -1;
|
||||
ERR_SiteRuntime cache = m_Mode.Sites().Find("everon-supply-1");
|
||||
Move(cache.Container.GetOrigin() + "0 0 2");
|
||||
InventoryStorageManagerComponent source = InventoryStorageManagerComponent.Cast(cache.Container.FindComponent(InventoryStorageManagerComponent));
|
||||
SCR_InventoryStorageManagerComponent target = SCR_InventoryStorageManagerComponent.Cast(m_Player.FindComponent(SCR_InventoryStorageManagerComponent));
|
||||
array<IEntity> stock = {};
|
||||
ERR_Inventory.Items(source, stock);
|
||||
IEntity selected;
|
||||
foreach (IEntity item : stock) if (m_Documents.Contains(item)) { selected = item; break; }
|
||||
BaseInventoryStorageComponent destination;
|
||||
if (selected && target) destination = target.FindStorageForItem(selected);
|
||||
if (!Check(destination && source.TryMoveItemToStorage(selected, destination), "one real document transfer accepted before the remaining clues are lost")) return -1;
|
||||
m_Wait = now + 8000;
|
||||
}
|
||||
m_Step = 1;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
int expected;
|
||||
if (m_Partial) expected = 1;
|
||||
if (!Check(m_Radio.Location.Knowledge() == expected, "ordinary clue processing leaves the requested unknown or partial station state")) return -1;
|
||||
foreach (IEntity document : m_Documents) if (document) SCR_EntityHelper.DeleteEntityAndChildren(document);
|
||||
m_Step = 2;
|
||||
m_Wait = now + 1500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
foreach (IEntity removed : m_Documents)
|
||||
if (!Check(!removed, "each original physical document is deleted")) return -1;
|
||||
array<IEntity> remaining = {};
|
||||
CollectDocuments(remaining);
|
||||
if (!Check(remaining.IsEmpty() && m_Mode.Sites().Prepare() == ERR_PrepareResult.READY, "all targeted documents are absent and preparation does not replenish them")) return -1;
|
||||
Move(m_Radio.Location.Position() + "0 0 20");
|
||||
m_NonParticipant = ERR_Actors.Spawn(m_Mode.Factions().PrisonerPrefab, ERR_Actors.Ground(m_Radio.Location.Position() + "3 0 0"));
|
||||
if (!Check(m_NonParticipant != null, "disposable unpossessed character created for authorization rejection")) return -1;
|
||||
m_Mode.Own(m_NonParticipant);
|
||||
if (!Check(!m_Mode.Sites().CanObserve(m_NonParticipant, m_Radio), "unpossessed character cannot identify the station")) return -1;
|
||||
m_Step = 3;
|
||||
m_Wait = now + 6000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
int expected;
|
||||
if (m_Partial) expected = 1;
|
||||
if (!Check(m_Radio.Location.Knowledge() == expected && !m_Mode.Sites().CanObserve(m_Player, m_Radio), "distant participant and nearby nonparticipant do not reveal the station")) return -1;
|
||||
ERR_Actors.DeleteSpawned(m_NonParticipant);
|
||||
m_Blocker = ERR_Actors.Spawn("{A67420C1FB91856E}Prefabs/ERR/PrisonWall.et", ERR_Actors.Ground(m_Radio.Location.Position() + "-1.5 0 2"));
|
||||
if (!Check(m_Blocker != null, "physical obstruction created before close approach")) return -1;
|
||||
m_Mode.Own(m_Blocker);
|
||||
Move(m_Radio.Location.Position() + "0 0 4");
|
||||
m_Step = 4;
|
||||
m_Wait = now + 6000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
int expected;
|
||||
if (m_Partial) expected = 1;
|
||||
PrintFormat("ERR OBJECTIVE LOSS: player=%1 radio=%2 knowledge=%3 visible=%4", m_Player.GetOrigin(), m_Radio.Location.Position(), m_Radio.Location.Knowledge(), m_Mode.Sites().CanObserve(m_Player, m_Radio));
|
||||
if (!Check(m_Radio.Location.Knowledge() == expected && !m_Mode.Sites().CanObserve(m_Player, m_Radio), "a nearby station behind a wall remains unidentified")) return -1;
|
||||
ERR_Actors.DeleteSpawned(m_Blocker);
|
||||
m_Step = 5;
|
||||
m_Wait = now + 6000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 5)
|
||||
{
|
||||
TraceParam sight = new TraceParam();
|
||||
sight.Start = m_Player.GetOrigin() + "0 1.5 0";
|
||||
sight.End = m_Radio.Location.Position() + "0 1.3 0";
|
||||
sight.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
|
||||
sight.LayerMask = TRACE_LAYER_CAMERA;
|
||||
sight.Exclude = m_Player;
|
||||
float fraction = m_Mode.GetWorld().TraceMove(sight, null);
|
||||
PrintFormat("ERR OBJECTIVE LOSS FINAL: player=%1 radio=%2 knowledge=%3 identifications=%4 visible=%5", m_Player.GetOrigin(), m_Radio.Location.Position(), m_Radio.Location.Knowledge(), m_Identifications, m_Mode.Sites().CanObserve(m_Player, m_Radio));
|
||||
PrintFormat("ERR OBJECTIVE LOSS SIGHT: fraction=%1 hit=%2 blockerRemaining=%3", fraction, sight.TraceEnt, m_Blocker);
|
||||
if (!Check(m_Mode.Sites().CanObserve(m_Player, m_Radio) && m_Radio.Location.Knowledge() == 2 && m_Identifications == 1, "actual participant with clear close approach identifies the station once through normal discovery")) return -1;
|
||||
array<IEntity> remaining = {};
|
||||
CollectDocuments(remaining);
|
||||
if (!Check(remaining.IsEmpty(), "physical discovery creates no replacement documents")) return -1;
|
||||
if (!Check(m_Mode.RadioDefence().CanBegin(m_Player, m_Radio.Location) && m_Mode.TuneRadio(m_Player, m_Radio.Location) && m_Mode.Phase() == ERR_Phase.RADIO_DEFENCE, "identified station permits ordinary authorized tuning after complete document loss")) return -1;
|
||||
Stop();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
#ifdef WORKBENCH
|
||||
// Observe existing physical guards. No teleporting, spawned soldiers or forced
|
||||
// completion: a full ordered loop and physical movement must happen natively.
|
||||
class ERR_NativePatrolProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected string m_SiteId;
|
||||
protected ERR_SiteRuntime m_Site;
|
||||
protected IEntity m_Actor;
|
||||
protected vector m_Origin;
|
||||
protected float m_Deadline;
|
||||
protected int m_Completions;
|
||||
protected int m_LastIndex = -1;
|
||||
protected bool m_BadSequence;
|
||||
protected bool m_Moved;
|
||||
protected bool m_Started;
|
||||
protected bool m_Prepared;
|
||||
protected float m_AcquireDeadline;
|
||||
protected bool m_Finished;
|
||||
protected int m_LastQueueSample = -1;
|
||||
protected ref map<string, int> m_QueueBounds = new map<string, int>();
|
||||
void ERR_NativePatrolProbe(ERR_GameMode mode, string siteId = "everon-outpost-1") { m_Mode = mode; m_SiteId = siteId; }
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: patrol " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: patrol " + detail, LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
protected void Completed(AIWaypoint waypoint)
|
||||
{
|
||||
if (!m_Site) return;
|
||||
int index = m_Site.PatrolWaypoints.Find(waypoint);
|
||||
if (index < 0) return;
|
||||
if (m_LastIndex >= 0 && index != (m_LastIndex + 1) % m_Site.PatrolWaypoints.Count()) m_BadSequence = true;
|
||||
m_LastIndex = index;
|
||||
m_Completions++;
|
||||
PrintFormat("ERR PATROL COMPLETED: site=%1 index=%2 count=%3", m_Site.Definition.Id, index, m_Completions);
|
||||
}
|
||||
protected bool DefinitionChecks()
|
||||
{
|
||||
ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf"));
|
||||
if (!Check(definition && definition.Valid(), "authored definition resolves")) return false;
|
||||
ERR_SiteDefinition site = definition.Find("everon-outpost-1");
|
||||
if (!Check(site && site.Patrol && site.Patrol.Count() == 4, "four ordered outpost points authored")) return false;
|
||||
ref array<ref ERR_SitePatrolPoint> savedRoute = site.Patrol;
|
||||
site.Patrol = new array<ref ERR_SitePatrolPoint>();
|
||||
site.Patrol.Insert(savedRoute[0]);
|
||||
if (!Check(!definition.Valid(), "single-point route rejected")) return false;
|
||||
for (int extra = 1; extra < 7; extra++) site.Patrol.Insert(savedRoute[extra % savedRoute.Count()]);
|
||||
if (!Check(!definition.Valid(), "over-six-point route rejected")) return false;
|
||||
site.Patrol.Clear();
|
||||
site.Patrol.Insert(null);
|
||||
site.Patrol.Insert(savedRoute[1]);
|
||||
if (!Check(!definition.Valid(), "missing point rejected")) return false;
|
||||
site.Patrol = savedRoute;
|
||||
vector saved = site.Patrol[0].Offset;
|
||||
site.Patrol[0].Offset = "61 0 0";
|
||||
if (!Check(!definition.Valid(), "unbounded route rejected")) return false;
|
||||
site.Patrol[0].Offset = "0 1 0";
|
||||
if (!Check(!definition.Valid(), "floating route rejected")) return false;
|
||||
site.Patrol[0].Offset = site.Patrol[1].Offset;
|
||||
if (!Check(!definition.Valid(), "duplicate route points rejected")) return false;
|
||||
site.Patrol[0].Offset = saved;
|
||||
site.Guarded = false;
|
||||
if (!Check(!definition.Valid(), "route without a physical guard rejected")) return false;
|
||||
site.Guarded = true;
|
||||
ERR_SiteDefinition prison = definition.Find("everon-prison-1");
|
||||
prison.Patrol = site.Patrol;
|
||||
if (!Check(!definition.Valid(), "prison patrol rejected; gate guards remain stationary")) return false;
|
||||
prison.Patrol = null;
|
||||
return Check(definition.Valid(), "isolated authoring mutations restored");
|
||||
}
|
||||
protected bool PreparedRoute(string id, bool deferDuplicateFailure = false)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().Find(id);
|
||||
if (!Check(site && site.Group && site.PatrolCycle && site.PatrolWaypoints.Count() == 4, id + " existing group has one cycle and four native moves")) return false;
|
||||
array<AIWaypoint> route = {};
|
||||
site.PatrolCycle.GetWaypoints(route);
|
||||
if (!Check(route.Count() == 4 && site.PatrolCycle.GetRerunCounter() == -1 && m_Mode.Sites().Owns(site.PatrolCycle), id + " finite owner holds repeating cycle")) return false;
|
||||
for (int i = 0; i < route.Count(); i++)
|
||||
{
|
||||
vector expected = site.Definition.Position + site.Definition.GuardOffset + site.Definition.Patrol[i].Offset;
|
||||
if (!Check(route[i] == site.PatrolWaypoints[i] && m_Mode.Sites().Owns(route[i]) && vector.DistanceXZ(route[i].GetOrigin(), expected) < 0.1, id + " authored point " + i.ToString())) return false;
|
||||
}
|
||||
array<AIWaypoint> queued = {};
|
||||
site.Group.GetWaypoints(queued);
|
||||
PrintFormat("ERR PATROL QUEUE: site=%1 count=%2 current=%3", id, queued.Count(), site.Group.GetCurrentWaypoint());
|
||||
for (int diagnosticIndex = 0; diagnosticIndex < Math.Min(queued.Count(), 20); diagnosticIndex++)
|
||||
{
|
||||
AIWaypoint entry = queued[diagnosticIndex];
|
||||
PrintFormat("ERR PATROL QUEUE ENTRY: site=%1 index=%2 point=%3 cycle=%4 current=%5 entity=%6", id, diagnosticIndex, site.PatrolWaypoints.Find(entry), entry == site.PatrolCycle, entry == site.Group.GetCurrentWaypoint(), entry);
|
||||
}
|
||||
// Diagnostic only: retain duplicate rejection at final acceptance, but first
|
||||
// observe whether native completion events execute the apparent repetitions.
|
||||
// GetWaypoints has no documented raw-queue/expanded-cycle distinction.
|
||||
int repeated;
|
||||
for (int j = 0; j < queued.Count(); j++)
|
||||
{
|
||||
if (!Check(queued[j] && (queued[j] == site.PatrolCycle || site.PatrolWaypoints.Contains(queued[j])), id + " queue contains only owned patrol references")) return false;
|
||||
for (int k = 0; k < j; k++) if (queued[j] == queued[k]) repeated++;
|
||||
}
|
||||
int currentIndex = site.PatrolWaypoints.Find(site.Group.GetCurrentWaypoint());
|
||||
string stateKey = id + ":" + currentIndex.ToString();
|
||||
if (m_QueueBounds.Contains(stateKey))
|
||||
{
|
||||
if (!Check(queued.Count() <= m_QueueBounds.Get(stateKey), id + " queue does not grow at the same current route point")) return false;
|
||||
}
|
||||
else m_QueueBounds.Insert(stateKey, queued.Count());
|
||||
PrintFormat("ERR PATROL QUEUE DIAGNOSTIC: site=%1 repeatedPairs=%2 deferred=%3 completions=%4", id, repeated, deferDuplicateFailure, m_Completions);
|
||||
if (!deferDuplicateFailure && !Check(repeated == 0, id + " no duplicate queue references")) return false;
|
||||
return true;
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Finished) return 1;
|
||||
if (!m_Started)
|
||||
{
|
||||
if (!m_Prepared)
|
||||
{
|
||||
if (!DefinitionChecks() || !PreparedRoute("everon-supply-2", true) || !PreparedRoute("everon-outpost-1", true)) return -1;
|
||||
ERR_SiteRuntime prison = m_Mode.Sites().Find("everon-prison-1");
|
||||
if (!Check(prison && prison.Group && !prison.PatrolCycle && prison.PatrolWaypoints.IsEmpty(), "prison guards retain stationary orders")) return -1;
|
||||
m_Site = m_Mode.Sites().Find(m_SiteId);
|
||||
if (!Check(m_Site && m_Site.Group && m_Site.InitialGuardCount == 6, "selected native guard profile requests six physical members")) return -1;
|
||||
m_AcquireDeadline = now + 15000;
|
||||
m_Prepared = true;
|
||||
}
|
||||
if (!m_Site || !m_Site.Group) { Check(false, "original guard group disappeared before observation"); return -1; }
|
||||
array<AIAgent> agents = {};
|
||||
m_Site.Group.GetAgents(agents);
|
||||
array<IEntity> ready = {};
|
||||
foreach (AIAgent agent : agents)
|
||||
{
|
||||
if (!agent) continue;
|
||||
IEntity actor = agent.GetControlledEntity();
|
||||
if (ERR_Actors.CanFight(actor) && !ready.Contains(actor)) ready.Insert(actor);
|
||||
}
|
||||
if (ready.Count() > m_Site.InitialGuardCount) { Check(false, "original group contains excess living physical guards"); return -1; }
|
||||
if (ready.Count() < m_Site.InitialGuardCount)
|
||||
{
|
||||
if (now < m_AcquireDeadline) return 0;
|
||||
PrintFormat("ERR PATROL ACTOR TIMEOUT: site=%1 agents=%2 requested=%3 nativeComplete=%4", m_SiteId, agents.Count(), m_Site.InitialGuardCount, m_Site.Group.IsExpandComplete());
|
||||
Check(false, "existing living physical guard unavailable after bounded readiness wait");
|
||||
return -1;
|
||||
}
|
||||
m_Actor = ready[0];
|
||||
if (!Check(ready.Count() == 6, "six distinct original living physical guards available")) return -1;
|
||||
m_Origin = m_Actor.GetOrigin();
|
||||
m_Site.Group.GetOnWaypointCompleted().Insert(Completed);
|
||||
m_Deadline = now + 180000;
|
||||
m_Started = true;
|
||||
return 0;
|
||||
}
|
||||
if (m_Actor && vector.DistanceXZ(m_Origin, m_Actor.GetOrigin()) >= 8) m_Moved = true;
|
||||
if (m_BadSequence) { Stop(); Check(false, "native route completion order"); return -1; }
|
||||
if (m_Completions != m_LastQueueSample)
|
||||
{
|
||||
m_LastQueueSample = m_Completions;
|
||||
if (!PreparedRoute(m_SiteId, true)) { Stop(); return -1; }
|
||||
}
|
||||
// Five completions prove traversal across a cycle boundary, from any starting point.
|
||||
if (m_Completions >= 5 && m_Moved)
|
||||
{
|
||||
Stop();
|
||||
if (!Check(true, "existing physical guard moved at least 8m and five native moves completed in authored cyclic order")) return -1;
|
||||
if (!PreparedRoute(m_SiteId)) return -1;
|
||||
m_Finished = true;
|
||||
return 1;
|
||||
}
|
||||
if (now >= m_Deadline)
|
||||
{
|
||||
PrintFormat("ERR PATROL TIMEOUT: completions=%1 moved=%2 actor=%3 current=%4", m_Completions, m_Moved, m_Actor, m_Site.Group.GetCurrentWaypoint());
|
||||
Stop(); Check(false, "native route traversal completed within 180s"); return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Run last in a disposable mission: deliberately stops both route owners.
|
||||
static bool StopChecks(ERR_GameMode mode)
|
||||
{
|
||||
ERR_SiteRuntime site = mode.Sites().Find("everon-outpost-1");
|
||||
if (!site || !site.Group || !site.PatrolCycle) return false;
|
||||
AIWaypoint search = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.SearchWaypoint(), ERR_Actors.Ground(site.Definition.Position + "40 0 0")));
|
||||
if (!search) return false;
|
||||
mode.Own(search);
|
||||
site.Group.AddWaypointAt(search, 0);
|
||||
mode.Sites().Stop();
|
||||
mode.Sites().Stop();
|
||||
array<AIWaypoint> queued = {};
|
||||
site.Group.GetWaypoints(queued);
|
||||
bool valid = !site.PatrolCycle && site.PatrolWaypoints.IsEmpty() && queued.Contains(search) && mode.Sites().Prepare() == ERR_PrepareResult.FAILED;
|
||||
site.Group.RemoveWaypoint(search);
|
||||
ERR_Actors.DeleteSpawned(search);
|
||||
if (valid) Print("ERR SMOKE PASS: patrol stop clears owned routes once and preserves foreign Search");
|
||||
else Print("ERR SMOKE FAIL: patrol stop ownership", LogLevel.ERROR);
|
||||
return valid;
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Site && m_Site.Group) m_Site.Group.GetOnWaypointCompleted().Remove(Completed);
|
||||
}
|
||||
void ~ERR_NativePatrolProbe() { Stop(); }
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,210 @@
|
||||
#ifdef WORKBENCH
|
||||
// One real controller plus eleven disposable physical characters. This probes
|
||||
// native inventory and transfer compatibility, not twelve clients or UI pickup.
|
||||
class ERR_NativePrisonerProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Player;
|
||||
protected ref array<IEntity> m_Actors = {};
|
||||
protected ref map<int, vector> m_Reservations = new map<int, vector>();
|
||||
protected ref ERR_SpawnPlacement m_Placement = new ERR_SpawnPlacement();
|
||||
protected ref map<string, int> m_Expected = new map<string, int>();
|
||||
protected ERR_SiteRuntime m_Cache;
|
||||
protected InventoryStorageManagerComponent m_Source;
|
||||
protected SCR_InventoryStorageManagerComponent m_Inventory;
|
||||
protected IEntity m_Document;
|
||||
protected vector m_Original[4];
|
||||
protected int m_Step;
|
||||
protected int m_Checked;
|
||||
protected float m_Wait;
|
||||
void ERR_NativePrisonerProbe(ERR_GameMode mode, IEntity player)
|
||||
{
|
||||
m_Mode = mode; m_Player = player;
|
||||
m_Expected.Set("Prefabs/Characters/HeadGear/Hat_Patrol_US_01/Hat_Patrol_US_01.et", 1);
|
||||
m_Expected.Set("Prefabs/Characters/Uniforms/Jacket_US_BDU_rolledup.et", 1);
|
||||
m_Expected.Set("Prefabs/Characters/Uniforms/Pants_US_BDU.et", 1);
|
||||
m_Expected.Set("Prefabs/Characters/Footwear/CombatBoots_US_01.et", 1);
|
||||
m_Expected.Set("Prefabs/Items/Equipment/Watches/Watch_SandY184A.et", 1);
|
||||
m_Expected.Set("Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et", 2);
|
||||
m_Expected.Set("Prefabs/Items/Medicine/Tourniquet_01/Tourniquet_US_01.et", 1);
|
||||
m_Expected.Set("Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et", 1);
|
||||
}
|
||||
protected bool Check(bool condition, string detail)
|
||||
{
|
||||
if (condition) { Print("ERR SMOKE PASS: prisoner " + detail); return true; }
|
||||
Print("ERR SMOKE FAIL: prisoner " + detail, LogLevel.ERROR);
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
protected void Positions(string stage)
|
||||
{
|
||||
foreach (int index, IEntity actor : m_Actors)
|
||||
{
|
||||
if (!actor) continue;
|
||||
vector lower, upper;
|
||||
actor.GetWorldBounds(lower, upper);
|
||||
PrintFormat("ERR PRISONER POSITION: stage=%1 index=%2 requested=%3 actual=%4 boundsMin=%5 boundsMax=%6", stage, index, m_Reservations.Get(index), actor.GetOrigin(), lower, upper);
|
||||
}
|
||||
}
|
||||
protected bool Kit(IEntity actor, int index)
|
||||
{
|
||||
if (!Check(actor && actor.GetPrefabData() && actor.GetPrefabData().GetPrefabName() == "{3FF693715C9F8928}Prefabs/ERR/Prisoner.et", "character " + index.ToString() + " uses successor resource")) return false;
|
||||
if (!Check(actor.FindComponent(SCR_CharacterDamageManagerComponent) && actor.FindComponent(CharacterControllerComponent) && actor.FindComponent(SCR_SalineStorageComponent) && actor.FindComponent(SCR_TourniquetStorageComponent) && actor.FindComponent(CompartmentAccessComponent), "character " + index.ToString() + " retains vanilla health, treatment and vehicle components")) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!Check(inventory != null, "character inventory exists")) return false;
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
map<string, int> counts = new map<string, int>();
|
||||
int identityItems;
|
||||
array<IEntity> seen = {};
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (!item || !item.GetPrefabData()) return Check(false, "inventory item has no resource identity");
|
||||
ResourceName resource = item.GetPrefabData().GetPrefabName();
|
||||
PrintFormat("ERR PRISONER ITEM: actor=%1 item=%2 resource=%3 duplicateReference=%4", index, item, resource, seen.Contains(item));
|
||||
if (seen.Contains(item)) continue;
|
||||
seen.Insert(item);
|
||||
// Vanilla creates identification on possession, death or unconsciousness.
|
||||
// Preserve this native identity record; it is not mission navigation equipment.
|
||||
if (resource.EndsWith("Prefabs/Items/PersonalBelongings/PersonalBelongings_US.et"))
|
||||
{
|
||||
if (!Check(ERR_Actors.Player(actor) && item.FindComponent(SCR_IdentityInventoryItemComponent), "possessed prisoner retains native identification")) return false;
|
||||
identityItems++;
|
||||
continue;
|
||||
}
|
||||
// A non-equipment belt is authored by the rolled-up vanilla jacket itself.
|
||||
if (resource.EndsWith("Prefabs/Characters/Vests/Vest_ALICE/Vest_ALICE_belt_dummy.et")) continue;
|
||||
bool allowed = false;
|
||||
foreach (string path, int expected : m_Expected)
|
||||
{
|
||||
if (!resource.EndsWith(path)) continue;
|
||||
counts.Set(path, counts.Get(path) + 1);
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
if (!allowed) return Check(false, "unexpected starter inventory resource: " + resource);
|
||||
}
|
||||
int expectedIdentity;
|
||||
if (ERR_Actors.Player(actor)) expectedIdentity = 1;
|
||||
if (!Check(identityItems == expectedIdentity, "native identification is created exactly once for the possessed prisoner")) return false;
|
||||
foreach (string path, int expected : m_Expected)
|
||||
if (counts.Get(path) != expected) return Check(false, string.Format("character %1 expected %2 of %3, found %4", index, expected, path, counts.Get(path)));
|
||||
PrintFormat("ERR PRISONER INVENTORY: character=%1 storedItems=%2", index, items.Count());
|
||||
return Check(true, "character " + index.ToString() + " has exact clothing/watch/medical kit and no inherited navigation, radio, binoculars, tools, flares or weapons");
|
||||
}
|
||||
protected bool Contains(InventoryStorageManagerComponent inventory, IEntity item)
|
||||
{
|
||||
if (!inventory || !item) return false;
|
||||
array<IEntity> items = {};
|
||||
inventory.GetItems(items);
|
||||
return items.Contains(item);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
// Return borrowed stock when its source still exists; never spawn replacements.
|
||||
if (m_Document && m_Cache && m_Cache.Container && m_Inventory && Contains(m_Inventory, m_Document))
|
||||
{
|
||||
BaseInventoryStorageComponent destination = BaseInventoryStorageComponent.Cast(m_Cache.Container.FindComponent(BaseInventoryStorageComponent));
|
||||
if (destination) m_Inventory.TryMoveItemToStorage(m_Document, destination);
|
||||
}
|
||||
for (int i = 1; i < m_Actors.Count(); i++) ERR_Actors.DeleteSpawned(m_Actors[i]);
|
||||
m_Reservations.Clear();
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
if (!Check(m_Mode && m_Mode.Phase() == ERR_Phase.PRISON && ERR_Actors.Player(m_Player) && ERR_Actors.CanFight(m_Player), "fixture begins with a real conscious prisoner")) return -1;
|
||||
m_Player.GetWorldTransform(m_Original);
|
||||
m_Actors.Insert(m_Player);
|
||||
m_Reservations.Set(0, m_Player.GetOrigin());
|
||||
Positions("initial");
|
||||
m_Step = 1;
|
||||
m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
if (m_Actors.Count() < 12)
|
||||
{
|
||||
vector position;
|
||||
bool available = m_Placement.Prison(m_Mode.PrisonPosition(), m_Reservations, position);
|
||||
if (!available) Positions("no-clear-slot");
|
||||
if (!Check(available, "bounded clear prison slot exists for next test character")) return -1;
|
||||
IEntity actor = ERR_Actors.Spawn(m_Mode.Factions().PrisonerPrefab, position);
|
||||
if (!Check(actor != null, "physical test prisoner created")) return -1;
|
||||
m_Mode.Own(actor);
|
||||
m_Reservations.Set(m_Actors.Count(), position);
|
||||
m_Actors.Insert(actor);
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent));
|
||||
if (!Check(damage != null, "test prisoner damage component exists")) return -1;
|
||||
damage.EnableDamageHandling(false);
|
||||
m_Wait = now + 500;
|
||||
return 0;
|
||||
}
|
||||
Positions("all-spawned");
|
||||
m_Step = 2; m_Wait = now + 1500;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (m_Checked == 0) Positions("settled");
|
||||
if (!Kit(m_Actors[m_Checked], m_Checked)) return -1;
|
||||
m_Checked++;
|
||||
if (m_Checked < 12) return 0;
|
||||
m_Cache = m_Mode.Sites().Find("everon-supply-1");
|
||||
if (!Check(m_Cache && m_Cache.Container, "authored clue source remains available")) return -1;
|
||||
m_Source = InventoryStorageManagerComponent.Cast(m_Cache.Container.FindComponent(InventoryStorageManagerComponent));
|
||||
m_Inventory = SCR_InventoryStorageManagerComponent.Cast(m_Player.FindComponent(SCR_InventoryStorageManagerComponent));
|
||||
if (!Check(m_Source && m_Inventory, "source and player inventory managers are usable")) return -1;
|
||||
array<IEntity> stock = {};
|
||||
m_Source.GetItems(stock);
|
||||
foreach (IEntity item : stock)
|
||||
{
|
||||
ERR_DocumentComponent document = ERR_DocumentComponent.Cast(item.FindComponent(ERR_DocumentComponent));
|
||||
if (document && document.TargetId() == "everon-radio-1") { m_Document = item; break; }
|
||||
}
|
||||
if (!Check(m_Document && m_Inventory, "real finite radio document and player storage found")) return -1;
|
||||
vector transform[4]; m_Player.GetWorldTransform(transform);
|
||||
transform[3] = ERR_Actors.Ground(m_Cache.Container.GetOrigin() + "0 0 2");
|
||||
ChimeraCharacter.Cast(m_Player).Teleport(transform);
|
||||
m_Step = 3; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
BaseInventoryStorageComponent destination = m_Inventory.FindStorageForItem(m_Document);
|
||||
if (!Check(destination && m_Source.TryMoveItemToStorage(m_Document, destination), "minimal starter clothing accepts a real authored clue transfer")) return -1;
|
||||
m_Step = 4; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
if (!Check(Contains(m_Inventory, m_Document) && !Contains(m_Source, m_Document) && m_Mode.Phase() == ERR_Phase.PRISON, "document physically moved without duplication while prison phase remains active")) return -1;
|
||||
BaseInventoryStorageComponent destination = BaseInventoryStorageComponent.Cast(m_Cache.Container.FindComponent(BaseInventoryStorageComponent));
|
||||
if (!Check(destination && m_Inventory.TryMoveItemToStorage(m_Document, destination), "borrowed document returns to finite source")) return -1;
|
||||
m_Step = 5; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 5)
|
||||
{
|
||||
if (!Check(Contains(m_Source, m_Document) && !Contains(m_Inventory, m_Document), "borrowed clue restored exactly once")) return -1;
|
||||
Stop();
|
||||
ChimeraCharacter.Cast(m_Player).Teleport(m_Original);
|
||||
m_Step = 6; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 6)
|
||||
{
|
||||
for (int i = 1; i < m_Actors.Count(); i++)
|
||||
if (!Check(!m_Actors[i], "disposable prisoner removed after native cleanup")) return -1;
|
||||
ERR_PlayerLife life = m_Mode.Players().Get(GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(m_Player));
|
||||
if (!Check(ERR_Actors.Player(m_Player) && ERR_Actors.Alive(m_Player) && life && life.UsedLife, "real prisoner and spent life preserved")) return -1;
|
||||
m_Step = 7;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
#ifdef WORKBENCH
|
||||
class ERR_NativeRecoveryProbe
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected IEntity m_Player;
|
||||
protected CharacterControllerComponent m_Controller;
|
||||
protected float m_Wait;
|
||||
protected float m_RecoveryDeadline;
|
||||
protected bool m_Stopped;
|
||||
protected bool m_ChangedConsciousness;
|
||||
protected bool m_InitiallyUnconscious;
|
||||
protected int m_Step;
|
||||
protected int m_Changes;
|
||||
void ERR_NativeRecoveryProbe(ERR_GameMode mode, IEntity player)
|
||||
{
|
||||
m_Mode = mode; m_Player = player;
|
||||
m_Controller = CharacterControllerComponent.Cast(player.FindComponent(CharacterControllerComponent));
|
||||
if (m_Controller) m_InitiallyUnconscious = m_Controller.IsUnconscious();
|
||||
mode.Recovery().OnChanged().Insert(Changed);
|
||||
mode.OnStop().Insert(Stop);
|
||||
}
|
||||
protected void Changed(string message) { m_Changes++; }
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
if (m_Mode) m_Mode.OnStop().Remove(Stop);
|
||||
if (m_Mode && m_Mode.Recovery()) m_Mode.Recovery().OnChanged().Remove(Changed);
|
||||
if (m_ChangedConsciousness && m_Controller && ERR_Actors.Alive(m_Player)) m_Controller.SetUnconscious(m_InitiallyUnconscious);
|
||||
}
|
||||
protected bool Check(bool ok, string detail)
|
||||
{
|
||||
if (ok) { Print("ERR SMOKE PASS: recovery " + detail); return true; }
|
||||
Stop();
|
||||
Print("ERR SMOKE FAIL: recovery " + detail, LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_Stopped) return -1;
|
||||
if (now < m_Wait) return 0;
|
||||
if (m_Step == 0)
|
||||
{
|
||||
m_Mode.Recovery().Tick();
|
||||
if (!Check(m_Controller && m_Mode.Recovery().Conscious() == 1 && m_Mode.RecoveryStatus().IsEmpty(), "real conscious prisoner is available without recovery warning")) return -1;
|
||||
array<string> replies = {};
|
||||
m_Mode.Admin().Execute(m_Mode, false, "mission abandon", replies);
|
||||
if (!Check(replies.Count() == 1 && replies[0].Contains("Administrator") && m_Mode.Phase() == ERR_Phase.PRISON && m_Mode.EndReason().IsEmpty(), "unauthorized abandonment leaves round and result intact")) return -1;
|
||||
m_Mode.Admin().Execute(m_Mode, true, "mission abandon now", replies);
|
||||
if (!Check(m_Mode.Phase() == ERR_Phase.PRISON && m_Mode.EndReason().IsEmpty(), "malformed abandonment does not end a round")) return -1;
|
||||
m_ChangedConsciousness = true;
|
||||
m_Controller.SetUnconscious(true);
|
||||
m_Step = 1; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 1)
|
||||
{
|
||||
m_Mode.Recovery().Tick();
|
||||
if (!Check(ERR_Actors.Alive(m_Player) && !ERR_Actors.CanFight(m_Player) && m_Mode.Recovery().Incapacitated() == 1 && m_Mode.Recovery().Conscious() == 0, "native unconscious prisoner is counted as incapacitated, not dead")) return -1;
|
||||
if (!Check(m_Mode.RecoveryStatus().Contains("No conscious prisoner") && m_Mode.Status().Contains("mission abandon") && ERR_ObjectiveText.Description(m_Mode).Contains(m_Mode.RecoveryStatus()), "server status and native objective copy explain the recovery state")) return -1;
|
||||
if (!Check(m_Changes == 1, "recovery state publishes exactly one change")) return -1;
|
||||
m_Mode.Recovery().Tick();
|
||||
if (!Check(m_Changes == 1, "unchanged sampling emits no duplicate recovery event")) return -1;
|
||||
m_Step = 2; m_Wait = now + 35000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 2)
|
||||
{
|
||||
if (!Check(m_Mode.Phase() == ERR_Phase.PRISON && ERR_Actors.Alive(m_Player) && !ERR_Actors.CanFight(m_Player) && m_Mode.Players().HasSurvivor(), "all-incapacitated player survives beyond ordinary defeat grace")) return -1;
|
||||
m_Controller.SetUnconscious(false);
|
||||
m_RecoveryDeadline = now + 12000;
|
||||
m_Step = 3; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 3)
|
||||
{
|
||||
if (!ERR_Actors.CanFight(m_Player) && now < m_RecoveryDeadline) return 0;
|
||||
m_Mode.Recovery().Tick();
|
||||
if (!Check(ERR_Actors.CanFight(m_Player) && m_Mode.RecoveryStatus().IsEmpty() && m_Mode.Recovery().Conscious() == 1 && m_Changes == 2, "native recovery clears the warning once")) return -1;
|
||||
int id = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(m_Player);
|
||||
ERR_PlayerLife life = m_Mode.Players().Get(id);
|
||||
if (!Check(life && life.UsedLife && life.Actor == m_Player, "recovery preserves original actor and spent life")) return -1;
|
||||
m_Controller.SetUnconscious(true);
|
||||
m_Step = 4; m_Wait = now + 1000;
|
||||
return 0;
|
||||
}
|
||||
if (m_Step == 4)
|
||||
{
|
||||
m_Mode.Recovery().Tick();
|
||||
if (!Check(!m_Mode.RecoveryStatus().IsEmpty() && m_Changes == 3, "second incapacitation restores warning before abandonment")) return -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -3,9 +3,40 @@
|
||||
modded class SCR_BaseItemSupportStationComponent
|
||||
{
|
||||
protected static int s_ERRStationTeardownLines;
|
||||
protected static int s_ERRStationInitLines;
|
||||
protected bool m_ERRStationInitSeen;
|
||||
protected bool m_ERRStationInitModePresent;
|
||||
protected bool m_ERRStationInitMainWorld;
|
||||
protected bool m_ERRStationInitSiteOwned;
|
||||
protected bool m_ERRStationInitInInventory;
|
||||
protected ResourceName m_ERRStationInitParentPrefab;
|
||||
protected bool m_ERRStationInDelete;
|
||||
protected IEntity m_ERRStationDeleteOwner;
|
||||
|
||||
protected override void DelayedInit(IEntity owner)
|
||||
{
|
||||
// Preserve initialization and every native validation before observation.
|
||||
super.DelayedInit(owner);
|
||||
string enabled;
|
||||
if (!System.GetCLIParam("errStationTeardownDiag", enabled) || enabled != "1" || !owner) return;
|
||||
m_ERRStationInitSeen = true;
|
||||
ERR_GameMode mode = ERR_GameMode.Get();
|
||||
m_ERRStationInitModePresent = mode != null;
|
||||
if (GetGame()) m_ERRStationInitMainWorld = owner.GetWorld() == GetGame().GetWorld();
|
||||
ERR_SiteService sites;
|
||||
if (mode) sites = mode.Sites();
|
||||
m_ERRStationInitSiteOwned = sites && sites.Owns(owner);
|
||||
InventoryItemComponent item = InventoryItemComponent.Cast(owner.FindComponent(InventoryItemComponent));
|
||||
m_ERRStationInitInInventory = item && item.GetParentSlot();
|
||||
IEntity parent = owner.GetParent();
|
||||
if (parent && parent.GetPrefabData()) m_ERRStationInitParentPrefab = parent.GetPrefabData().GetPrefabName();
|
||||
if (s_ERRStationInitLines >= 64) return;
|
||||
s_ERRStationInitLines++;
|
||||
ResourceName prefab;
|
||||
if (owner.GetPrefabData()) prefab = owner.GetPrefabData().GetPrefabName();
|
||||
PrintFormat("ERR STATION INIT OWNERSHIP: n=%1 prefab=%2 modePresent=%3 mainWorld=%4 siteOwned=%5 inInventory=%6 parentPrefab=%7", s_ERRStationInitLines, prefab, m_ERRStationInitModePresent, m_ERRStationInitMainWorld, m_ERRStationInitSiteOwned, m_ERRStationInitInInventory, m_ERRStationInitParentPrefab);
|
||||
}
|
||||
|
||||
override void OnDelete(IEntity owner)
|
||||
{
|
||||
string enabled;
|
||||
@@ -51,6 +82,24 @@ modded class SCR_BaseItemSupportStationComponent
|
||||
}
|
||||
string detail = string.Format("ERR STATION TEARDOWN DIAG: n=%1 owner=%2 prefab=%3 cachedCatalog=%4 globalCatalog=%5", s_ERRStationTeardownLines, ownerName, prefab, m_EntityCatalogManager != null, catalog != null);
|
||||
detail += string.Format(" modePresent=%1 gameState=%2 errPhase=%3 endData=%4 call=OnDelete/InitValidSetup", baseMode != null, gameState, phase, hasEndData);
|
||||
detail += string.Format(" initSeen=%1 initMode=%2 initMainWorld=%3 initSiteOwned=%4 initInInventory=%5 initParentPrefab=%6", m_ERRStationInitSeen, m_ERRStationInitModePresent, m_ERRStationInitMainWorld, m_ERRStationInitSiteOwned, m_ERRStationInitInInventory, m_ERRStationInitParentPrefab);
|
||||
bool deleteMainWorld;
|
||||
bool deleteSiteOwned;
|
||||
bool deleteInInventory;
|
||||
ResourceName deleteParentPrefab;
|
||||
if (owner)
|
||||
{
|
||||
if (GetGame()) deleteMainWorld = owner.GetWorld() == GetGame().GetWorld();
|
||||
ERR_GameMode deleteMode = ERR_GameMode.Cast(baseMode);
|
||||
ERR_SiteService deleteSites;
|
||||
if (deleteMode) deleteSites = deleteMode.Sites();
|
||||
deleteSiteOwned = deleteSites && deleteSites.Owns(owner);
|
||||
InventoryItemComponent deleteItem = InventoryItemComponent.Cast(owner.FindComponent(InventoryItemComponent));
|
||||
deleteInInventory = deleteItem && deleteItem.GetParentSlot();
|
||||
IEntity deleteParent = owner.GetParent();
|
||||
if (deleteParent && deleteParent.GetPrefabData()) deleteParentPrefab = deleteParent.GetPrefabData().GetPrefabName();
|
||||
}
|
||||
detail += string.Format(" deleteMainWorld=%1 deleteSiteOwned=%2 deleteInInventory=%3 deleteParentPrefab=%4", deleteMainWorld, deleteSiteOwned, deleteInInventory, deleteParentPrefab);
|
||||
Print(detail);
|
||||
if (s_ERRStationTeardownLines == 64) Print("ERR STATION TEARDOWN DIAG: 64-line diagnostic limit reached; vanilla validation and cleanup continue unchanged.");
|
||||
}
|
||||
|
||||
@@ -11,9 +11,25 @@ class ERR_ObjectiveText
|
||||
}
|
||||
static string Extraction(float radius)
|
||||
{
|
||||
return string.Format("Reach the helicopter marked on your map. Board and fly beyond %1 kilometres from the prison. Living prisoners aboard escape, including unconscious passengers. Dead or absent prisoners do not.", radius / 1000.0);
|
||||
return string.Format("The map marks the initial helicopter pickup site. Board the helicopter and fly beyond %1 kilometres from the prison. Living prisoners aboard escape, including unconscious passengers. Dead or absent prisoners do not.", radius / 1000.0);
|
||||
}
|
||||
static string RadioFeedbackMessage(ERR_RadioFeedback feedback)
|
||||
{
|
||||
if (feedback == ERR_RadioFeedback.WAITING)
|
||||
return "Waiting for a conscious defender near the radio. Keep someone within 60 metres to start the transmission.";
|
||||
if (feedback == ERR_RadioFeedback.TRANSMITTING)
|
||||
return "Transmission in progress. Keep a conscious survivor within 60 metres of the radio. Leaving the area resets progress.";
|
||||
if (feedback == ERR_RadioFeedback.INTERRUPTED)
|
||||
return "Transmission interrupted. Progress has reset. Return a conscious survivor to within 60 metres of the radio to resume.";
|
||||
return "Keep a conscious survivor within 60 metres of the radio until the transmission finishes. Leaving the area resets the defence timer.";
|
||||
}
|
||||
static string Description(ERR_GameMode mode, bool progress = true)
|
||||
{
|
||||
string description = PhaseDescription(mode, progress);
|
||||
if (mode && mode.Active() && !mode.RecoveryStatus().IsEmpty()) description += "\n" + mode.RecoveryStatus();
|
||||
return description;
|
||||
}
|
||||
protected static string PhaseDescription(ERR_GameMode mode, bool progress)
|
||||
{
|
||||
if (!mode) return "";
|
||||
ERR_Phase phase = mode.Phase();
|
||||
@@ -30,12 +46,12 @@ class ERR_ObjectiveText
|
||||
mode.Locations(locations);
|
||||
foreach (ERR_LocationComponent location : locations)
|
||||
if (location.Kind() == ERR_LocationKind.RADIO && location.Knowledge() == 2)
|
||||
return "The recovered documents identify the radio station on your map. Reach the station and tune its radio to start the transmission.";
|
||||
return "Choose either marked supply cache. Each has equipment and enough radio documents to identify the station. If one cache is lost, use the other. Nearby medical and guard sites can be discovered by approaching with a clear view.";
|
||||
return "The radio station is identified on your map. Reach the station and tune its radio to start the transmission.";
|
||||
return "Choose either marked supply cache. Each has equipment and enough radio documents to identify the station. If one cache is lost, use the other. If every document is lost, a close approach with a clear view can identify the station itself. Nearby medical and guard sites can be discovered by approaching with a clear view.";
|
||||
}
|
||||
if (phase == ERR_Phase.RADIO_DEFENCE)
|
||||
{
|
||||
if (!progress) return "Keep a conscious survivor within 60 metres of the radio until the transmission finishes. Leaving the area resets the defence timer.";
|
||||
if (!progress) return RadioFeedbackMessage(mode.RadioFeedback());
|
||||
int seconds = mode.DefenceSecondsRemaining();
|
||||
if (!mode.DefenceOccupied())
|
||||
return string.Format("Transmission interrupted. Keep a conscious survivor within 60 metres of the radio for %1 seconds. Leaving resets progress.", seconds);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// Explicit local diagnostic launcher. Normal games and Workbench never request
|
||||
// transitions from this file. No player, identity or audit state is fabricated.
|
||||
#ifndef WORKBENCH
|
||||
// Native Game is not Managed; this script-owned helper owns the callback.
|
||||
class ERR_OrdinaryScenarioLaunchRequest : Managed
|
||||
{
|
||||
protected string m_Project;
|
||||
protected ResourceName m_Header;
|
||||
protected string m_Addon;
|
||||
protected bool m_Queued;
|
||||
protected bool m_Finished;
|
||||
|
||||
void Queue(string project, ResourceName header, string addon)
|
||||
{
|
||||
if (m_Queued || m_Finished) return;
|
||||
m_Queued = true;
|
||||
m_Project = project;
|
||||
m_Header = header;
|
||||
m_Addon = addon;
|
||||
GetGame().GetCallqueue().CallLater(Attempt, 0, false);
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
m_Finished = true;
|
||||
if (GetGame() && GetGame().GetCallqueue()) GetGame().GetCallqueue().Remove(Attempt);
|
||||
}
|
||||
|
||||
protected void Attempt()
|
||||
{
|
||||
if (m_Finished) return;
|
||||
m_Finished = true;
|
||||
if (!GameStateTransitions.IsInsideMainMenu() || ERR_GameMode.Get() || GameStateTransitions.IsTransitionRequestedOrInProgress())
|
||||
{
|
||||
Print("ERR ORDINARY: header launch refused outside idle main menu", LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
string addons;
|
||||
if (!System.GetCLIParam("addons", addons) || addons != m_Addon)
|
||||
{
|
||||
Print("ERR ORDINARY: header launch addon selection mismatch", LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
ResourceName expected = m_Header;
|
||||
MissionHeader header = MissionHeader.ReadMissionHeader(expected);
|
||||
if (!header || header.GetWorldResourceName() != "{B6C516F86302C679}Worlds/ERR_Everon.ent" || header.GetWorldSystemsConfig() != "{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf")
|
||||
{
|
||||
Print("ERR ORDINARY: diagnostic mission header is invalid", LogLevel.ERROR);
|
||||
return;
|
||||
}
|
||||
PrintFormat("ERR ORDINARY: requesting header project=%1", m_Project);
|
||||
if (!GameStateTransitions.RequestScenarioChangeTransition(expected, string.Empty, addons))
|
||||
Print("ERR ORDINARY: native header transition refused", LogLevel.ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
modded class ArmaReforgerScripted
|
||||
{
|
||||
protected ref ERR_OrdinaryScenarioLaunchRequest m_ERRDiagnosticLaunchRequest;
|
||||
protected bool m_ERRDiagnosticLaunchAttempted;
|
||||
protected string m_ERRDiagnosticProject;
|
||||
|
||||
protected ResourceName ERR_DiagnosticHeader(string project)
|
||||
{
|
||||
if (project == "core") return "{AD62322D5213C440}Missions/ERR_Everon_Base.conf";
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
protected string ERR_DiagnosticAddon(string project)
|
||||
{
|
||||
if (project == "core") return "2528466DE220D91C";
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
override bool OnGameStart()
|
||||
{
|
||||
bool started = super.OnGameStart();
|
||||
if (!started || !System.GetCLIParam("errOrdinaryScenario", m_ERRDiagnosticProject)) return started;
|
||||
ResourceName expected = ERR_DiagnosticHeader(m_ERRDiagnosticProject);
|
||||
if (expected.IsEmpty())
|
||||
{
|
||||
Print("ERR ORDINARY: invalid diagnostic project", LogLevel.ERROR);
|
||||
return started;
|
||||
}
|
||||
// A loaded successor is inspected only; never replace an active mission.
|
||||
if (ERR_GameMode.Get())
|
||||
{
|
||||
MissionHeader active = GetMissionHeader();
|
||||
ResourceName systems = "{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf";
|
||||
if (!active || active.GetHeaderResourceName() != expected || active.GetWorldSystemsConfig() != systems || GetSystemsConfig() != systems)
|
||||
Print("ERR ORDINARY: active scenario header/systems mismatch", LogLevel.ERROR);
|
||||
else
|
||||
PrintFormat("ERR ORDINARY: header verified project=%1 systems=MissionSystems", m_ERRDiagnosticProject);
|
||||
return started;
|
||||
}
|
||||
if (m_ERRDiagnosticLaunchAttempted) return started;
|
||||
m_ERRDiagnosticLaunchAttempted = true;
|
||||
// OnGameStart runs while the native state is finishing initialization. The
|
||||
// one queued attempt requires that it actually reached the main menu.
|
||||
m_ERRDiagnosticLaunchRequest = new ERR_OrdinaryScenarioLaunchRequest();
|
||||
m_ERRDiagnosticLaunchRequest.Queue(m_ERRDiagnosticProject, expected, ERR_DiagnosticAddon(m_ERRDiagnosticProject));
|
||||
return started;
|
||||
}
|
||||
|
||||
|
||||
override protected void OnBeforeWorldCleanup()
|
||||
{
|
||||
if (m_ERRDiagnosticLaunchRequest) m_ERRDiagnosticLaunchRequest.Cancel();
|
||||
m_ERRDiagnosticLaunchRequest = null;
|
||||
super.OnBeforeWorldCleanup();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -49,6 +49,18 @@ class ERR_PlayerRoster
|
||||
if (!m_Connections.Find(playerId, identity)) return null;
|
||||
return m_Lives.Get(identity);
|
||||
}
|
||||
// The roster identity was bound by the audited connection lifecycle. Consumers
|
||||
// validate its current body rather than requesting a second backend identity.
|
||||
ERR_PlayerLife CurrentActor(IEntity actor)
|
||||
{
|
||||
if (!Replication.IsServer() || !actor || !GetGame() || !GetGame().GetPlayerManager()) return null;
|
||||
PlayerManager manager = GetGame().GetPlayerManager();
|
||||
int connection = manager.GetPlayerIdFromControlledEntity(actor);
|
||||
if (connection <= 0 || manager.GetPlayerControlledEntity(connection) != actor) return null;
|
||||
ERR_PlayerLife life = Get(connection);
|
||||
if (!life || life.AccountId.IsNull() || !life.Connected || !life.UsedLife || life.ConnectionId != connection || life.Actor != actor) return null;
|
||||
return life;
|
||||
}
|
||||
bool CanEnter(int playerId, int phase)
|
||||
{
|
||||
ERR_PlayerLife life = Get(playerId);
|
||||
|
||||
@@ -67,10 +67,7 @@ class ERR_RadioDefenceService
|
||||
}
|
||||
protected bool IsPlayer(IEntity actor)
|
||||
{
|
||||
if (!m_Mode || !ERR_Actors.Player(actor)) return false;
|
||||
int id = GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(actor);
|
||||
ERR_PlayerLife life = m_Mode.Players().Get(id);
|
||||
return life && life.Connected && life.UsedLife && life.Actor == actor;
|
||||
return m_Mode && m_Mode.Players() && m_Mode.Players().CurrentActor(actor) != null;
|
||||
}
|
||||
protected bool Friendly(IEntity actor)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Presentation only. The defence service remains the sole owner of progress.
|
||||
enum ERR_RadioFeedback
|
||||
{
|
||||
INACTIVE,
|
||||
WAITING,
|
||||
TRANSMITTING,
|
||||
INTERRUPTED
|
||||
}
|
||||
|
||||
class ERR_RadioFeedbackRules
|
||||
{
|
||||
static ERR_RadioFeedback Next(ERR_RadioFeedback previous, bool defending, bool occupied)
|
||||
{
|
||||
if (!defending) return ERR_RadioFeedback.INACTIVE;
|
||||
if (occupied) return ERR_RadioFeedback.TRANSMITTING;
|
||||
if (previous == ERR_RadioFeedback.TRANSMITTING || previous == ERR_RadioFeedback.INTERRUPTED) return ERR_RadioFeedback.INTERRUPTED;
|
||||
return ERR_RadioFeedback.WAITING;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// Observation only: unconsciousness never consumes a life or ends a round here.
|
||||
class ERR_RecoveryRules
|
||||
{
|
||||
// 0 absent/dead, 1 reserved or awaiting handoff, 2 conscious, 3 incapacitated.
|
||||
static int SurvivorKind(bool alive, bool connected, bool sameActor, bool canFight)
|
||||
{
|
||||
if (!alive) return 0;
|
||||
if (!connected || !sameActor) return 1;
|
||||
if (canFight) return 2;
|
||||
return 3;
|
||||
}
|
||||
static bool NeedsRescuer(int conscious, int incapacitated)
|
||||
{
|
||||
return conscious == 0 && incapacitated > 0;
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_RecoveryService
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected bool m_Stopped;
|
||||
protected int m_Conscious;
|
||||
protected int m_Incapacitated;
|
||||
protected int m_Reserved;
|
||||
protected string m_Message;
|
||||
protected ref ScriptInvoker m_OnChanged = new ScriptInvoker();
|
||||
void ERR_RecoveryService(ERR_GameMode mode) { m_Mode = mode; }
|
||||
ScriptInvoker OnChanged() { return m_OnChanged; }
|
||||
int Conscious() { return m_Conscious; }
|
||||
int Incapacitated() { return m_Incapacitated; }
|
||||
int Reserved() { return m_Reserved; }
|
||||
string Message() { return m_Message; }
|
||||
|
||||
void Tick()
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || !m_Mode || !m_Mode.Active()) return;
|
||||
int conscious, incapacitated, reserved;
|
||||
array<ref ERR_PlayerLife> lives = {};
|
||||
m_Mode.Players().Participants(lives);
|
||||
foreach (ERR_PlayerLife life : lives)
|
||||
{
|
||||
IEntity controlled = null;
|
||||
if (life.Connected) controlled = GetGame().GetPlayerManager().GetPlayerControlledEntity(life.ConnectionId);
|
||||
int kind = ERR_RecoveryRules.SurvivorKind(ERR_Actors.Alive(life.Actor), life.Connected, controlled == life.Actor, ERR_Actors.CanFight(life.Actor));
|
||||
if (kind == 1) reserved++;
|
||||
else if (kind == 2) conscious++;
|
||||
else if (kind == 3) incapacitated++;
|
||||
}
|
||||
m_Conscious = conscious;
|
||||
m_Incapacitated = incapacitated;
|
||||
m_Reserved = reserved;
|
||||
string message;
|
||||
if (ERR_RecoveryRules.NeedsRescuer(conscious, incapacitated))
|
||||
{
|
||||
message = "No conscious prisoner is currently available to help. Natural recovery and treatment can still continue.";
|
||||
if (reserved > 0) message += " A surviving prisoner's reconnection may provide help.";
|
||||
message += " An administrator can abandon this round with /esc mission abandon.";
|
||||
}
|
||||
Publish(message);
|
||||
}
|
||||
protected void Publish(string message)
|
||||
{
|
||||
if (m_Message == message) return;
|
||||
m_Message = message;
|
||||
m_OnChanged.Invoke(message);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
m_Conscious = 0; m_Incapacitated = 0; m_Reserved = 0;
|
||||
Publish("");
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ class ERR_Resources
|
||||
{
|
||||
static ResourceName ObjectiveDocument() { return "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et"; }
|
||||
static ResourceName SearchWaypoint() { return "{B3E7B8DC2BAB8ACC}Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et"; }
|
||||
static ResourceName MoveWaypoint() { return "{750A8D1695BD6998}Prefabs/AI/Waypoints/AIWaypoint_Move.et"; }
|
||||
static ResourceName CycleWaypoint() { return "{35BD6541CBB8AC08}Prefabs/AI/Waypoints/AIWaypoint_Cycle.et"; }
|
||||
static ResourceName DefendWaypoint() { return "{93291E72AC23930F}Prefabs/AI/Waypoints/AIWaypoint_Defend.et"; }
|
||||
static ResourceName IntelFolder() { return "{6D56FED1E55A8F84}Prefabs/Items/Misc/IntelligenceFolder_E_01/IntelligenceFolder_E_01.et"; }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ class ERR_Settings
|
||||
|
||||
static array<string> Keys()
|
||||
{
|
||||
return {"reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier"};
|
||||
return {"reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile"};
|
||||
}
|
||||
|
||||
static bool Valid(string key, int value)
|
||||
@@ -20,6 +20,25 @@ class ERR_Settings
|
||||
if (key == "radioDefenceSeconds") return value >= 30 && value <= 1800;
|
||||
if (key == "startTimeMinutes") return value >= 0 && value <= 1439;
|
||||
if (key == "timeMultiplier") return value >= 1 && value <= 24;
|
||||
if (key == "weatherProfile") return value >= 0 && value <= 3;
|
||||
if (key == "startDateCode")
|
||||
{
|
||||
if (value == 0) return true;
|
||||
// Compact (year-1900)MMDD stays exactly representable by JSON floats.
|
||||
if (value < 101 || value > 1501231) return false;
|
||||
int year = 1900 + value / 10000;
|
||||
int month = (value % 10000) / 100;
|
||||
int day = value % 100;
|
||||
if (month < 1 || month > 12 || day < 1) return false;
|
||||
int days = 31;
|
||||
if (month == 4 || month == 6 || month == 9 || month == 11) days = 30;
|
||||
if (month == 2)
|
||||
{
|
||||
days = 28;
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) days = 29;
|
||||
}
|
||||
return day <= days;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,6 +46,7 @@ class ERR_Settings
|
||||
{
|
||||
if (key == "startTimeMinutes") return 840;
|
||||
if (key == "timeMultiplier") return 1;
|
||||
if (key == "startDateCode" || key == "weatherProfile") return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -41,6 +61,8 @@ class ERR_Settings
|
||||
m_Values.Set("radioDefenceSeconds", 180);
|
||||
m_Values.Set("startTimeMinutes", AddedDefault("startTimeMinutes"));
|
||||
m_Values.Set("timeMultiplier", AddedDefault("timeMultiplier"));
|
||||
m_Values.Set("startDateCode", AddedDefault("startDateCode"));
|
||||
m_Values.Set("weatherProfile", AddedDefault("weatherProfile"));
|
||||
if (!Replication.IsServer()) { m_ReadOnly = true; return; }
|
||||
map<string, int> loaded;
|
||||
if (Read(m_Path, loaded) || Read(m_Path + ".bak", loaded)) m_Values = loaded;
|
||||
|
||||
@@ -34,13 +34,20 @@ class ERR_SiteTransport
|
||||
float MaximumTerrainRange;
|
||||
}
|
||||
|
||||
[BaseContainerProps()]
|
||||
class ERR_SitePatrolPoint
|
||||
{
|
||||
[Attribute("0 0 0", UIWidgets.Coords, "Ground waypoint offset from the guard anchor")]
|
||||
vector Offset;
|
||||
}
|
||||
|
||||
[BaseContainerProps()]
|
||||
class ERR_SiteDefinition
|
||||
{
|
||||
[Attribute()]
|
||||
string Id;
|
||||
[Attribute()] string Label;
|
||||
[Attribute("0", UIWidgets.EditBox, "Conscious visual discovery radius for optional sites") ]
|
||||
[Attribute("0", UIWidgets.EditBox, "Conscious visual discovery radius: radio up to 8m, optional sites up to 60m") ]
|
||||
float DiscoverRadius;
|
||||
[Attribute()] ref array<ref ERR_SiteProp> Props;
|
||||
[Attribute()] ref ERR_SiteTransport Transport;
|
||||
@@ -52,6 +59,7 @@ class ERR_SiteDefinition
|
||||
vector Position;
|
||||
[Attribute("", UIWidgets.ResourceNamePicker, "Optional physical guard group", "et")]
|
||||
ResourceName Guards;
|
||||
[Attribute()] ref array<ref ERR_SitePatrolPoint> Patrol;
|
||||
[Attribute("0", UIWidgets.CheckBox, "Populate a finite squad from the faction catalog") ]
|
||||
bool Guarded;
|
||||
[Attribute("20 0 0", UIWidgets.Coords)]
|
||||
@@ -92,9 +100,9 @@ class ERR_ScenarioDefinition
|
||||
{
|
||||
if (!site || site.Id.IsEmpty() || ids.Contains(site.Id) || site.Prefab.IsEmpty()) return false;
|
||||
if (site.Label.IsEmpty() || site.Label.Length() > 64) return false;
|
||||
if (site.DiscoverRadius < 0 || site.DiscoverRadius > 60) return false;
|
||||
if (!ERR_SiteDiscoveryRules.ValidRadius(site.Kind, site.DiscoverRadius)) return false;
|
||||
bool optionalSite = site.Kind == ERR_LocationKind.DEPOT || site.Kind == ERR_LocationKind.OUTPOST;
|
||||
if (!optionalSite && (site.DiscoverRadius > 0 || site.RevealOnEscape)) return false;
|
||||
if (!optionalSite && site.RevealOnEscape) return false;
|
||||
if (site.Transport)
|
||||
{
|
||||
ERR_SiteTransport transport = site.Transport;
|
||||
@@ -116,6 +124,18 @@ class ERR_ScenarioDefinition
|
||||
if (site.Kind == ERR_LocationKind.RADIO) radios++;
|
||||
if (site.Kind == ERR_LocationKind.EXTRACTION) extractions++;
|
||||
if (site.Guarded || !site.Guards.IsEmpty()) groups++;
|
||||
if (site.Patrol && !site.Patrol.IsEmpty())
|
||||
{
|
||||
// Native Move completes within 5m: separate every point by at least 12m.
|
||||
if (!(site.Guarded || !site.Guards.IsEmpty()) || !optionalSite || site.Patrol.Count() < 2 || site.Patrol.Count() > 6) return false;
|
||||
for (int pointIndex = 0; pointIndex < site.Patrol.Count(); pointIndex++)
|
||||
{
|
||||
ERR_SitePatrolPoint point = site.Patrol[pointIndex];
|
||||
if (!point || point.Offset.Length() > 60 || Math.AbsFloat(point.Offset[1]) > 0.01) return false;
|
||||
for (int previous = 0; previous < pointIndex; previous++)
|
||||
if (vector.DistanceXZ(point.Offset, site.Patrol[previous].Offset) < 12) return false;
|
||||
}
|
||||
}
|
||||
int documents = 0;
|
||||
if (!site.Stock) continue;
|
||||
foreach (ERR_SiteStock stock : site.Stock)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Authoring bounds separate close identification of the objective radio from
|
||||
// broader discovery of optional supply sites. Neither reveals a remote site.
|
||||
class ERR_SiteDiscoveryRules
|
||||
{
|
||||
static float RadioRadiusLimit() { return 8; }
|
||||
static bool ValidRadius(int kind, float radius)
|
||||
{
|
||||
if (radius < 0 || radius > 60) return false;
|
||||
if (kind == ERR_LocationKind.RADIO) return radius <= RadioRadiusLimit();
|
||||
if (kind == ERR_LocationKind.DEPOT || kind == ERR_LocationKind.OUTPOST) return true;
|
||||
return (kind == ERR_LocationKind.PRISON || kind == ERR_LocationKind.EXTRACTION) && radius == 0;
|
||||
}
|
||||
static bool InRange(float radius, float horizontalDistance, float verticalDistance)
|
||||
{
|
||||
return radius > 0 && horizontalDistance >= 0 && horizontalDistance <= radius && verticalDistance >= 0 && verticalDistance <= 8;
|
||||
}
|
||||
}
|
||||
@@ -13,18 +13,26 @@ class ERR_SiteRuntime
|
||||
ERR_LocationComponent Location;
|
||||
IEntity Container;
|
||||
SCR_AIGroup Group;
|
||||
int InitialGuardCount;
|
||||
int LastInitialPhysical = -1;
|
||||
int LastInitialConscious = -1;
|
||||
Vehicle Transport;
|
||||
AIWaypointCycle PatrolCycle;
|
||||
ref array<AIWaypoint> PatrolWaypoints = {};
|
||||
}
|
||||
|
||||
// One owner for finite physical site contents. No population or stock refill tick.
|
||||
class ERR_SiteService
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ref ERR_ExtractionPlacement m_ExtractionPlacement;
|
||||
ERR_ExtractionPlacement ExtractionPlacement() { return m_ExtractionPlacement; }
|
||||
protected ref array<ref ERR_SiteRuntime> m_Sites = {};
|
||||
protected ref array<IEntity> m_Entities = {};
|
||||
protected ref array<ref ERR_StockPlacement> m_Placements = {};
|
||||
protected ERR_PrepareResult m_State = ERR_PrepareResult.PENDING;
|
||||
protected float m_Deadline;
|
||||
protected float m_GuardDeadline;
|
||||
protected bool m_Begun;
|
||||
protected bool m_Stopped;
|
||||
protected bool m_Activated;
|
||||
@@ -62,6 +70,49 @@ class ERR_SiteService
|
||||
PrintFormat("Rereintroduced [sites]: cache clearance position=%1 clear=%2", ground, !m_Obstructed);
|
||||
return !m_Obstructed;
|
||||
}
|
||||
protected bool CreateGuardOrders(ERR_SiteRuntime site, vector anchor)
|
||||
{
|
||||
if (!site.Definition.Patrol || site.Definition.Patrol.IsEmpty())
|
||||
{
|
||||
AIWaypoint defend = AIWaypoint.Cast(Spawn(ERR_Resources.DefendWaypoint(), anchor));
|
||||
if (!defend) return false;
|
||||
site.Group.AddWaypoint(defend);
|
||||
return true;
|
||||
}
|
||||
foreach (ERR_SitePatrolPoint point : site.Definition.Patrol)
|
||||
{
|
||||
AIWaypoint move = AIWaypoint.Cast(Spawn(ERR_Resources.MoveWaypoint(), anchor + point.Offset));
|
||||
if (!move) return false;
|
||||
site.PatrolWaypoints.Insert(move);
|
||||
}
|
||||
site.PatrolCycle = AIWaypointCycle.Cast(Spawn(ERR_Resources.CycleWaypoint(), anchor));
|
||||
if (!site.PatrolCycle) return false;
|
||||
site.PatrolCycle.SetRerunCounter(-1);
|
||||
site.PatrolCycle.SetWaypoints(site.PatrolWaypoints);
|
||||
// The native cycle inserts its own children and itself. Adding children here
|
||||
// would duplicate the route. HQ inserts Search at index 0 above this queue.
|
||||
site.Group.AddWaypoint(site.PatrolCycle);
|
||||
return true;
|
||||
}
|
||||
protected void StopPatrols()
|
||||
{
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
{
|
||||
array<AIWaypoint> empty = {};
|
||||
if (site.PatrolCycle) site.PatrolCycle.SetWaypoints(empty);
|
||||
if (site.Group)
|
||||
{
|
||||
array<AIWaypoint> queued = {};
|
||||
site.Group.GetWaypoints(queued);
|
||||
foreach (AIWaypoint waypoint : queued)
|
||||
if (waypoint && (waypoint == site.PatrolCycle || site.PatrolWaypoints.Contains(waypoint))) site.Group.RemoveWaypoint(waypoint);
|
||||
}
|
||||
foreach (AIWaypoint move : site.PatrolWaypoints) ERR_Actors.DeleteSpawned(move);
|
||||
ERR_Actors.DeleteSpawned(site.PatrolCycle);
|
||||
site.PatrolWaypoints.Clear();
|
||||
site.PatrolCycle = null;
|
||||
}
|
||||
}
|
||||
protected IEntity Spawn(ResourceName resource, vector position)
|
||||
{
|
||||
IEntity entity = ERR_Actors.Spawn(resource, ERR_Actors.Ground(position));
|
||||
@@ -159,6 +210,7 @@ class ERR_SiteService
|
||||
m_Begun = true;
|
||||
if (!definition || !definition.Valid()) return Fail("invalid scenario definition");
|
||||
m_Deadline = GetGame().GetWorld().GetWorldTime() + 15000;
|
||||
m_GuardDeadline = GetGame().GetWorld().GetWorldTime() + ERR_InitialGuardRules.TimeoutMilliseconds();
|
||||
foreach (ERR_SiteDefinition spec : definition.Sites)
|
||||
{
|
||||
vector position = ERR_Actors.Ground(spec.Position);
|
||||
@@ -176,6 +228,7 @@ class ERR_SiteService
|
||||
Vehicle helicopter = Vehicle.Cast(Spawn(m_Mode.Factions().ExtractionPrefab, position + "12 0 0"));
|
||||
if (!helicopter) return Fail("extraction vehicle");
|
||||
if (!m_Mode.SetExtractionVehicle(helicopter)) return Fail("extraction vehicle registration");
|
||||
m_ExtractionPlacement = new ERR_ExtractionPlacement(m_Mode, helicopter);
|
||||
}
|
||||
if (!spec.Container.IsEmpty())
|
||||
{
|
||||
@@ -231,20 +284,100 @@ class ERR_SiteService
|
||||
ResourceName groupPrefab = spec.Guards;
|
||||
if (groupPrefab.IsEmpty()) groupPrefab = m_Mode.Factions().GuardGroupPrefab;
|
||||
site.Group = SCR_AIGroup.Cast(Spawn(groupPrefab, guardPosition));
|
||||
AIWaypoint waypoint = AIWaypoint.Cast(Spawn(ERR_Resources.DefendWaypoint(), guardPosition));
|
||||
if (!site.Group || !waypoint) return Fail("guard population: " + spec.Id);
|
||||
site.Group.AddWaypoint(waypoint);
|
||||
if (!site.Group) return Fail("guard group resource: " + spec.Id);
|
||||
if (!site.Group.m_aUnitPrefabSlots || site.Group.m_aUnitPrefabSlots.IsEmpty() || !site.Group.GetSpawnImmediately()) return Fail("guard profile must request an initial physical squad: " + spec.Id);
|
||||
site.InitialGuardCount = site.Group.m_aUnitPrefabSlots.Count();
|
||||
foreach (ResourceName member : site.Group.m_aUnitPrefabSlots)
|
||||
if (member.IsEmpty()) return Fail("guard profile has an empty member resource: " + spec.Id);
|
||||
if (!CreateGuardOrders(site, guardPosition)) return Fail("guard initial orders: " + spec.Id);
|
||||
}
|
||||
PrintFormat("Rereintroduced [sites]: authored %1 at %2", spec.Id, position);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ERR_PrepareResult InitialGuards(ERR_SiteRuntime site)
|
||||
{
|
||||
bool requested = site.Definition.Guarded || !site.Definition.Guards.IsEmpty();
|
||||
if (!requested) return ERR_PrepareResult.READY;
|
||||
if (!site.Group || site.InitialGuardCount <= 0)
|
||||
{
|
||||
Fail("initial guard group disappeared or has no configured members: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
if (site.Group.GetFaction() != m_Mode.EnemyFaction())
|
||||
{
|
||||
Fail("guard group faction disagrees with catalog: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
array<AIAgent> agents = {};
|
||||
array<IEntity> physical = {};
|
||||
site.Group.GetAgents(agents);
|
||||
int conscious;
|
||||
foreach (AIAgent agent : agents)
|
||||
{
|
||||
if (!agent) continue;
|
||||
IEntity actor = agent.GetControlledEntity();
|
||||
if (!actor || physical.Contains(actor)) continue;
|
||||
physical.Insert(actor);
|
||||
if (SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction())
|
||||
{
|
||||
Fail("initial guard actor faction disagrees with catalog: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
if (ERR_Actors.CanFight(actor)) conscious++;
|
||||
}
|
||||
bool complete = site.Group.IsExpandComplete();
|
||||
if (site.LastInitialPhysical != physical.Count() || site.LastInitialConscious != conscious)
|
||||
{
|
||||
PrintFormat("Rereintroduced [guards]: initial site=%1 requested=%2 physical=%3 conscious=%4 nativeComplete=%5", site.Definition.Id, site.InitialGuardCount, physical.Count(), conscious, complete);
|
||||
site.LastInitialPhysical = physical.Count();
|
||||
site.LastInitialConscious = conscious;
|
||||
}
|
||||
ERR_PrepareResult result = ERR_InitialGuardRules.State(site.InitialGuardCount, physical.Count(), conscious, complete, GetGame().GetWorld().GetWorldTime() > m_GuardDeadline);
|
||||
if (result == ERR_PrepareResult.FAILED)
|
||||
{
|
||||
AIPathfindingComponent path = AIPathfindingComponent.Cast(site.Group.FindComponent(AIPathfindingComponent));
|
||||
NavmeshWorldComponent navmesh;
|
||||
if (path) navmesh = path.GetNavmeshComponent();
|
||||
bool tileLoaded, tileRequested;
|
||||
if (navmesh)
|
||||
{
|
||||
tileLoaded = navmesh.IsTileLoaded(site.Group.GetOrigin());
|
||||
tileRequested = navmesh.IsTileRequested(site.Group.GetOrigin());
|
||||
}
|
||||
PrintFormat("Rereintroduced [guards]: timeout detail site=%1 navmesh=%2 tileLoaded=%3 tileRequested=%4 dormantAlive=%5 dormantDead=%6", site.Definition.Id, navmesh != null, tileLoaded, tileRequested, site.Group.GetDormantAliveCount(), site.Group.GetDormantDeadCount());
|
||||
Fail(string.Format("initial guard population incomplete or invalid: site=%1 requested=%2 physical=%3 conscious=%4 nativeComplete=%5; limit=90s; no replacement requested", site.Definition.Id, site.InitialGuardCount, physical.Count(), conscious, complete));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected void CancelInitialGuardRequests()
|
||||
{
|
||||
// Stock DespawnMembers returns early for an empty group; explicitly remove
|
||||
// its queued initial request before a failed/stopped preparation deletes it.
|
||||
if (!GetGame()) return;
|
||||
ChimeraAIWorld world = ChimeraAIWorld.Cast(GetGame().GetAIWorld());
|
||||
if (!world) return;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
{
|
||||
if (!site.Group || site.InitialGuardCount <= 0) continue;
|
||||
// Retire this instance's initial spawn intent as well as its current queue
|
||||
// entries. A native expansion pass may otherwise schedule the empty capacity
|
||||
// again. Existing physical members remain until the owner rolls back.
|
||||
site.Group.SetSpawnImmediately(false);
|
||||
site.Group.m_aUnitPrefabSlots = new array<ResourceName>();
|
||||
world.PurgeSpawnRequestsForGroup(site.Group);
|
||||
}
|
||||
}
|
||||
|
||||
ERR_PrepareResult Prepare()
|
||||
{
|
||||
if (!Replication.IsServer() || !m_Begun || m_Stopped) return ERR_PrepareResult.FAILED;
|
||||
if (m_State != ERR_PrepareResult.PENDING) return m_State;
|
||||
int pending, accepted;
|
||||
if (!m_ExtractionPlacement) { Fail("extraction placement owner missing"); return m_State; }
|
||||
ERR_PrepareResult aircraftPlacement = m_ExtractionPlacement.Poll(GetGame().GetWorld().GetWorldTime());
|
||||
if (aircraftPlacement == ERR_PrepareResult.FAILED) { Fail(m_ExtractionPlacement.FailureReason()); return m_State; }
|
||||
int pending, accepted, pendingGuards;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
{
|
||||
if (!TransportReady(site))
|
||||
@@ -252,12 +385,9 @@ class ERR_SiteService
|
||||
if (GetGame().GetWorld().GetWorldTime() > m_Deadline) Fail("transport needs fuel, driver/passenger seats and a fitting parking footprint: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
if (!site.Group) continue;
|
||||
if (site.Group.GetFaction() != m_Mode.EnemyFaction())
|
||||
{
|
||||
Fail("guard group faction disagrees with catalog: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
ERR_PrepareResult guards = InitialGuards(site);
|
||||
if (guards == ERR_PrepareResult.FAILED) return m_State;
|
||||
if (guards == ERR_PrepareResult.PENDING) pendingGuards++;
|
||||
}
|
||||
string firstRejected;
|
||||
foreach (ERR_StockPlacement placement : m_Placements)
|
||||
@@ -276,6 +406,7 @@ class ERR_SiteService
|
||||
if (GetGame().GetWorld().GetWorldTime() > m_Deadline) Fail(string.Format("physical stock insertion timed out: pending=%1 accepted=%2 sample=%3", pending, accepted, firstRejected));
|
||||
return m_State;
|
||||
}
|
||||
if (pendingGuards > 0 || aircraftPlacement == ERR_PrepareResult.PENDING) return m_State;
|
||||
foreach (IEntity entity : m_Entities) m_Mode.Own(entity);
|
||||
m_State = ERR_PrepareResult.READY;
|
||||
PrintFormat("Rereintroduced [sites]: %1 sites and %2 physical stock items ready", m_Sites.Count(), m_Placements.Count());
|
||||
@@ -302,10 +433,12 @@ class ERR_SiteService
|
||||
bool CanObserve(IEntity player, ERR_SiteRuntime site)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || !m_Mode.Active() || m_Mode.Phase() < ERR_Phase.RADIO_SEARCH) return false;
|
||||
if (!site || !site.Location || site.Definition.DiscoverRadius <= 0 || !ERR_Actors.CanFight(player)) return false;
|
||||
if (!site || !site.Definition || !m_Sites.Contains(site) || !site.Location || !m_Mode.HasLocation(site.Location) || !ERR_Actors.CanFight(player)) return false;
|
||||
if (!ERR_Actors.Player(player) || !m_Mode.Players() || !m_Mode.PlayerFaction() || SCR_FactionManager.SGetFaction(player) != m_Mode.PlayerFaction()) return false;
|
||||
if (!m_Mode.Players().CurrentActor(player)) return false;
|
||||
vector position = site.Location.Position();
|
||||
vector observer = player.GetOrigin();
|
||||
if (vector.DistanceXZ(observer, position) > site.Definition.DiscoverRadius || Math.AbsFloat(observer[1] - position[1]) > 8) return false;
|
||||
if (!ERR_SiteDiscoveryRules.InRange(site.Definition.DiscoverRadius, vector.DistanceXZ(observer, position), Math.AbsFloat(observer[1] - position[1]))) return false;
|
||||
TraceParam trace = new TraceParam();
|
||||
trace.Start = player.GetOrigin() + "0 1.5 0";
|
||||
trace.End = position + "0 1.3 0";
|
||||
@@ -333,11 +466,19 @@ class ERR_SiteService
|
||||
}
|
||||
void Rollback()
|
||||
{
|
||||
Stop();
|
||||
// Children/items are listed after parents; delete them first.
|
||||
for (int i = m_Entities.Count() - 1; i >= 0; i--) ERR_Actors.DeleteSpawned(m_Entities[i]);
|
||||
m_Entities.Clear();
|
||||
m_Placements.Clear();
|
||||
m_Sites.Clear();
|
||||
}
|
||||
void Stop() { m_Stopped = true; }
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
if (m_ExtractionPlacement) m_ExtractionPlacement.Stop();
|
||||
if (m_State == ERR_PrepareResult.PENDING) CancelInitialGuardRequests();
|
||||
StopPatrols();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ class ERR_SpawnLogic : SCR_SpawnLogic
|
||||
BindLifecycle(mode);
|
||||
SCR_PlayerController resultController = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId));
|
||||
if (resultController) resultController.ERR_ResetEscapeResult();
|
||||
#ifndef WORKBENCH
|
||||
string diagnosticProject;
|
||||
if (System.GetCLIParam("errOrdinaryScenario", diagnosticProject))
|
||||
PrintFormat("ERR ORDINARY ADMISSION: server=%1 sessionMode=%2 modePresent=%3 controllerPresent=%4 identityPresent=%5 nameLength=%6", Replication.IsServer(), RplSession.Mode(), mode != null, resultController != null, !identity.IsNull(), GetGame().GetPlayerManager().GetPlayerName(playerId).Length());
|
||||
#endif
|
||||
if (!mode || !mode.Players().Bind(playerId, identity))
|
||||
{
|
||||
Print("Rereintroduced: player identity could not be bound; spawn withheld", LogLevel.ERROR);
|
||||
|
||||
@@ -38,15 +38,23 @@ class ERR_SpawnPlacement
|
||||
}
|
||||
bool Prison(vector center, map<int, vector> reservations, out vector position)
|
||||
{
|
||||
// 25 bounded candidates lie inside the authored 12 by 12 metre prison.
|
||||
for (int z = -2; z <= 2; z++)
|
||||
for (int x = -2; x <= 2; x++)
|
||||
{
|
||||
vector candidate = ERR_Actors.Ground(center + Vector(x * 1.5, 0, z * 1.5));
|
||||
if (!Clear(candidate, reservations)) continue;
|
||||
position = candidate;
|
||||
return true;
|
||||
}
|
||||
// Native character query bounds are about 4m wide. A 3m lattice leaves
|
||||
// clearance between that conservative bound and the 0.9m query column.
|
||||
// Search the four inner positions, then eight edge positions, then corners.
|
||||
// All sixteen centers remain at least 1.5m inside the authored +/-6m walls.
|
||||
for (int band = 0; band <= 2; band++)
|
||||
for (int row = 0; row < 4; row++)
|
||||
for (int column = 0; column < 4; column++)
|
||||
{
|
||||
int outerAxes = 0;
|
||||
if (row == 0 || row == 3) outerAxes++;
|
||||
if (column == 0 || column == 3) outerAxes++;
|
||||
if (outerAxes != band) continue;
|
||||
vector candidate = ERR_Actors.Ground(center + Vector(-4.5 + column * 3, 0, -4.5 + row * 3));
|
||||
if (!Clear(candidate, reservations)) continue;
|
||||
position = candidate;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Near(IEntity survivor, map<int, vector> reservations, out vector position)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Honor noSplash before Game-module widget classes exist, only for the
|
||||
// explicit ordinary diagnostic. Visible/unflagged startup stays vanilla.
|
||||
#ifndef WORKBENCH
|
||||
modded class SplashScreen
|
||||
{
|
||||
protected bool m_ERRDiagnosticSplashSkipped;
|
||||
|
||||
override void Load()
|
||||
{
|
||||
string project;
|
||||
if (!System.IsCLIParam("noSplash") || !System.GetCLIParam("errOrdinaryScenario", project) || (project != "core" && project != "chat"))
|
||||
{
|
||||
super.Load();
|
||||
return;
|
||||
}
|
||||
// BaseLoadingAnim.Show may request Load again while the deliberately absent
|
||||
// root is null. Preserve the splash sequence counter once per instance.
|
||||
if (!m_ERRDiagnosticSplashSkipped)
|
||||
{
|
||||
m_ERRDiagnosticSplashSkipped = true;
|
||||
s_iSplashShown++;
|
||||
Print("ERR ORDINARY: diagnostic noSplash honored before Game compilation");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@ SCR_AIWorld AIWorld : "{E0A05C76552E7F58}Prefabs/AI/SCR_AIWorld.et" {
|
||||
}
|
||||
PerceptionManager Perception : "{028DAEAD63E056BE}Prefabs/World/Game/PerceptionManager.et" {
|
||||
}
|
||||
SCR_FactionManager Factions : "{589540B35EBA8CDC}Prefabs/MP/Managers/Factions/FactionManager_USxUSSR.et" {
|
||||
SCR_FactionManager Factions : "{5414041A15DC4B54}Prefabs/ERR/FactionManager.et" {
|
||||
}
|
||||
SCR_LoadoutManager Loadouts : "{97EF4C1A41F63DDB}Prefabs/MP/Managers/Loadouts/LoadoutManager_USxUSSR.et" {
|
||||
}
|
||||
|
||||
+105
-4
@@ -81,11 +81,12 @@
|
||||
]
|
||||
},
|
||||
"clean_native_runtime": {
|
||||
"status": "failed",
|
||||
"reason": "Inherited vehicle schema errors remain; earlier restart also reported vanilla catalog cleanup errors",
|
||||
"status": "pending",
|
||||
"scope": "The 065351 source snapshot passed two environment/restart rounds with zero native errors. Subsequent production changes require another current-source full-loop run before this release gate can pass. Historical evidence remains recorded in scripted_environment_restart.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-003520/report.json",
|
||||
"docs/evidence/native-2026-09-19-002824/report.json"
|
||||
"docs/evidence/native-2026-09-19-065351/report.json",
|
||||
"docs/evidence/native-2026-09-19-065351/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-065351/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_helicopter_loss_and_restart": {
|
||||
@@ -400,6 +401,106 @@
|
||||
"docs/evidence/native-2026-09-19-053124/source-sha256.json",
|
||||
"docs/evidence/native-2026-09-19-053124/source-provenance.json"
|
||||
]
|
||||
},
|
||||
"native_medical_consumption_recovery": {
|
||||
"status": "passed",
|
||||
"scope": "24 local hidden/muted Workbench assertions: real blood loss, bandage consumption, native saline treatment slot/effect, duplicate refusal, natural consciousness recovery and90-second expiry. No direct consciousness restoration. Seven inherited engine errors remain; no manual interaction or multiplayer claim.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-062406/report.json",
|
||||
"docs/evidence/native-2026-09-19-062406/runner.json.txt",
|
||||
"docs/evidence/native-2026-09-19-062406/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"native_environment_and_faction_catalogs": {
|
||||
"status": "passed",
|
||||
"scope": "67 local hidden/muted Workbench assertions: exact two-vehicle faction catalogs with native inventory/medical/radio support, authored defaults, persisted date/profile, leap-date validation, next-round commands, native clear/overcast/rain and clock preservation. Zero script/VM or engine errors. One round only; multiplayer and repeated restart qualification remain pending.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-063559/report.json",
|
||||
"docs/evidence/native-2026-09-19-063559/runner.json.txt",
|
||||
"docs/evidence/native-2026-09-19-063559/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_twelve_prisoner_kit": {
|
||||
"status": "passed",
|
||||
"scope": "155 combined native assertions passed with zero engine errors: one controlled prisoner and eleven physical test characters fit inside the prison, each has the exact unique starting inventory, can receive and return a clue, and test actors are cleaned up. This is not twelve network clients or manual inventory UI validation.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-063949/report.json",
|
||||
"docs/evidence/native-2026-09-19-063949/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-063949/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_recovery_abandonment": {
|
||||
"status": "passed",
|
||||
"scope": "54 combined native assertions passed with zero engine errors, including all-incapacitated status, event deduplication, survivor preservation beyond the death grace, authorization checks and abandonment while the warning is active. Health state is controlled by this policy fixture; actual treatment has a separate fixture.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-064406/report.json",
|
||||
"docs/evidence/native-2026-09-19-064406/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-064406/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_environment_restart": {
|
||||
"status": "passed",
|
||||
"scope": "Two actual local Workbench rounds; 107 assertions with zero script/VM or engine errors. Real production settings owner saves a leap date and overcast profile for the next instance, preserves active weather/clock in round one, applies choices in round two and cleans owned fixture files. Remote agreement and manual administration remain unqualified.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-065351/report.json",
|
||||
"docs/evidence/native-2026-09-19-065351/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-065351/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_total_document_loss": {
|
||||
"status": "passed",
|
||||
"scope": "58 native assertions and zero errors. All four finite radio documents were deleted; distant and unpossessed actors and an obstructing wall were rejected. A clear close approach by the actual controlled participant identifies the station once and permits normal tuning, without replacement clues. Partial knowledge has a separate passing fixture.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-070733/report.json",
|
||||
"docs/evidence/native-2026-09-19-070733/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-070733/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_initial_guards_and_patrols": {
|
||||
"status": "passed",
|
||||
"scope": "295 native assertions and zero errors. Preparation observes all six original squads with six distinct conscious members and completed native spawn requests. Both patrols move existing actors and complete five native waypoints in cyclic order. Native startup queue references repeat but clear as waypoints complete; final queues are unique. Repeated route Stop preserves a foreign Search. No HQ order transit or multiplayer claim.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-070919/report.json",
|
||||
"docs/evidence/native-2026-09-19-070919/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-070919/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_partial_document_loss": {
|
||||
"status": "passed",
|
||||
"scope": "60 native assertions and zero errors. One real clue supplies partial knowledge before all four finite documents are deleted. Distant/NPC/obstructed observers are rejected; clear close approach identifies the station once and permits tuning. No replacement documents, remote clients or manual gameplay claim.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-071654/report.json",
|
||||
"docs/evidence/native-2026-09-19-071654/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-071654/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_patrol_hq_resume": {
|
||||
"status": "passed",
|
||||
"scope": "272 local native assertions, zero errors, all companions. Same physical squad traverses patrol, real HQ delivered-order Search preempts it, release preserves route, and movement/cyclic completion resumes. No extra force, radio-transit or remote-client claim.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-072838/report.json",
|
||||
"docs/evidence/native-2026-09-19-072838/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-072838/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_pending_guard_cancellation": {
|
||||
"status": "passed",
|
||||
"scope": "68 native assertions and zero errors. Empty and partial PENDING-owned groups receive no late dispatch or members after Stop2x while uncancelled control reaches six. Rollback deletes captured actors/groups, six-second observation stays quiet, original mission groups intact. No multiplayer claim.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-073601/report.json",
|
||||
"docs/evidence/native-2026-09-19-073601/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-073601/source-sha256.json"
|
||||
]
|
||||
},
|
||||
"scripted_radio_feedback_restart": {
|
||||
"status": "passed",
|
||||
"scope": "Two complete Core escape/restart rounds, 564 assertions and zero errors. Both verify initial radio wait, transmission, unconscious interruption, recovery, leave/reset and completion feedback plus existing administration, roster, documents, objective UI and extraction. Station teardown diagnostics enabled. No remote feedback, ordinary gameplay or later placement-source qualification.",
|
||||
"evidence": [
|
||||
"docs/evidence/native-2026-09-19-073806/report.json",
|
||||
"docs/evidence/native-2026-09-19-073806/console.log.txt",
|
||||
"docs/evidence/native-2026-09-19-073806/source-sha256.json",
|
||||
"docs/evidence/native-2026-09-19-073806/source-provenance.json"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Core document discovery setting
|
||||
|
||||
The physical document discovery service belongs to Core. Its existing `intelRevealChancePercent` setting is now configurable in Core-only games through the same administrator-only command used by the companion Chat addon:
|
||||
|
||||
| Command | Result |
|
||||
| --- | --- |
|
||||
| `/esc intel reveal show` | Display the current saved percentage |
|
||||
| `/esc intel reveal set N` | Save a whole number from 0 to 100 |
|
||||
| `/esc intel reveal help` | Explain the range, document rules and when changes apply |
|
||||
|
||||
The first recovered document identifies its destination exactly with the configured percentage chance. Otherwise it provides a rough location. A second eligible document for the same location always identifies it. Setting 0 therefore still permits progression through the two independent two-document caches; setting 100 identifies the destination on the first document. A change affects newly recovered documents immediately. Existing knowledge and documents already counted by discovery are not reset or reprocessed.
|
||||
|
||||
The server retains the existing authentication, rate limit and command-length checks. Malformed values, out-of-range values and failed saves preserve the previous setting. Existing show and successful-set reply formats remain unchanged. Invalid discovery values now include the valid range and progression explanation. Other settings and time/abandon commands keep their existing behavior.
|
||||
|
||||
Chat delegates the reveal alias to Core instead of defining a duplicate. Its `intel carrying` and HQ commands remain companion-specific. This does not expose administration to ordinary players or add a new RPC.
|
||||
|
||||
## Validation
|
||||
|
||||
`tests/test_admin_setting_policy.py` executes the actual Core alias mapping, strict integer parser and settings range predicates through the source-local C++ harness. It checks percentage endpoints, malformed numeric text, radio-duration boundaries, unknown aliases and companion-only exclusions. `python3 tools/check.py` includes it.
|
||||
|
||||
`ERR_NativeAdminSettingsProbe.Run(ERR_GameMode mode)` is an opt-in WORKBENCH test awaiting central native execution. It checks actual authorized read/help dispatch and unauthorized/invalid mutation rejection. Valid changes exercise the same production setting-command handler with a separate `ERR_Settings` instance at `$profile:erri-native-admin-settings-probe.json`; they never mutate the active mission's settings. The fixture rejects already-existing fixture files, verifies native save/reload and unrelated values, then removes only its own fixture primary, backup and temporary files.
|
||||
|
||||
A policy pass does not prove native script compilation, remote RPC ownership or readable chat presentation. Run the native probe inside Core-only and companion regression fixtures, then retain real-client administration in multiplayer acceptance.
|
||||
@@ -38,7 +38,7 @@ The server selects a living friendly survivor for each spectator and replicates
|
||||
|
||||
Core reads `ERR_ScenarioDefinition` from `Configs/ERR/EveronSites.conf`. `ERR_SiteService` owns the resulting locations, guards, containers and stock. The scenario component handles pending/ready/failed preparation separately from mission progression. Location IDs are supplied by configuration and replicated; templates carry no fixed scenario identity. Initial inventory items are created once, and retries move the same entities into the container. Readiness requires observed physical inventory contents. A completed service never refills stock or replaces destroyed sites.
|
||||
|
||||
`ERR_DocumentComponent` binds each mandatory physical clue to a radio location. Core recovery applies it only to that destination; optional generic enemy intel retains its broader discovery behavior. Definition validation requires a starting map and, for Everon, two separate guaranteed clue sources at least 100 metres apart. Each has enough documents to identify the radio independently. Optional supply/outpost locations use bounded five-second conscious-player visibility scans; progression sites remain document-controlled. Location names and discovery state replicate to the map, while actual knowledge transitions publish the server-side discovery event. Native tests mutate separate definition instances to verify invalid inputs are rejected. [Authoring details and current stock](site-authoring.md).
|
||||
`ERR_DocumentComponent` binds each mandatory physical clue to a radio location. Core recovery applies it only to that destination; optional generic enemy intel retains its broader discovery behavior. Definition validation requires a starting map and, for Everon, two separate guaranteed clue sources at least 100 metres apart. Each has enough documents to identify the radio independently. Optional supply/outpost locations use bounded five-second conscious-participant visibility scans. Radio identification also permits an eight-metre clear-view approach to the physical station, preserving progress if every finite document is lost. Prison and extraction locations do not gain proximity disclosure. Location names and discovery state replicate to the map, while actual knowledge transitions publish the server-side discovery event. Native tests mutate separate definition instances to verify invalid inputs are rejected. [Authoring details and current stock](site-authoring.md).
|
||||
|
||||
## Base configuration and administration
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Bounded base gameplay audit: starting kit and casualty recovery
|
||||
|
||||
Current implementation update: an independently authored prisoner prefab now specifies its starting inventory; Core observes all-incapacitated survivors and supports explicit administrator abandonment. Separate native prisoner, medical and casualty mechanism fixtures have been added. Their actual evidence and remaining limits are recorded in the companion documents and validation log. The audit below is the original finding record, not a claim that these implementations remain absent.
|
||||
|
||||
This source audit covers the first Everon release for up to 12 players. It identifies the next three implementation/acceptance priorities; it does not claim that the ordinary escape route is impossible. No health settings, loadouts, original missions or shared staging were changed by this review. No engine was launched.
|
||||
|
||||
## 1. Establish an explicit successor starting kit
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"/tmp/erri-vanilla/Prefabs/Vehicles/Helicopters/Mi8MT/Mi8_base.et": "2b6c425e48beda9f67082204023fdbace7773ab0e9b25b7e9f72de6bef22a571"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# Parked extraction helicopter: verified landing-gear support
|
||||
|
||||
The parent's native `logs_2026-09-19_07-20-14` showed ten seconds of an intact, upright, motionless authored Mi8 with a valid controller/simulation/physics and `HasAnyGroundContact()==false`. The caller/helper were alive and correctly positioned. Native helicopter simulation exposes this aggregate contact flag and terrain altitude, but no per-wheel query equivalent to wheeled simulation. The installed vanilla available-action condition also simply reads the aggregate flag; it provides no alternative initialization mechanism. No physics wake, engine start, teleport or simulation mutation is added to production.
|
||||
|
||||
`ERR_CasualtyGroundSupport` supplies a conservative fallback only for the known Mi8 family when its physics body is asleep and its engine is off. The ordinary native contact path is retained. Existing speed (0.5m/s), angular velocity (0.1rad/s) and upright (up.y >= 0.85) limits still apply to both routes. Powered hovering cannot use the fallback.
|
||||
|
||||
The installed Mi8_base.et defines three landing-gear bones: `v_wheel_F` with radius 0.30m and `v_wheel_bL`/`v_wheel_bR` with radius 0.45m. Native PointInfo resolves their actual world pivots. All three pivots must exist and remain separated by at least one metre, guarding against failed/collapsed resolution. At each tire bottom, a short vertical trace spans 0.10m above to 0.12m below. Every trace must hit upward-facing collision (normal.y >= 0.85). Hits on the aircraft or its children, dynamic entities and entities without physical support are rejected. Terrain/static collision can support the aircraft; altitude alone cannot. The small tolerance covers collision/placement precision and does not claim exact zero-distance tire contact. Active aircraft without a native contact flag fail closed; unsupported dynamic platforms are outside this fallback.
|
||||
|
||||
Native PointInfo bone resolution, actual tire-to-ground gaps, awake state and trace normal/entity behavior are still **unverified in the engine for this patch**. The opt-in fixture prints all of them. If the untouched aircraft is awake or its authored geometry lies outside the tight support tolerance, the test will fail explicitly; do not silently widen it or activate physics simply to get a pass.
|
||||
|
||||
## Files and integration
|
||||
|
||||
New files:
|
||||
|
||||
- `addons/core/Scripts/Game/ERR/ERR_CasualtyGroundSupport.c`
|
||||
- `addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c`
|
||||
- `tests/test_casualty_ground_policy.py`
|
||||
|
||||
Apply `ground-support-integration.patch` only to the indicated AircraftReady/Nearby and native casualty-fixture hunks. Its latest central-service baseline preserves the separately reviewed committed-lifecycle changes. Add `test_casualty_ground_policy.py` to the parent's `tools/check.py` test list. No new outcome or BaseSmoke steps are required: the existing `casualty-service` readiness stage runs the bounded ground probe before causing unconsciousness.
|
||||
|
||||
The positive native check reads the untouched actual mission helicopter. It then spawns a separate empty aircraft twenty metres higher, protects that disposable entity from damage, and verifies airborne rejection. On that clone only, it sets a 90-degree tilt and reads the resulting native up vector, then assigns and immediately reads a nonzero native velocity. The production motion policy is checked independently with those actual values, while full AircraftReady must also reject the clone. This is not a travelled-distance/flight-control test. The clone is deleted on completion or failure. The mission aircraft's transform, velocity, activation, engine and health handling are never changed.
|
||||
|
||||
The focused support policy test passed. Native compilation, positive wheel support and the negative physics checks remain pending. `source-sha256.json` identifies the exact installed Mi8 configuration inspected.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Fixture incapacitation correction
|
||||
|
||||
The native casualty fixture used a protected actor, but installed `ForceUnconsciousness` calls resilience `HandleDamage(..., EDamageType.TRUE, ...)`. Native evidence showed protection could swallow that operation and leave the actor conscious.
|
||||
|
||||
The isolated base-probe patch snapshots the actual damage-handling flag, enables it for one synchronous `ForceUnconsciousness` call, reads the actual resilience decrease, and restores the original flag before assertions or cleanup. It asserts decreased resilience, a living actor and exact flag restoration. The existing asynchronous native controller-state check and five-second settling interval remain. No health, consciousness or resilience is restored afterward; no production medical or damage behavior changes.
|
||||
|
||||
`test_casualty_incapacitation.py` executes the actual extracted fixture method against a narrow damage API fake. Both original flag values are preserved; blocked reduction, missing hit zone/manager and dead actor cases fail. This is source-level regression evidence, not native runtime proof.
|
||||
|
||||
The latest parent identifier fixes are retained in the local removal-probe baseline: `doorReference` and `exitTransform`. Installed generated source confirms `BaseCompartmentManagerComponent.GetDoorReference(int)` returns `CompartmentDoorReference`; that class exposes `GetReferencedDoorCompartmentManager()` and inherits `GetAnimDoorIndex()` from `BaseCompartmentDoor`. The native compiler rejected the previous local identifier `reference`; the API return type itself exists. This patch does not include or repeat those already-applied identifier changes.
|
||||
|
||||
Merge only `casualty-incapacitation.patch` and new `tests/test_casualty_incapacitation.py`; no central source or engine was touched by this agent.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Ground casualty loading into extraction transport
|
||||
|
||||
This independently authored implementation adds a five-second `Load casualty into extraction helicopter` action only to the successor Prisoner prefab, using its existing Chest and LowerTorso interaction contexts. It keeps inherited vanilla medical interactions. The service and owner bridge compile natively, and the five-second action and inherited medical actions have been inspected in the native fixture. Ground support, completed interaction and multiplayer qualification are still pending; the earlier successful child-bench mechanism experiment alone does not qualify this complete interaction. Ground exit placement still fails its separate native assertion, so this implementation deliberately supplies no unload action or claim.
|
||||
|
||||
The server accepts only distinct, connected participants whose current controller, connection and used-life roster record all match their current bodies through the canonical server-owned `ERR_PlayerRoster.CurrentActor` check. The bound roster identity must be non-null; this also preserves the existing offline Workbench identity path. A reserved disconnected body is deliberately ineligible. The rescuer must be conscious and on foot; the living target must be natively incapacitated, on the ground, not entering/exiting a vehicle and observed settled for at least five seconds. Settlement is sampled through the round tick with a maximum two-second observation gap; it does not infer that unobserved sub-tick movement was impossible. Recovery, falling, movement, stale observation or identity changes reset the observation window.
|
||||
|
||||
Both actors must be within 12 metres of the registered extraction aircraft and within three metres of one another. The mission must be active in EXTRACTION. The intact helicopter needs actual simulation ground contact or the conservative sleeping, engine-off three-wheel support check described in [casualty-ground-support.md](casualty-ground-support.md), an upright vertical component at least 0.85, linear velocity at most 0.5 m/s and angular velocity at most 0.1 rad/s. Native body interaction contexts provide initial line-of-sight presentation. A new shared native raycast revalidates rescuer-to-casualty sight on the server at request and commit, then again on the owner immediately before entry. It accepts an unobstructed segment or contact with the intended casualty and its attachments. This first version does not supply carrying/dragging animations, arbitrary vehicle loading, or a player unloading action.
|
||||
|
||||
Only actual child transport benches of the registered Mi8 are selectable. The service rejects its root navigator CARGO slot, patient slots, pilot/turret slots, occupied, inaccessible, locked or reserved slots. The exact slot must belong to the actual aircraft's hierarchy and the installed Mi8 seat-part prefab. Native seat classes and health settings remain unchanged. A native reservation plus service tickets prevents duplicate requests for the same caller, casualty or bench. Reservation replication/contention still needs remote tests.
|
||||
|
||||
## Ownership and commit boundary
|
||||
|
||||
A stock `MoveInVehicle` request may retry for missing replicated vehicle entities. This service does not invoke that method or queue callbacks. It uses a successor-specific controller handshake:
|
||||
|
||||
1. Action completion passes live server checks and reserves a bench. The target's controller receives a prepare request identifying the actual mode instance and ticket. Preparation cannot move anyone.
|
||||
2. The target owner validates its current body/phase, starts a three-second local `System.GetTickCount` lease, and sends ready. The server accepts ready only from the ticket's exact controller/body and revalidates identity, current physical state, settled duration, reservation and a five-second preparation deadline.
|
||||
3. The server commits one command with exact mode, caller, casualty, aircraft, seat-owner replication IDs and the slot ID. This is the final authorization boundary. The owner consumes the unexpired lease before executing, rechecks matching mode/body/aircraft, native incapacitation, ranges, grounded craft and the real child seat, then calls native `GetInVehicle` once. Missing entities and native refusals fail once; no delayed retry can later acquire a seat. Duplicate or expired commits cannot execute.
|
||||
4. The server never trusts either a positive or negative client acknowledgement as permission to resolve or release a seat. It observes actual target-seat occupancy and aircraft membership, with an eight-second post-commit budget. The local lease bounds how long a delayed commit may start movement without requiring clocks synchronized between machines. Before commit, identity/physical changes cancel the request. After commit, caller or casualty connection changes alone do not cancel the authorized move or release its reservation: the immutable original body/aircraft/seat are observed until completion or expiry. Death of a still-existing target body retains the committed reservation through physical occupancy or expiry, because the owner can still have pre-death replicated state. Occupancy by a dead target resolves as failure. Loss of the physical aircraft/body or terminal/explicit Stop ends observation without compensating teleports or health changes.
|
||||
|
||||
An already committed native movement is not rolled back if conditions subsequently change. A false resolution means loading was not confirmed by this service, not that a committed native command was magically revoked. Terminal/identity changes are also rechecked on the owner; replication ordering under real latency remains a required multiplayer test. The service removes only a reservation still owned by the same surviving target reference, never another player's reservation. Native reservation cleanup after entity deletion also requires explicit runtime verification.
|
||||
|
||||
The mode adapter owns Tick/Stop/roster subscriptions and replicates only the current extraction-aircraft reference for client action presentation. Roster events run cleanup even when the ordinary mission tick returns early on an empty server. PREPARING roster callbacks are no-ops and cannot permanently stop the service. Terminal/explicit Stop latches before notifying subscribers, releases owned tickets and removes subscriptions. No new persistent settings, public entity-selection RPC, automatic spawning or original Escapists resource is introduced.
|
||||
|
||||
## Merge and checks
|
||||
|
||||
New production files:
|
||||
|
||||
- `addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c`
|
||||
- `addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingOwner.c`
|
||||
- `addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingGameMode.c`
|
||||
- `addons/core/Scripts/Game/ERR/ERR_LoadCasualtyAction.c`
|
||||
|
||||
Copy this document and `tests/test_casualty_loading_policy.py`, then apply `casualty-production-integration.patch` for `Prisoner.et` and `tools/check.py`. No existing GameMode source or native probe is replaced. The action reuses the existing Prisoner resource identity; new nested action/UI component IDs are successor-authored.
|
||||
|
||||
Offline checks execute production timing/range/aircraft-motion policy bodies and the complete repository suite. Native work must inspect the real spawned action and inherited medicine actions, show strict rejection for nonparticipants/old bodies/wrong phase, then exercise genuine two-player authorization and physical movement. Test cancellation during action progress, recovery during progress, duplicate callers, last-seat contention, native refusal, loss of replication visibility, delayed/reordered/expired handshake, disconnect/reconnect, aircraft loss and terminal transition. Confirm native seat reservation cleanup and actual single occupancy. Do not count synthetic fixture roster identities as proof of remote controller ownership.
|
||||
|
||||
## Bounded local service fixture
|
||||
|
||||
`ERR_NativeCasualtyServiceProbe.c` is excluded outside WORKBENCH. Opt-in `casualty-service` uses Core steps 1400/1402 and a 45-second fixture deadline. It moves the actual local controlled player beside the real helicopter and causes native incapacitation once; the ordinary owner-controller handshake and target roster checks remain real. Only a separately spawned physical helper receives a synthetic `CurrentLife` adapter. Before enabling that adapter, the fixture explicitly checks real-target membership and strict rejection of the helper, including in a valid physical extraction state. This is not a second authenticated network player.
|
||||
|
||||
The fixture deliberately advances legal mission phases to reach extraction; it does not claim a completed radio objective. It checks a fresh settling window, native external bench reservations, a physical successor wall blocking sight, the real action's completion boundary, duplicate requests, actual player occupancy, reservation release, preserved target identity and idempotent Stop. It does not simulate holding action input, remote packet timing or Stop during an in-flight command. It retains inherited medical-action presence. On completion the normal test reset ends the round; cleanup deletes only the helper/obstacle and releases fixture-owned reservations, with no forced recovery, seated-player teleport, body deletion or unrelated health restoration.
|
||||
|
||||
The WORKBENCH mode override routes owner callbacks to the helper adapter only during this explicit case. Add the new fixture source, then use `casualty-service-base-snippets.md` for parent-owned smoke/runner integration. [075514](evidence/native-2026-09-19-075514/report.json) completes this local fixture with 87 passing assertions and zero engine or script/VM errors. The production one-shot initial placement lets the original aircraft settle naturally; separate raised, tilted and moving aircraft are rejected. A single actual native damage request incapacitates the controlled player, then the real action completion boundary and owner-controller handshake load that living body into the selected child bench exactly once. External reservations and physical obstruction reject requests; successful loading releases the reservation, retains player identity and survives idempotent Stop without another completion.
|
||||
|
||||
The real local controller takes the server/local fast path; this does not exercise remote Owner/Server RPC transit. Only the helper membership is adapted, and action completion is invoked directly rather than holding input for five seconds. The fixture requests its own reset after loading, without a complete radio-to-extraction playthrough. Real two-player input, latency/reordering, disconnect/death while pending, last-seat contention and entity-removal cleanup remain separate requirements. Earlier contact and damage-fixture failures are preserved in the validation log.
|
||||
|
||||
|
||||
The separate [stock removal fixture](native-casualty-remove.md) passes in [080058](evidence/native-2026-09-19-080058/report.json): the helicopter's inherited door action removes a test-owned casualty from a real bench, leaving it living and incapacitated beside the authored exit with the seat vacant and accessible. This supplements loading with a local native removal path. It is not the production service's real-player/remote handshake, held action input, or a new extraction-result calculation.
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"scripts/Game/UserActions/SCR_RemoveCasualtyUserAction.c": "fb82fba4e3fd2cc94457942605eb09b13ad10bb033b51615732c7a5ff6611ac0",
|
||||
"scripts/GameCode/UserAction/SCR_CompartmentUserAction.c": "1bb3aeb3aaba90e582a41b737558879e712faf3a57a7542fae89c12e536b50f9",
|
||||
"scripts/Game/generated/Components/CompartmentAccessComponent.c": "a3a0907d771293d2423649aa0ff0e71b7f457279defac05fd693baf4dd7c447e",
|
||||
"scripts/Game/generated/CompartmentDoorInfo.c": "bcb885c5bcb13ce4ad98275be1a8079a96e0f0deb9f2470ba581b15da0ec410a",
|
||||
"scripts/Game/generated/CompartmentDoorReference.c": "c653c63c1835919ec5c5d29fbe7a5d22ee4a805d8ebc806e448dacbfcb4056b8",
|
||||
"scripts/Game/generated/BaseCompartmentDoor.c": "35f6797ac5bc69ccdf3de755601d2a5f74f4ead567cbda35f8a1f5478459f3c6",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/VehParts/Seats/VehPart_MI8_seats_base.et": "1b9a2e55a9a1cb884886488b6e170f437b6c1a615b584449819b96a6c78ad973",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/Mi8_base.et": "2b6c425e48beda9f67082204023fdbace7773ab0e9b25b7e9f72de6bef22a571",
|
||||
"Prefabs/Vehicles/Core/Configs/CargoCompartment_Base.conf": "326668ddc77c1ccb48ce10a0bea33be3bec77803cacae523d3e1f0c93249c5bc"
|
||||
}
|
||||
@@ -40,3 +40,5 @@ The command parser and setting mutations have native service tests. Actual remot
|
||||
If the faction/catalog setup or authored site preparation fails, the mode retains the reason, stops its services and refuses progression or spawning. It does not fall back to a partially prepared mission. A local hint describes the failure and `/esc status` gives administrators the cause. Correct the resource/configuration and restart the scenario. There is no automatic retry that recreates stock or forces after failure.
|
||||
|
||||
Waiting for normal site preparation does not consume a player's spawn retry budget. Once ready, actual failed spawn requests are bounded. This does not remove the one-life or identity requirements.
|
||||
|
||||
Core also provides `/esc mission abandon`: an administrator-only explicit defeat and normal restart for an active round. See [recovery policy](recovery.md).
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Current development status
|
||||
|
||||
Evidence checkpoint: 19 September 2026, through archived run `080058`. Later running tests are not included. The primary deliverable is an independently authored replacement for the abandoned Escapists base mission, with the existing companion behavior integrated through its interfaces. The first release targets vanilla Everon and up to twelve players. It must complete prison → scavenging/intel → radio defence → helicopter extraction without the original mod or dependent extensions loaded.
|
||||
|
||||
The successor has its own five addon projects, scenario/resource identities, authored Everon sites and vanilla asset references. The base loop and several failure paths have passed scripted local Workbench checkpoints. This is a development implementation, not a released or fully accepted replacement. [Acceptance](acceptance.json) remains pending for manual gameplay, real multiplayer, performance and release qualification.
|
||||
|
||||
## Established development checkpoints
|
||||
|
||||
| Area | What the recorded evidence establishes | Important limit |
|
||||
| --- | --- | --- |
|
||||
| Independent base loop | Core-only and companion-loaded scripted escape, interrupted radio defence, extraction, defeat and restart have completed. Native task details and personal result widgets have focused lifecycle checks. | Historical runs exercise their recorded sources; they do not qualify later changes or manual play. See [validation](validation.md). |
|
||||
| Prison, equipment and medicine | [Prisoner fixture](evidence/native-2026-09-19-063949/report.json) places one controlled player and eleven physical characters inside the prison, verifies explicit starter inventory and real clue transfers. [Medical fixture](evidence/native-2026-09-19-062406/report.json) demonstrates blood-loss treatment, consumed supplies and native consciousness recovery. | These are not twelve connected clients or ordinary treatment input/animation tests. Five initial pistols are a balance choice to evaluate in play; the count alone is not a demonstrated defect. |
|
||||
| Scavenging and discovery | Finite stock/lost containers remain depleted; two independent clue caches support progression. [Document-loss fixture](evidence/native-2026-09-19-071654/report.json) verifies close physical radio discovery after partial knowledge and loss of all documents. | Manual route visibility, travel, inventory interaction and threat balance remain unqualified. |
|
||||
| Player lifecycle and extraction | Native admission/finalization, local observer cleanup, physical helicopter seat capacity and identity-based results have focused checks. [Recovery fixture](evidence/native-2026-09-19-064406/report.json) preserves incapacitated survivors and verifies explicit authorized abandonment. | [Casualty-loading fixture](evidence/native-2026-09-19-075514/report.json) now loads the real local incapacitated player from the ground into a reserved bench and releases the reservation. Its helper identity is synthetic; remote reconnect and two-client rescue remain unproved. |
|
||||
| Existing physical forces | [Patrol fixture](evidence/native-2026-09-19-070919/report.json) demonstrates real cyclic movement. [Companion fixture](evidence/native-2026-09-19-072838/report.json) verifies HQ Search preemption and physical patrol resumption without creating response forces. [Cancellation fixture](evidence/native-2026-09-19-073601/report.json) verifies stopped incomplete groups do not dispatch late members. | The delivered-order patrol test bypasses radio transit. Broader reports, combat, support and losses need integrated qualification. |
|
||||
| Environment and native errors | [Environment/restart fixture](evidence/native-2026-09-19-065351/report.json) passes two real rounds with zero native errors after restricting vehicle catalogs to required assets. | Earlier vehicle-schema errors are historical, not evidence every current run fails. Intermittent medical-kit teardown attribution remains unresolved; a later [full-loop checkpoint](evidence/native-2026-09-19-073806/report.json) also passes two rounds without native errors. Subsequent initial-placement changes still need their own qualification. |
|
||||
|
||||
## Immediate blockers and next work
|
||||
|
||||
1. **Resolve the remaining ordinary-game errors and establish player admission.** The [scenario-header launch](evidence/game-2026-09-19-080004/report.json) compiles production Game without WORKBENCH/ENF_WB, verifies the Core header and vanilla MissionSystems, and reaches `phase 0 -> 1` without the earlier guard-spawn crash being captured. It remains a failed run: vanilla splash `SCR_WidgetExportRuleRoot` errors persist and the local player's identity cannot be bound, so spawning is withheld. Preserve identity validation while diagnosing the offline launch/admission path. This is partial startup evidence, not clean startup or a playable session. [Runner details](ordinary-game-startup.md).
|
||||
2. **Qualify casualty loading beyond the local success.** [075514](evidence/native-2026-09-19-075514/report.json) passes the complete local service fixture with no native errors: naturally settled helicopter, actual incapacitation, completion-time authorization, external reservations, blocked sight, one owner-handshake load into the selected bench, identity retention and cleanup. Earlier parked-contact and fixture-damage failures remain archived. [Stock removal fixture](evidence/native-2026-09-19-080058/report.json) also verifies the inherited door action clears the bench and leaves a living incapacitated body beside its authored exit. Real action input, remote ownership/RPC timing, competing rescuers, disconnect/death during a pending load and entity-deletion cleanup still need their own tests. [Casualty service](casualty-loading.md), [support investigation](casualty-ground-support.md).
|
||||
3. **Rerun the current integrated base and companions.** Guard cancellation and replicated radio feedback have clean evidence from [two complete Core rounds](evidence/native-2026-09-19-073806/report.json); the later placement/casualty changes now have a focused local pass. A full current-source escape/restart regression must still exercise those changes together with discovery/task presentation, ordinary victory, early aircraft loss, death and abandonment. Keep failed iterations and source/log provenance; do not substitute earlier clean snapshots.
|
||||
|
||||
4. **Play the complete route with ordinary input.** Validate prison gate/equipment access, scavenging and medical interactions, finding the radio without fixture knowledge, defend/recover behavior, ground-vehicle route, manual helicopter boarding/takeoff/navigation and partial escape. Tune the authored layout and finite supplies from actual play. The implemented all-incapacitated policy is preserved vanilla recovery plus explicit administrator abandonment; no automatic recovery is promised.
|
||||
5. **Finish and qualify physical HQ support.** Infantry observation/report/order paths and patrol integration exist. Operational mortar firing, aircraft support, transport/rearming and depot/logistics behavior remain incomplete. Preserve a single HQ coordinator, radio-delivered reports, finite physical forces/ammunition and loss retention; cover interrupted reports, stale contacts and duplicate-order prevention. The [responsibility inventory](original-feature-coverage.md) remains a scope map, not behavioral proof.
|
||||
|
||||
## First-release qualification still required
|
||||
|
||||
Establish a dedicated-server test environment and real clients, then cover concurrent/late joins in each phase, preload cancellation, reconnect and connection-ID reuse, reserved bodies, spent lives, death/unconsciousness/treatment, spectators and streaming cleanup. Verify remote task/map/radio/result updates, settings authorization, seat contention, partial escape, empty-server behavior, defeat and repeated restart with up to twelve connected players. Local fixtures narrow these risks but do not close them.
|
||||
|
||||
Collect real matched original/successor workloads with repeated client-frame and server-tick recordings. No FPS improvement has been demonstrated; the [comparison tool](performance-comparison.md) currently has synthetic regression evidence only.
|
||||
|
||||
Finally complete provenance/dependency review, build and test the package under the successor's own identities, and satisfy the [release checker](release-qualification.md) with current source-bound evidence. No release package has been published. RHS, additional terrains, complete original parity, alternate starts and distant-unit simulation remain later scope.
|
||||
|
||||
Older audits such as [base gameplay gaps](base-gameplay-gaps.md) preserve findings made before subsequent implementations. Read their update notes and linked native evidence before treating an old missing-feature statement as a current defect. This status page consolidates priorities; the evidence ledger remains authoritative for individual recorded checks.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Native next-round environment fixture
|
||||
|
||||
`--project core --smoke environment-restart --rounds 2` is a bounded, opt-in check of two actual `ERR_GameMode` initializations. Use the existing private Workbench profile and headless runner. This is a native script fixture, not manual or multiplayer acceptance.
|
||||
|
||||
Production adds only `protected string SettingsPath()` with the unchanged `ERR_Settings.PATH` default; the constructor uses that path. A WORKBENCH-only override selects `$profile:erri-environment-restart.json` only when both `errBaseSmoke=1` and `errSmokeOutcome=environment-restart` are present. All other runs retain the production path. The probe records the authored environment before normal service startup; it never substitutes a sample environment service or edits normal `rereintroduced.json`.
|
||||
|
||||
The runner refuses any existing fixture settings, `.bak`, `.tmp`, or `erri-environment-restart-round.json` marker, including broken symlinks. It requires exactly two Core rounds. Round one checks authored defaults and original 14:00 / 1x clock defaults, saves 2000-02-29 and overcast through the real mode settings owner and production environment command helper, reloads the private file to verify persistence, and waits 2.5 seconds. The active environment must remain authored while the native clock advances at its original rate. Only after these assertions does it write a round-one completion marker and request the ordinary test defeat/reset.
|
||||
|
||||
The next real mode initialization opens the same file through the production settings constructor. Its ordinary environment service must record the saved date/profile and apply the exact leap date plus native `Overcast` family. Another 2.5 seconds proves continuing clock progression. Successful round two deletes only the fixture settings/backup/temp/marker and verifies their absence. Failures leave fixture evidence untouched for diagnosis; preserve or move that evidence before rerunning. The persistent marker is for this explicit runner workflow; it does not authenticate arbitrary files supplied outside it. No general settings-path CLI has been introduced.
|
||||
|
||||
The assertion compares authored weather across a short first-round interval; an authored weather transition coinciding with that interval could require investigation rather than indicating a settings mutation. Second-round weather uses the production forced family and loops normally. Clock rate checks do not benchmark simulation performance or prove remote replication.
|
||||
|
||||
## Integration
|
||||
|
||||
Copy the new `ERR_NativeEnvironmentRestartProbe.c`, this document, and `tests/test_environment_restart_runner.py`. Apply `environment-restart-integration.patch` to `ERR_GameMode.c`, `ERR_NativeBaseSmoke.c`, `tools/headless_workbench.py`, and `tools/check.py`. The patch is based on current central sources containing `casualty-bench` and `environment`; other outcomes remain unchanged.
|
||||
|
||||
The smoke uses steps 1200/1202. Its probe is created before settings loading by the WORKBENCH path override, then polled by the ordinary Core smoke loop after the real prisoner exists. Both rounds use existing explicit defeat/reset behavior. `OnStop` stops the probe without deleting failure evidence. No normal player health or lifecycle is changed by this fixture.
|
||||
|
||||
Run `python3 tools/check.py` for repository policy checks and runner refusal tests. Native compile, two-round execution, and archive provenance are still required before claiming this fixture passed.
|
||||
|
||||
Native evidence `native-2026-09-19-065351` passes both real rounds, 107 combined assertions, with zero engine or script errors. The private fixture files were removed by successful round two. This proves the described local persistence path and retains the limits above.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Round date and weather
|
||||
|
||||
Core's `ERR_EnvironmentService` applies optional date and weather selections once during server-side round preparation, immediately before the existing clock service. The native time/weather manager owns simulation and replication. There is no environment tick, local preview, player-health modification or periodic reset. Repeated starts retain the initial selection; a stopped service cannot restart.
|
||||
|
||||
Defaults preserve the authored world. Old valid settings files without `startDateCode` and `weatherProfile` acquire zero values in memory, are not rewritten during loading, and retain every existing supported value. An explicit successful save writes the expanded schema using the existing validated temporary-file/backup flow. Present invalid environment values reject the file rather than silently defaulting.
|
||||
|
||||
Administrators use:
|
||||
|
||||
- `/esc mission date show` and `/esc mission date set YYYY-MM-DD` (1900–2050 inclusive), or `set authored`.
|
||||
- `/esc mission weather show` and `/esc mission weather set authored|clear|overcast|rain` (`rainy` is accepted as an alias).
|
||||
|
||||
These commands save next-round choices. They report the current native environment separately and do not apply saved changes to the running world. Date validation covers month lengths and Gregorian leap years, including non-leap 1900 and leap 2000. The native manager also validates an explicit date before applying it.
|
||||
|
||||
`weatherProfile` values are 0 authored, 1 Clear, 2 Overcast and 3 Rainy. An explicit profile uses the native replicated `ForceWeatherTo` route and loops that weather family. The service validates that the named vanilla state and transition manager exist before changing the date or issuing a request. It verifies the requested current/next state and looping flag. On rejection it attempts to restore the previous date and weather family/looping before startup reports failure. This is not a snapshot of every native transition queue or variant parameter. No UI preview API is used.
|
||||
|
||||
A fixed profile selects a family deterministically; cloud variants, wind and other native weather behavior still follow vanilla rules. Existing authored wind/fog overrides are retained. The `authored` setting makes no weather request and preserves the scenario's original weather evolution. Visual intensity, remote replication, manual visibility and long-running transitions still require runtime acceptance.
|
||||
|
||||
`startDateCode` is an internal compact integer: `(year - 1900) * 10000 + month * 100 + day`, with 0 meaning authored. For example, 1989-06-01 is 890601. It intentionally stays below 1,501,232, exactly representable by the existing settings reader's floating-point JSON path. A full `YYYYMMDD` number can exceed single-precision exact integer range and corrupt odd dates. Use the natural date command rather than constructing codes by hand.
|
||||
|
||||
## Validation
|
||||
|
||||
`tests/test_environment_policy.py` executes the actual settings validator and production parsing/formatting functions through the existing C++ policy harness. It compares calendar boundary cases across every supported year against Python's independent `datetime` calendar, tests malformed dates and names, and checks defaults and native family names. Existing migration tests cover the added defaults and bounds. These checks pass; they are not Enforce compilation.
|
||||
|
||||
The opt-in WORKBENCH `ERR_NativeEnvironmentProbe` uses a dedicated test settings file, preserving the actual mission settings. It tests legacy loading without rewrite, exact odd date-code serialization, save rejection, unauthorized commands, next-round command behavior and no world mutation from saves. It then temporarily uses fresh service instances to select Clear, Overcast and Rainy with explicit/leap/authored dates, waiting at least one 500ms smoke tick per state. It verifies start idempotency, stopped-service rejection and unchanged clock/progression settings. Before completing it restores the original date, weather family and looping mode. Native transition-queue timing and cloud-variant history are not restored exactly; this is an isolated case that ends with a test-requested round reset. Native compilation and execution remain pending centralized hidden and muted testing.
|
||||
|
||||
## Native evidence
|
||||
|
||||
[063559](evidence/native-2026-09-19-063559/report.json) completed 67 combined environment/catalog assertions with no script/VM failures and no engine errors. Exact native catalogs retained medical and radio entries; all three weather families and a leap date applied without resetting the clock. Defaults and next-round settings behavior were exercised. This one-round development result does not establish multiplayer replication or repeated-restart reliability.
|
||||
@@ -0,0 +1,102 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-26-09\console.log started at 2026-09-19 07:26:09 (2026-09-19 05:26:09 UTC)
|
||||
|
||||
07:26:09.124 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-26-09' to filesystem under name logs
|
||||
07:26:09.125 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\profile' to filesystem under name profile
|
||||
07:26:09.125 ENGINE : FileSystem: Current working directory: 'Z:\home\jakub\.local\share\Steam\steamapps\common\Arma Reforger\'
|
||||
07:26:09.126 ENGINE : Initializing engine, version 192142
|
||||
07:26:09.126 ENGINE : CLI Params: -addonsDir Z:/home/jakub/devel/escapistsrereintroduced/addons -addons 2528466DE220D91C -profile Z:/tmp/erri-game-profile -world Worlds/ERR_Everon.ent -noBackend -noSound -noSplash -noThrow -logconsole
|
||||
07:26:09.135 ENGINE : Addon dirs:
|
||||
07:26:09.135 ENGINE : dir: 'Z:/home/jakub/devel/escapistsrereintroduced/addons'
|
||||
07:26:09.135 ENGINE : dir: './addons'
|
||||
07:26:09.135 ENGINE : dir: 'Z:/tmp/erri-game-profile/addons'
|
||||
07:26:09.135 ENGINE : Available addons:
|
||||
07:26:09.135 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/ai/addon.gproj' guid: '5192138CB9D5B911'
|
||||
07:26:09.135 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/chat/addon.gproj' guid: 'FA804F411BDDF2C6'
|
||||
07:26:09.135 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:26:09.135 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/intel/addon.gproj' guid: 'D31039C7C53E348A'
|
||||
07:26:09.135 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/map/addon.gproj' guid: '9AAEE9041D79809E'
|
||||
07:26:09.135 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C' (packed)
|
||||
07:26:09.135 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859' (packed)
|
||||
07:26:09.136 ENGINE : FileSystem: Adding relative directory 'Z:\home\jakub\devel\escapistsrereintroduced\addons\core' to filesystem under name ERR_Core
|
||||
07:26:09.263 ENGINE : FileSystem: Adding package './addons/data/' (pak count: 14) to filesystem under name ArmaReforger
|
||||
07:26:09.266 ENGINE : FileSystem: Adding package './addons/core/' (pak count: 2) to filesystem under name core
|
||||
07:26:09.266 ENGINE : CPU vendor : AuthenticAMD
|
||||
07:26:09.266 ENGINE : CPU type : 2
|
||||
07:26:09.266 ENGINE : CPU name : AMD Ryzen 7 3800XT 8-Core Processor
|
||||
07:26:09.266 ENGINE : CPU cache info : L1 [Inst 32KB, Data 32KB], L2 [Unif 512KB], L3 [Unif 16384KB]
|
||||
07:26:09.266 ENGINE : CPU count logical : 16
|
||||
07:26:09.266 ENGINE : CPU count physical : 8
|
||||
07:26:09.266 ENGINE : CPU features : mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcnt aesni pclmulqdq osxsave avx sha avx2
|
||||
07:26:09.266 RESOURCES : ResourceDB: loading cache (id=0 name=ERR_Core path=Z:\home\jakub\devel\escapistsrereintroduced\addons\core/resourceDatabase.rdb)
|
||||
07:26:09.267 RESOURCES : ResourceDB: loading cache (id=1 name=ArmaReforger path=./addons/data/resourceDatabase.rdb)
|
||||
07:26:09.403 RESOURCES : ResourceDB: loading cache (id=2 name=core path=./addons/core/resourceDatabase.rdb)
|
||||
07:26:09.404 RESOURCES : ResourceDB: loading cache (id=3 name=profile path=Z:\tmp\erri-game-profile\profile/resourceDatabase.rdb)
|
||||
07:26:09.404 RESOURCES : ResourceDB: loading cache (id=4 name=logs path=Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-26-09/resourceDatabase.rdb)
|
||||
07:26:09.555 ENGINE : GameProject load
|
||||
07:26:09.555 ENGINE : Loaded addons:
|
||||
07:26:09.555 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C'
|
||||
07:26:09.555 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859'
|
||||
07:26:09.555 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:26:09.557 ENGINE : Loading custom engine user config '$profile:.save/app1874880_user76561198020202999/settings/ReforgerEngineSettings.conf'
|
||||
07:26:09.558 ENGINE : No Enfusion settings file loaded. Continuing with defaults
|
||||
07:26:09.558 ENGINE : Locale info: system en-US (English), user en-US (English)
|
||||
07:26:09.684 RENDER : (OK) Adapter 'AMD Radeon RX 6950 XT (RADV NAVI21)' supports feature level 12_0
|
||||
07:26:09.686 RENDER : Basic screen setup:
|
||||
07:26:09.686 RENDER : Back buffer width x height: 1280x720
|
||||
07:26:09.686 RENDER : Back buffer format : TEXFMT_R8G8B8A8_SRGB (29)
|
||||
07:26:09.686 RENDER : MSAA : none
|
||||
07:26:09.701 RENDER : AMD AGS library initialized, version 6.1.0 x DLL 6.1.0
|
||||
07:26:09.701 RENDER : Extendeded AMD info for AMD Radeon RX 6950 XT (RADV NAVI21) (primary device)
|
||||
07:26:09.701 RENDER : * architecture RDNA2, 80 CUs, 40 WGPs (for RDNA), 64 ROPs
|
||||
07:26:09.701 RENDER : * core clocks 2720 MHz, memory 1124 MHz
|
||||
07:26:09.701 RENDER : * TFlops 27.9, memory bandwidth (562.0 GB/s)
|
||||
07:26:09.701 RENDER : AMD AGS correctly initialized
|
||||
07:26:09.702 RENDER : GPU_ATI (0x1002) (AMD Radeon RX 6950 XT (RADV NAVI21)) with 1 GPU detected, VRAM 16128MB (fast 0MB), shared 64362MB, driver version 99.19.02-230831a-396538C-AMD-Software-Adrenalin-Edition
|
||||
07:26:09.702 RENDER : Detected output devices:
|
||||
07:26:09.702 RENDER : * 1 device/s connected to AMD Radeon RX 6950 XT (RADV NAVI21):
|
||||
07:26:09.702 RENDER : Generic Non-PnP Monitor (\\.\DISPLAY1), 1280x720 (offset 0x0), 30Hz
|
||||
07:26:09.702 RENDER : Concurrent frames limit 2
|
||||
07:26:09.784 RENDER : DX12 device successfully created by AMD AGS library
|
||||
07:26:09.784 RENDER : * user markers not supported in this version AMD SW
|
||||
07:26:09.784 RENDER : Graphics device features
|
||||
07:26:09.784 RENDER : Needed:
|
||||
07:26:09.784 RENDER : * Highest supported shader model: 6.8 (6.0 needed)
|
||||
07:26:09.784 RENDER : Optional:
|
||||
07:26:09.784 RENDER : * Allow tearing (VSYNC) : 1
|
||||
07:26:09.784 RENDER : * 16 bits : 1
|
||||
07:26:09.784 RENDER : * Resource heap tier : 3
|
||||
07:26:09.784 RENDER : * Persistent heaps (DRED) : 1
|
||||
07:26:09.784 RENDER : * DRED 1.2 is supported by compiler
|
||||
07:26:09.805 RENDER : Main RT format setup.
|
||||
07:26:09.805 RENDER : Main RT format for quality 0 : TEXFMT_R11G11B10_FLOAT (26)
|
||||
07:26:09.805 RENDER : Main RT format for quality 1 : TEXFMT_R16G16B16A16_FLOAT (10)
|
||||
07:26:09.810 ENGINE : Job system settings: coreCount=16, shortJobContextCount=16, shortJobThreadCount=15, longJobThreadCount=7
|
||||
07:26:09.839 PROFILING : Settings changed took: 0.951700 ms
|
||||
07:26:09.847 RENDER : RENDER : Reload shaders
|
||||
07:26:09.847 RENDER : Enfusion shader version 13
|
||||
07:26:09.847 INIT : INIT : ShaderListReload
|
||||
07:26:09.847 PROFILING : ShaderListReload took: 0.000400 ms
|
||||
07:26:10.125 RENDER : Loaded 3752 newer shader binaries
|
||||
07:26:10.125 PROFILING : Reload shaders took: 278.518900 ms
|
||||
07:26:10.132 ENGINE : Initializing inputs.
|
||||
07:26:10.146 NETWORK : Initializing networking.
|
||||
07:26:10.146 NETWORK : Using new GameRplScheduler.
|
||||
07:26:10.146 SCRIPT : SCRIPT : Initializing scripts
|
||||
07:26:10.146 SCRIPT : SCRIPT : ScriptProjectManager init
|
||||
07:26:10.146 PROFILING : ScriptProjectManager init took: 0.026000 ms
|
||||
07:26:10.182 PROFILING : Initializing scripts took: 35.078400 ms
|
||||
07:26:10.182 BACKEND : Backend Services are disabled.
|
||||
07:26:10.182 ENGINE : Enfusion engine successfully created.
|
||||
07:26:10.195 DEFAULT (W): LogiLED: Cannot initialize! (service not running or no compatible device detected)
|
||||
07:26:10.222 GUI : Using default language (en_us)
|
||||
07:26:10.222 GUI : Loading 'en_us' localization file.
|
||||
07:26:10.222 INIT : INIT : Loading StringTable
|
||||
07:26:10.255 PROFILING : Loading StringTable took: 33.142300 ms
|
||||
07:26:10.255 SCRIPT : SCRIPT : Compiling GameLib scripts
|
||||
07:26:10.307 SCRIPT : Module: GameLib; loaded 465x files; 607x classes; used 775K of static memory; defines: "ENF_WB,PLATFORM_WINDOWS,ENABLE_DIAG,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: 4507af04
|
||||
07:26:10.307 PROFILING : Compiling GameLib scripts took: 52.687700 ms
|
||||
07:26:10.308 RESOURCES : GetResourceObject @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:26:10.308 GUI : Layout load @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:26:10.308 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)
|
||||
07:26:10.402 SCRIPT : SCRIPT : Compiling Game scripts
|
||||
@@ -0,0 +1,7 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-26-09\error.log started at 2026-09-19 07:26:10 (2026-09-19 05:26:10 UTC)
|
||||
|
||||
07:26:10.195 DEFAULT (W): LogiLED: Cannot initialize! (service not running or no compatible device detected)
|
||||
07:26:10.308 RESOURCES : GetResourceObject @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:26:10.308 GUI : Layout load @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:26:10.308 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"log": "console.log",
|
||||
"smoke_completions": 0,
|
||||
"assertions_passed": 0,
|
||||
"script_or_runtime_failures": [],
|
||||
"engine_errors": [
|
||||
"07:26:10.308 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)"
|
||||
],
|
||||
"missing_end_screen": [],
|
||||
"scope": "ordinary local game startup only; no player input, full escape, multiplayer or FPS proof",
|
||||
"game_module_defines": [],
|
||||
"workbench_undefined": false,
|
||||
"normal_mission_ready": false,
|
||||
"unexpected_smoke_fixture": false,
|
||||
"failed": true,
|
||||
"ready": false
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mconsole:[0m gamescope version 3.16.28 (gcc 16.2.1)
|
||||
No CAP_SYS_NICE, falling back to regular-priority compute and threads.
|
||||
Performance will be affected.
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope/common'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/inspect.lua' (id: 0)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/modegen.lua' (id: 1)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/util.lua' (id: 2)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope/displays'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/asus.rogally.lcd.lua' (id: 3)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua' (id: 4)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/gpd.win4.lcd.lua' (id: 5)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/lenovo.legiongo.lcd.lua' (id: 6)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/lenovo.legiongos.lcd.lua' (id: 7)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/onexplayer.f1.oled.lua' (id: 8)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/valve.steamdeck.lcd.lua' (id: 9)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/valve.steamdeck.oled.lua' (id: 10)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/zotac.zone.oled.lua' (id: 11)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/etc/gamescope/scripts'
|
||||
[gamescope] [[0;33mWarn[0m] [0;37mscriptmgr:[0m Directory '/etc/gamescope/scripts' does not exist
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/home/jakub/.config/gamescope/scripts'
|
||||
[gamescope] [[0;33mWarn[0m] [0;37mscriptmgr:[0m Directory '/home/jakub/.config/gamescope/scripts' does not exist
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m selecting physical device 'AMD Radeon RX 6950 XT (RADV NAVI21)': queue family 1 (general queue family 0)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m physical device supports DRM format modifiers
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [backend/headless/backend.c:60] Creating headless backend
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m supported DRM formats for sampling usage:
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AR24 (0x34325241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XR24 (0x34325258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB24 (0x34324241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB24 (0x34324258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m RG16 (0x36314752)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m NV12 (0x3231564E)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB4H (0x48344241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB4H (0x48344258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB48 (0x38344241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB48 (0x38344258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB30 (0x30334241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB30 (0x30334258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AR30 (0x30335241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XR30 (0x30335258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Using explicit sync when available
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Running compositor on wayland display 'gamescope-0'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [backend/headless/backend.c:17] Starting headless backend
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Successfully initialized libei for input emulation!
|
||||
[gamescope] [[0;31mError[0m] [0;37mwlserver:[0m [xwayland/sockets.c:47] Failed to bind socket @/tmp/.X11-unix/X0: Address already in use
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [xwayland/server.c:108] Starting Xwayland on :2
|
||||
The XKEYBOARD keymap compiler (xkbcomp) reports:
|
||||
> Warning: Multiple symbols for level 1/group 1 on key <FK23>
|
||||
> Using F23, ignoring XF86TouchpadOff
|
||||
> Warning: Symbol map for key <FK23> redefined
|
||||
> Using last definition for conflicting fields
|
||||
> Warning: Symbol map for key <FK24> redefined
|
||||
> Using last definition for conflicting fields
|
||||
> Warning: Could not resolve keysym XF86ElectronicPrivacyScreenOn
|
||||
> Warning: Could not resolve keysym XF86ElectronicPrivacyScreenOff
|
||||
> Warning: Could not resolve keysym XF86ActionOnSelection
|
||||
> Warning: Could not resolve keysym XF86ContextualInsert
|
||||
> Warning: Could not resolve keysym XF86ContextualQuery
|
||||
Errors from xkbcomp are not fatal to the X server
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream state changed: connecting
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream state changed: paused
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream available on node ID: 123
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvblank:[0m Using timerfd.
|
||||
fsync: up and running.
|
||||
[Gamescope WSI] No application info given.
|
||||
[Gamescope WSI] Executable name: explorer.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: xalia.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: DXVK
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Executable name: xalia.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] No application info given.
|
||||
The XKEYBOARD keymap compiler (xkbcomp) reports:
|
||||
> Warning: Unsupported maximum keycode 709, clipping.
|
||||
> X11 cannot support keycodes above 255.
|
||||
> Warning: Virtual modifier Hyper multiply defined
|
||||
> Using 0, ignoring 0
|
||||
> Warning: Virtual modifier ScrollLock multiply defined
|
||||
> Using 0, ignoring 0
|
||||
Errors from xkbcomp are not fatal to the X server
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteamDiag.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: DXVK
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Executable name: ArmaReforgerSteamDiag.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: (null)
|
||||
applicationVersion: 0
|
||||
pEngineName: (null)
|
||||
engineVersion: 0
|
||||
apiVersion: 4198400
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteamDiag.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: vkd3d
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Forcing on VK_EXT_swapchain_maintenance1.
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: (null)
|
||||
applicationVersion: 0
|
||||
pEngineName: (null)
|
||||
engineVersion: 0
|
||||
apiVersion: 4198400
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteamDiag.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: vkd3d
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Forcing on VK_EXT_swapchain_maintenance1.
|
||||
[Gamescope WSI] Creating Gamescope surface: xid: 0x1a00030
|
||||
[Gamescope WSI] Atom of T was wrong type. Expected XCB_ATOM_CARDINAL.
|
||||
[Gamescope WSI] Made gamescope surface for xid: 0x1a00030
|
||||
[Gamescope WSI] Surface state:
|
||||
steam app id: 1874880
|
||||
window xid: 0x1a00030
|
||||
wayland surface res id: 5
|
||||
layer client flags: 0x4
|
||||
server hdr output enabled: false
|
||||
hdr formats exposed to client: false
|
||||
[Gamescope WSI] Creating swapchain for xid: 0x1a00030 - oldSwapchain: (nil) - provided minImageCount: 3 - minImageCount: 3 - format: VK_FORMAT_R8G8B8A8_UNORM - colorspace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - flip: true
|
||||
[Gamescope WSI] Created swapchain for xid: 0x1a00030 swapchain: 0x7f50b01848f0 - imageCount: 3
|
||||
[Gamescope WSI] Destroying swapchain: 0x7f50b01848f0
|
||||
[Gamescope WSI] Destroyed swapchain: 0x7f50b01848f0
|
||||
[Gamescope WSI] Creating swapchain for xid: 0x1a00030 - oldSwapchain: (nil) - provided minImageCount: 3 - minImageCount: 3 - format: VK_FORMAT_R8G8B8A8_UNORM - colorspace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - flip: true
|
||||
[Gamescope WSI] Created swapchain for xid: 0x1a00030 swapchain: 0x7f50b01848f0 - imageCount: 3
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mlaunch:[0m Primary child shut down!
|
||||
(EE) failed to read Wayland events: Broken pipe
|
||||
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"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": "0b954c856cfee9b5dbb6241a5001726ca6940c885f968c2ed60a84264be7a1f4",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "657e96d1112b68c8ced37793e99f88e6078b38a579190e63d00b1f9a9a032e26",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "12d8fc39d47e03c3838e0642aa9e4a80baf60f250357493bff812d5c75812c86",
|
||||
"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/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": "becf85c5d1eb31d6bd480e9854aaab426118ad81b7a01f549314668d29216bae",
|
||||
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
|
||||
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
|
||||
"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_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c": "9bd789f4147dc2d309c9f92b1eddd33fd1e57d119defb97076a5d8cab2c570fb",
|
||||
"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_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "bce62ce70df26ed527375537faa7cfa0dee252ac89bac5ba3af1b2f3d3e3dbb1",
|
||||
"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_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": "1b67af6c72006a4bfed733d1809bb624254422fdde1b618168540c1d73883b60",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "c14e7386fb0ddc3514091e33c9eda56ac1540f30e18d283744ccfd25999605fe",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "dd7bdaca65a6207df5aaa140b6d3fde7867097c3fcfb6ded802163f895691f3f",
|
||||
"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": "599f4552893619f486e15032b393c48022e5b59afe50b93d658e7e7f4b93964f",
|
||||
"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": "c8a8ca5c79b00f06f58846e8bfccf95471eb2aa94ce30a5bd2002af9b4879050",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
|
||||
"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_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": "1f5f03628123331a091f52731717075821e024a86feef977777a8036f8922989",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "64c2cef62d8a435eea396f057255b269d457935bf5d261221700739bf37240b8",
|
||||
"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/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/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
|
||||
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"launch_id": "91412604-1c31-433f-a8b1-715ccae76ee6",
|
||||
"captured_unix": 1789795567.4900296,
|
||||
"source_root": "/home/jakub/devel/escapistsrereintroduced",
|
||||
"command": [
|
||||
"gamescope",
|
||||
"--backend",
|
||||
"headless",
|
||||
"-W",
|
||||
"1280",
|
||||
"-H",
|
||||
"720",
|
||||
"-w",
|
||||
"1280",
|
||||
"-h",
|
||||
"720",
|
||||
"-r",
|
||||
"30",
|
||||
"--",
|
||||
"/home/jakub/.local/share/Steam/steamapps/common/Proton - Experimental/proton",
|
||||
"run",
|
||||
"/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/ArmaReforgerSteamDiag.exe",
|
||||
"-addonsDir",
|
||||
"Z:/home/jakub/devel/escapistsrereintroduced/addons",
|
||||
"-addons",
|
||||
"2528466DE220D91C",
|
||||
"-profile",
|
||||
"Z:/tmp/erri-game-profile",
|
||||
"-world",
|
||||
"Worlds/ERR_Everon.ent",
|
||||
"-noBackend",
|
||||
"-noSound",
|
||||
"-noSplash",
|
||||
"-noThrow",
|
||||
"-logconsole"
|
||||
],
|
||||
"manifest_sha256": "0cb5587a12ddea89f35d448d6e46f34401a2c57e07700524b07464dcbc78787c"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"log": "docs/evidence/game-2026-09-19-072609/console.log.txt",
|
||||
"smoke_completions": 0,
|
||||
"assertions_passed": 0,
|
||||
"script_or_runtime_failures": [],
|
||||
"engine_errors": [
|
||||
"07:26:10.308 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)"
|
||||
],
|
||||
"missing_end_screen": [],
|
||||
"scope": "scripted local Workbench integration only; no multiplayer, piloting or FPS claim"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"stopped_unix": 1789795570.8475714,
|
||||
"console_sha256": "3865e9c521fece25525addae9e541ec3fc3d23cd3a0a9959278f00571c54c17e",
|
||||
"end_source_sha256": "0cb5587a12ddea89f35d448d6e46f34401a2c57e07700524b07464dcbc78787c",
|
||||
"source_unchanged_after_run": true,
|
||||
"source_provenance": "launch_snapshot",
|
||||
"launch_id": "91412604-1c31-433f-a8b1-715ccae76ee6",
|
||||
"launch_source_manifest": "launch-source-sha256.json",
|
||||
"launch_source_metadata": "launch-source.json",
|
||||
"launch_source_sha256": "0cb5587a12ddea89f35d448d6e46f34401a2c57e07700524b07464dcbc78787c",
|
||||
"started_unix": 1789795567.4901152,
|
||||
"result": "game-failed",
|
||||
"session": "/tmp/erri-game-profile/logs/logs_2026-09-19_07-26-09",
|
||||
"project": "core",
|
||||
"cleanup_confirmed": true,
|
||||
"runner_error": null,
|
||||
"executable": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/ArmaReforgerSteamDiag.exe",
|
||||
"dedicated_server": false,
|
||||
"display": "headless Gamescope",
|
||||
"audio": "-noSound plus own silent sink",
|
||||
"scope": "ordinary game compile/startup; no scripted fixture, full escape or multiplayer acceptance"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-26-09\script.log started at 2026-09-19 07:26:10 (2026-09-19 05:26:10 UTC)
|
||||
|
||||
07:26:10.146 SCRIPT : SCRIPT : Initializing scripts
|
||||
07:26:10.146 SCRIPT : SCRIPT : ScriptProjectManager init
|
||||
07:26:10.255 SCRIPT : SCRIPT : Compiling GameLib scripts
|
||||
07:26:10.307 SCRIPT : Module: GameLib; loaded 465x files; 607x classes; used 775K of static memory; defines: "ENF_WB,PLATFORM_WINDOWS,ENABLE_DIAG,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: 4507af04
|
||||
07:26:10.402 SCRIPT : SCRIPT : Compiling Game scripts
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"kind": "launch_snapshot"
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"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": "0b954c856cfee9b5dbb6241a5001726ca6940c885f968c2ed60a84264be7a1f4",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "657e96d1112b68c8ced37793e99f88e6078b38a579190e63d00b1f9a9a032e26",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "12d8fc39d47e03c3838e0642aa9e4a80baf60f250357493bff812d5c75812c86",
|
||||
"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/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": "becf85c5d1eb31d6bd480e9854aaab426118ad81b7a01f549314668d29216bae",
|
||||
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
|
||||
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
|
||||
"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_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c": "9bd789f4147dc2d309c9f92b1eddd33fd1e57d119defb97076a5d8cab2c570fb",
|
||||
"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_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "bce62ce70df26ed527375537faa7cfa0dee252ac89bac5ba3af1b2f3d3e3dbb1",
|
||||
"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_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": "1b67af6c72006a4bfed733d1809bb624254422fdde1b618168540c1d73883b60",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "c14e7386fb0ddc3514091e33c9eda56ac1540f30e18d283744ccfd25999605fe",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "dd7bdaca65a6207df5aaa140b6d3fde7867097c3fcfb6ded802163f895691f3f",
|
||||
"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": "599f4552893619f486e15032b393c48022e5b59afe50b93d658e7e7f4b93964f",
|
||||
"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": "c8a8ca5c79b00f06f58846e8bfccf95471eb2aa94ce30a5bd2002af9b4879050",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
|
||||
"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_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": "1f5f03628123331a091f52731717075821e024a86feef977777a8036f8922989",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "64c2cef62d8a435eea396f057255b269d457935bf5d261221700739bf37240b8",
|
||||
"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/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/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
|
||||
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-32-31\console.log started at 2026-09-19 07:32:31 (2026-09-19 05:32:31 UTC)
|
||||
|
||||
07:32:31.136 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-32-31' to filesystem under name logs
|
||||
07:32:31.136 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\profile' to filesystem under name profile
|
||||
07:32:31.136 ENGINE : FileSystem: Current working directory: 'Z:\home\jakub\.local\share\Steam\steamapps\common\Arma Reforger\'
|
||||
07:32:31.137 ENGINE : Initializing engine, version 192142
|
||||
07:32:31.137 ENGINE : CLI Params: -addonsDir Z:/home/jakub/devel/escapistsrereintroduced/addons -addons 2528466DE220D91C -profile Z:/tmp/erri-game-profile -world Worlds/ERR_Everon.ent -noBackend -noSound -noSplash -noThrow -logconsole
|
||||
07:32:31.144 ENGINE : Addon dirs:
|
||||
07:32:31.144 ENGINE : dir: 'Z:/home/jakub/devel/escapistsrereintroduced/addons'
|
||||
07:32:31.144 ENGINE : dir: './addons'
|
||||
07:32:31.144 ENGINE : dir: 'Z:/tmp/erri-game-profile/addons'
|
||||
07:32:31.144 ENGINE : Available addons:
|
||||
07:32:31.144 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/ai/addon.gproj' guid: '5192138CB9D5B911'
|
||||
07:32:31.144 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/chat/addon.gproj' guid: 'FA804F411BDDF2C6'
|
||||
07:32:31.144 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:32:31.144 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/intel/addon.gproj' guid: 'D31039C7C53E348A'
|
||||
07:32:31.144 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/map/addon.gproj' guid: '9AAEE9041D79809E'
|
||||
07:32:31.144 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C' (packed)
|
||||
07:32:31.144 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859' (packed)
|
||||
07:32:31.145 ENGINE : FileSystem: Adding relative directory 'Z:\home\jakub\devel\escapistsrereintroduced\addons\core' to filesystem under name ERR_Core
|
||||
07:32:31.302 ENGINE : FileSystem: Adding package './addons/data/' (pak count: 14) to filesystem under name ArmaReforger
|
||||
07:32:31.306 ENGINE : FileSystem: Adding package './addons/core/' (pak count: 2) to filesystem under name core
|
||||
07:32:31.306 ENGINE : CPU vendor : AuthenticAMD
|
||||
07:32:31.306 ENGINE : CPU type : 2
|
||||
07:32:31.306 ENGINE : CPU name : AMD Ryzen 7 3800XT 8-Core Processor
|
||||
07:32:31.306 ENGINE : CPU cache info : L1 [Inst 32KB, Data 32KB], L2 [Unif 512KB], L3 [Unif 16384KB]
|
||||
07:32:31.306 ENGINE : CPU count logical : 16
|
||||
07:32:31.306 ENGINE : CPU count physical : 8
|
||||
07:32:31.306 ENGINE : CPU features : mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcnt aesni pclmulqdq osxsave avx sha avx2
|
||||
07:32:31.306 RESOURCES : ResourceDB: loading cache (id=0 name=ERR_Core path=Z:\home\jakub\devel\escapistsrereintroduced\addons\core/resourceDatabase.rdb)
|
||||
07:32:31.307 RESOURCES : ResourceDB: loading cache (id=1 name=ArmaReforger path=./addons/data/resourceDatabase.rdb)
|
||||
07:32:31.450 RESOURCES : ResourceDB: loading cache (id=2 name=core path=./addons/core/resourceDatabase.rdb)
|
||||
07:32:31.451 RESOURCES : ResourceDB: loading cache (id=3 name=profile path=Z:\tmp\erri-game-profile\profile/resourceDatabase.rdb)
|
||||
07:32:31.451 RESOURCES : ResourceDB: loading cache (id=4 name=logs path=Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-32-31/resourceDatabase.rdb)
|
||||
07:32:31.603 ENGINE : GameProject load
|
||||
07:32:31.603 ENGINE : Loaded addons:
|
||||
07:32:31.603 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C'
|
||||
07:32:31.603 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859'
|
||||
07:32:31.603 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:32:31.604 ENGINE : Loading custom engine user config '$profile:.save/app1874880_user76561198020202999/settings/ReforgerEngineSettings.conf'
|
||||
07:32:31.604 ENGINE : No Enfusion settings file loaded. Continuing with defaults
|
||||
07:32:31.604 ENGINE : Locale info: system en-US (English), user en-US (English)
|
||||
07:32:31.734 RENDER : (OK) Adapter 'AMD Radeon RX 6950 XT (RADV NAVI21)' supports feature level 12_0
|
||||
07:32:31.736 RENDER : Basic screen setup:
|
||||
07:32:31.736 RENDER : Back buffer width x height: 1280x720
|
||||
07:32:31.736 RENDER : Back buffer format : TEXFMT_R8G8B8A8_SRGB (29)
|
||||
07:32:31.736 RENDER : MSAA : none
|
||||
07:32:31.748 RENDER : AMD AGS library initialized, version 6.1.0 x DLL 6.1.0
|
||||
07:32:31.748 RENDER : Extendeded AMD info for AMD Radeon RX 6950 XT (RADV NAVI21) (primary device)
|
||||
07:32:31.748 RENDER : * architecture RDNA2, 80 CUs, 40 WGPs (for RDNA), 64 ROPs
|
||||
07:32:31.748 RENDER : * core clocks 2720 MHz, memory 1124 MHz
|
||||
07:32:31.748 RENDER : * TFlops 27.9, memory bandwidth (562.0 GB/s)
|
||||
07:32:31.748 RENDER : AMD AGS correctly initialized
|
||||
07:32:31.749 RENDER : GPU_ATI (0x1002) (AMD Radeon RX 6950 XT (RADV NAVI21)) with 1 GPU detected, VRAM 16128MB (fast 0MB), shared 64362MB, driver version 99.19.02-230831a-396538C-AMD-Software-Adrenalin-Edition
|
||||
07:32:31.749 RENDER : Detected output devices:
|
||||
07:32:31.749 RENDER : * 1 device/s connected to AMD Radeon RX 6950 XT (RADV NAVI21):
|
||||
07:32:31.749 RENDER : Generic Non-PnP Monitor (\\.\DISPLAY1), 1280x720 (offset 0x0), 30Hz
|
||||
07:32:31.749 RENDER : Concurrent frames limit 2
|
||||
07:32:31.837 RENDER : DX12 device successfully created by AMD AGS library
|
||||
07:32:31.837 RENDER : * user markers not supported in this version AMD SW
|
||||
07:32:31.837 RENDER : Graphics device features
|
||||
07:32:31.837 RENDER : Needed:
|
||||
07:32:31.837 RENDER : * Highest supported shader model: 6.8 (6.0 needed)
|
||||
07:32:31.837 RENDER : Optional:
|
||||
07:32:31.837 RENDER : * Allow tearing (VSYNC) : 1
|
||||
07:32:31.837 RENDER : * 16 bits : 1
|
||||
07:32:31.837 RENDER : * Resource heap tier : 3
|
||||
07:32:31.837 RENDER : * Persistent heaps (DRED) : 1
|
||||
07:32:31.837 RENDER : * DRED 1.2 is supported by compiler
|
||||
07:32:31.859 RENDER : Main RT format setup.
|
||||
07:32:31.859 RENDER : Main RT format for quality 0 : TEXFMT_R11G11B10_FLOAT (26)
|
||||
07:32:31.859 RENDER : Main RT format for quality 1 : TEXFMT_R16G16B16A16_FLOAT (10)
|
||||
07:32:31.864 ENGINE : Job system settings: coreCount=16, shortJobContextCount=16, shortJobThreadCount=15, longJobThreadCount=7
|
||||
07:32:31.893 PROFILING : Settings changed took: 0.970300 ms
|
||||
07:32:31.900 RENDER : RENDER : Reload shaders
|
||||
07:32:31.900 RENDER : Enfusion shader version 13
|
||||
07:32:31.900 INIT : INIT : ShaderListReload
|
||||
07:32:31.900 PROFILING : ShaderListReload took: 0.000500 ms
|
||||
07:32:32.534 RENDER : Loaded 3383 newer shader binaries
|
||||
07:32:32.534 PROFILING : Reload shaders took: 633.890300 ms
|
||||
07:32:32.537 ENGINE : Initializing inputs.
|
||||
07:32:32.550 NETWORK : Initializing networking.
|
||||
07:32:32.550 NETWORK : Using new GameRplScheduler.
|
||||
07:32:32.551 SCRIPT : SCRIPT : Initializing scripts
|
||||
07:32:32.551 SCRIPT : SCRIPT : ScriptProjectManager init
|
||||
07:32:32.551 PROFILING : ScriptProjectManager init took: 0.013500 ms
|
||||
07:32:32.583 PROFILING : Initializing scripts took: 31.657500 ms
|
||||
07:32:32.583 BACKEND : Backend Services are disabled.
|
||||
07:32:32.583 ENGINE : Enfusion engine successfully created.
|
||||
07:32:32.590 DEFAULT (W): LogiLED: Cannot initialize! (service not running or no compatible device detected)
|
||||
07:32:32.616 GUI : Using default language (en_us)
|
||||
07:32:32.616 GUI : Loading 'en_us' localization file.
|
||||
07:32:32.616 INIT : INIT : Loading StringTable
|
||||
07:32:32.642 PROFILING : Loading StringTable took: 25.812900 ms
|
||||
07:32:32.642 SCRIPT : SCRIPT : Compiling GameLib scripts
|
||||
07:32:32.695 SCRIPT : Module: GameLib; loaded 465x files; 607x classes; used 665K of static memory; defines: "PLATFORM_WINDOWS,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: 4507af04
|
||||
07:32:32.696 PROFILING : Compiling GameLib scripts took: 53.742000 ms
|
||||
07:32:32.696 RESOURCES : GetResourceObject @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:32:32.696 GUI : Layout load @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:32:32.696 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)
|
||||
07:32:32.770 SCRIPT : SCRIPT : Compiling Game scripts
|
||||
@@ -0,0 +1,7 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-32-31\error.log started at 2026-09-19 07:32:32 (2026-09-19 05:32:32 UTC)
|
||||
|
||||
07:32:32.590 DEFAULT (W): LogiLED: Cannot initialize! (service not running or no compatible device detected)
|
||||
07:32:32.696 RESOURCES : GetResourceObject @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:32:32.696 GUI : Layout load @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:32:32.696 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"log": "console.log",
|
||||
"smoke_completions": 0,
|
||||
"assertions_passed": 0,
|
||||
"script_or_runtime_failures": [],
|
||||
"engine_errors": [
|
||||
"07:32:32.696 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)"
|
||||
],
|
||||
"missing_end_screen": [],
|
||||
"scope": "ordinary local game startup only; no player input, full escape, multiplayer or FPS proof",
|
||||
"game_module_defines": [],
|
||||
"workbench_undefined": false,
|
||||
"normal_mission_ready": false,
|
||||
"unexpected_smoke_fixture": false,
|
||||
"failed": true,
|
||||
"ready": false
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mconsole:[0m gamescope version 3.16.28 (gcc 16.2.1)
|
||||
No CAP_SYS_NICE, falling back to regular-priority compute and threads.
|
||||
Performance will be affected.
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope/common'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/inspect.lua' (id: 0)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/modegen.lua' (id: 1)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/common/util.lua' (id: 2)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/usr/share/gamescope/scripts/00-gamescope/displays'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/asus.rogally.lcd.lua' (id: 3)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua' (id: 4)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/gpd.win4.lcd.lua' (id: 5)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/lenovo.legiongo.lcd.lua' (id: 6)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/lenovo.legiongos.lcd.lua' (id: 7)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/onexplayer.f1.oled.lua' (id: 8)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/valve.steamdeck.lcd.lua' (id: 9)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/valve.steamdeck.oled.lua' (id: 10)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Running script file '/usr/share/gamescope/scripts/00-gamescope/displays/zotac.zone.oled.lua' (id: 11)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/etc/gamescope/scripts'
|
||||
[gamescope] [[0;33mWarn[0m] [0;37mscriptmgr:[0m Directory '/etc/gamescope/scripts' does not exist
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mscriptmgr:[0m Loading scripts from: '/home/jakub/.config/gamescope/scripts'
|
||||
[gamescope] [[0;33mWarn[0m] [0;37mscriptmgr:[0m Directory '/home/jakub/.config/gamescope/scripts' does not exist
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m selecting physical device 'AMD Radeon RX 6950 XT (RADV NAVI21)': queue family 1 (general queue family 0)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m physical device supports DRM format modifiers
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [backend/headless/backend.c:60] Creating headless backend
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m supported DRM formats for sampling usage:
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AR24 (0x34325241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XR24 (0x34325258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB24 (0x34324241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB24 (0x34324258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m RG16 (0x36314752)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m NV12 (0x3231564E)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB4H (0x48344241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB4H (0x48344258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB48 (0x38344241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB48 (0x38344258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AB30 (0x30334241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XB30 (0x30334258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m AR30 (0x30335241)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvulkan:[0m XR30 (0x30335258)
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Using explicit sync when available
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Running compositor on wayland display 'gamescope-0'
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [backend/headless/backend.c:17] Starting headless backend
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m Successfully initialized libei for input emulation!
|
||||
[gamescope] [[0;31mError[0m] [0;37mwlserver:[0m [xwayland/sockets.c:47] Failed to bind socket @/tmp/.X11-unix/X0: Address already in use
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mwlserver:[0m [xwayland/server.c:108] Starting Xwayland on :2
|
||||
The XKEYBOARD keymap compiler (xkbcomp) reports:
|
||||
> Warning: Multiple symbols for level 1/group 1 on key <FK23>
|
||||
> Using F23, ignoring XF86TouchpadOff
|
||||
> Warning: Symbol map for key <FK23> redefined
|
||||
> Using last definition for conflicting fields
|
||||
> Warning: Symbol map for key <FK24> redefined
|
||||
> Using last definition for conflicting fields
|
||||
> Warning: Could not resolve keysym XF86ElectronicPrivacyScreenOn
|
||||
> Warning: Could not resolve keysym XF86ElectronicPrivacyScreenOff
|
||||
> Warning: Could not resolve keysym XF86ActionOnSelection
|
||||
> Warning: Could not resolve keysym XF86ContextualInsert
|
||||
> Warning: Could not resolve keysym XF86ContextualQuery
|
||||
Errors from xkbcomp are not fatal to the X server
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream state changed: connecting
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream state changed: paused
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mpipewire:[0m stream available on node ID: 165
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mvblank:[0m Using timerfd.
|
||||
fsync: up and running.
|
||||
[Gamescope WSI] No application info given.
|
||||
[Gamescope WSI] Executable name: explorer.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: xalia.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: DXVK
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Executable name: xalia.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] No application info given.
|
||||
The XKEYBOARD keymap compiler (xkbcomp) reports:
|
||||
> Warning: Unsupported maximum keycode 709, clipping.
|
||||
> X11 cannot support keycodes above 255.
|
||||
> Warning: Virtual modifier Hyper multiply defined
|
||||
> Using 0, ignoring 0
|
||||
> Warning: Virtual modifier ScrollLock multiply defined
|
||||
> Using 0, ignoring 0
|
||||
Errors from xkbcomp are not fatal to the X server
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteam.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: DXVK
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Executable name: ArmaReforgerSteam.exe
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: (null)
|
||||
applicationVersion: 0
|
||||
pEngineName: (null)
|
||||
engineVersion: 0
|
||||
apiVersion: 4198400
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteam.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: vkd3d
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Forcing on VK_EXT_swapchain_maintenance1.
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: (null)
|
||||
applicationVersion: 0
|
||||
pEngineName: (null)
|
||||
engineVersion: 0
|
||||
apiVersion: 4198400
|
||||
ATTENTION: default value of option vk_wsi_force_swapchain_to_current_extent overridden by environment.
|
||||
[Gamescope WSI] Application info:
|
||||
pApplicationName: ArmaReforgerSteam.exe
|
||||
applicationVersion: 0
|
||||
pEngineName: vkd3d
|
||||
engineVersion: 12587008
|
||||
apiVersion: 4206592
|
||||
[Gamescope WSI] Forcing on VK_EXT_swapchain_maintenance1.
|
||||
[Gamescope WSI] Creating Gamescope surface: xid: 0x1a00030
|
||||
[Gamescope WSI] Atom of T was wrong type. Expected XCB_ATOM_CARDINAL.
|
||||
[Gamescope WSI] Made gamescope surface for xid: 0x1a00030
|
||||
[Gamescope WSI] Surface state:
|
||||
steam app id: 1874880
|
||||
window xid: 0x1a00030
|
||||
wayland surface res id: 5
|
||||
layer client flags: 0x4
|
||||
server hdr output enabled: false
|
||||
hdr formats exposed to client: false
|
||||
[Gamescope WSI] Creating swapchain for xid: 0x1a00030 - oldSwapchain: (nil) - provided minImageCount: 3 - minImageCount: 3 - format: VK_FORMAT_R8G8B8A8_UNORM - colorspace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - flip: true
|
||||
[Gamescope WSI] Created swapchain for xid: 0x1a00030 swapchain: 0x7f27041815c0 - imageCount: 3
|
||||
[Gamescope WSI] Destroying swapchain: 0x7f27041815c0
|
||||
[Gamescope WSI] Destroyed swapchain: 0x7f27041815c0
|
||||
[Gamescope WSI] Creating swapchain for xid: 0x1a00030 - oldSwapchain: (nil) - provided minImageCount: 3 - minImageCount: 3 - format: VK_FORMAT_R8G8B8A8_UNORM - colorspace: VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - flip: true
|
||||
[Gamescope WSI] Created swapchain for xid: 0x1a00030 swapchain: 0x7f27041815c0 - imageCount: 3
|
||||
[gamescope] [[0;34mInfo[0m] [0;37mlaunch:[0m Primary child shut down!
|
||||
(EE) failed to read Wayland events: Broken pipe
|
||||
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"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": "0b954c856cfee9b5dbb6241a5001726ca6940c885f968c2ed60a84264be7a1f4",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "657e96d1112b68c8ced37793e99f88e6078b38a579190e63d00b1f9a9a032e26",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "12d8fc39d47e03c3838e0642aa9e4a80baf60f250357493bff812d5c75812c86",
|
||||
"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/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": "becf85c5d1eb31d6bd480e9854aaab426118ad81b7a01f549314668d29216bae",
|
||||
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
|
||||
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
|
||||
"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": "8bd0b651681ea427c995f4a711ec5594e15e3cfa0878fc9148f4d5c3738d3d99",
|
||||
"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_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "bce62ce70df26ed527375537faa7cfa0dee252ac89bac5ba3af1b2f3d3e3dbb1",
|
||||
"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_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": "1b67af6c72006a4bfed733d1809bb624254422fdde1b618168540c1d73883b60",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c": "1766dafb25fbc8819f09cc977541c07a290b9e5e13e969cc9f576df6d2555a50",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "c14e7386fb0ddc3514091e33c9eda56ac1540f30e18d283744ccfd25999605fe",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "27c0e4abf65672c42dabbe84e8092455d339db2c5915f742bd6efa069c90424f",
|
||||
"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": "599f4552893619f486e15032b393c48022e5b59afe50b93d658e7e7f4b93964f",
|
||||
"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": "c8a8ca5c79b00f06f58846e8bfccf95471eb2aa94ce30a5bd2002af9b4879050",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
|
||||
"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_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": "1f5f03628123331a091f52731717075821e024a86feef977777a8036f8922989",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "64c2cef62d8a435eea396f057255b269d457935bf5d261221700739bf37240b8",
|
||||
"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/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/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
|
||||
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"launch_id": "20848d26-e852-4eac-af18-4f8c364ce84d",
|
||||
"captured_unix": 1789795949.5515647,
|
||||
"source_root": "/home/jakub/devel/escapistsrereintroduced",
|
||||
"command": [
|
||||
"gamescope",
|
||||
"--backend",
|
||||
"headless",
|
||||
"-W",
|
||||
"1280",
|
||||
"-H",
|
||||
"720",
|
||||
"-w",
|
||||
"1280",
|
||||
"-h",
|
||||
"720",
|
||||
"-r",
|
||||
"30",
|
||||
"--",
|
||||
"/home/jakub/.local/share/Steam/steamapps/common/Proton - Experimental/proton",
|
||||
"run",
|
||||
"/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/ArmaReforgerSteam.exe",
|
||||
"-addonsDir",
|
||||
"Z:/home/jakub/devel/escapistsrereintroduced/addons",
|
||||
"-addons",
|
||||
"2528466DE220D91C",
|
||||
"-profile",
|
||||
"Z:/tmp/erri-game-profile",
|
||||
"-world",
|
||||
"Worlds/ERR_Everon.ent",
|
||||
"-noBackend",
|
||||
"-noSound",
|
||||
"-noSplash",
|
||||
"-noThrow",
|
||||
"-logconsole"
|
||||
],
|
||||
"manifest_sha256": "af9d81e1ac19e0fe6d5d31d6547c9d2da80e461ac0a02870d0dd67abeb92548c"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"log": "docs/evidence/game-2026-09-19-073231/console.log.txt",
|
||||
"smoke_completions": 0,
|
||||
"assertions_passed": 0,
|
||||
"script_or_runtime_failures": [],
|
||||
"engine_errors": [
|
||||
"07:32:32.696 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)"
|
||||
],
|
||||
"missing_end_screen": [],
|
||||
"scope": "ordinary local game startup only; no player input, full escape, multiplayer or FPS proof",
|
||||
"game_module_defines": [],
|
||||
"workbench_undefined": false,
|
||||
"normal_mission_ready": false,
|
||||
"unexpected_smoke_fixture": false,
|
||||
"failed": true,
|
||||
"ready": false
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"stopped_unix": 1789795953.9254315,
|
||||
"console_sha256": "20684f6328c7e955d1f08edf16e470e19efc71284856701b43ed31811693536f",
|
||||
"end_source_sha256": "af9d81e1ac19e0fe6d5d31d6547c9d2da80e461ac0a02870d0dd67abeb92548c",
|
||||
"source_unchanged_after_run": true,
|
||||
"source_provenance": "launch_snapshot",
|
||||
"launch_id": "20848d26-e852-4eac-af18-4f8c364ce84d",
|
||||
"launch_source_manifest": "launch-source-sha256.json",
|
||||
"launch_source_metadata": "launch-source.json",
|
||||
"launch_source_sha256": "af9d81e1ac19e0fe6d5d31d6547c9d2da80e461ac0a02870d0dd67abeb92548c",
|
||||
"started_unix": 1789795949.551632,
|
||||
"result": "game-failed",
|
||||
"session": "/tmp/erri-game-profile/logs/logs_2026-09-19_07-32-31",
|
||||
"project": "core",
|
||||
"cleanup_confirmed": true,
|
||||
"runner_error": null,
|
||||
"executable": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/ArmaReforgerSteam.exe",
|
||||
"dedicated_server": false,
|
||||
"display": "headless Gamescope",
|
||||
"audio": "-noSound plus own silent sink",
|
||||
"scope": "ordinary game compile/startup; no scripted fixture, full escape or multiplayer acceptance"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-32-31\script.log started at 2026-09-19 07:32:32 (2026-09-19 05:32:32 UTC)
|
||||
|
||||
07:32:32.551 SCRIPT : SCRIPT : Initializing scripts
|
||||
07:32:32.551 SCRIPT : SCRIPT : ScriptProjectManager init
|
||||
07:32:32.642 SCRIPT : SCRIPT : Compiling GameLib scripts
|
||||
07:32:32.695 SCRIPT : Module: GameLib; loaded 465x files; 607x classes; used 665K of static memory; defines: "PLATFORM_WINDOWS,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: 4507af04
|
||||
07:32:32.770 SCRIPT : SCRIPT : Compiling Game scripts
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"kind": "launch_snapshot"
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"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": "0b954c856cfee9b5dbb6241a5001726ca6940c885f968c2ed60a84264be7a1f4",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarFiring.c": "657e96d1112b68c8ced37793e99f88e6078b38a579190e63d00b1f9a9a032e26",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarPrediction.c": "470dd196ed64800c697d24c09d1344bacd2502587fac76af4ee0edae2563092d",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c": "697c01f479df6c505a41d984a29c02002e3052114dafa2ec6252ae55e2979a2b",
|
||||
"addons/ai/Scripts/Game/ERR/ERR_MortarSystem.c": "12d8fc39d47e03c3838e0642aa9e4a80baf60f250357493bff812d5c75812c86",
|
||||
"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/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": "becf85c5d1eb31d6bd480e9854aaab426118ad81b7a01f549314668d29216bae",
|
||||
"addons/chat/Scripts/WorkbenchGame/ERR/ERR_ValidateWorldPlugin.c": "81c92d408ce88cc9f98d6053f1d0c863427693ba748f00df9f1bf8079015ef94",
|
||||
"addons/chat/addon.gproj": "ea1587e0174cf795334d306c71d99b06797fc891427cd57b6cab6e21cf0e4e0e",
|
||||
"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": "8bd0b651681ea427c995f4a711ec5594e15e3cfa0878fc9148f4d5c3738d3d99",
|
||||
"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_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/ERR_GameMode.c": "bce62ce70df26ed527375537faa7cfa0dee252ac89bac5ba3af1b2f3d3e3dbb1",
|
||||
"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_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": "1b67af6c72006a4bfed733d1809bb624254422fdde1b618168540c1d73883b60",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c": "1766dafb25fbc8819f09cc977541c07a290b9e5e13e969cc9f576df6d2555a50",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c": "c14e7386fb0ddc3514091e33c9eda56ac1540f30e18d283744ccfd25999605fe",
|
||||
"addons/core/Scripts/Game/ERR/ERR_NativeCasualtyServiceProbe.c": "27c0e4abf65672c42dabbe84e8092455d339db2c5915f742bd6efa069c90424f",
|
||||
"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": "599f4552893619f486e15032b393c48022e5b59afe50b93d658e7e7f4b93964f",
|
||||
"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": "c8a8ca5c79b00f06f58846e8bfccf95471eb2aa94ce30a5bd2002af9b4879050",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Objectives.c": "88d95a52fcba103483ea751571e1afeae0e6fc82115ed50d6fc195424726960f",
|
||||
"addons/core/Scripts/Game/ERR/ERR_Observer.c": "b719e723369ab4f403950c85226e1336eb48e3c127e84530ac1c695eb86bd0f9",
|
||||
"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_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": "1f5f03628123331a091f52731717075821e024a86feef977777a8036f8922989",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnFinalization.c": "2e295b0f225208c5414728ba83333e5e0ab6eef3a708ce39eb1dfce5400c94c9",
|
||||
"addons/core/Scripts/Game/ERR/ERR_SpawnLogic.c": "64c2cef62d8a435eea396f057255b269d457935bf5d261221700739bf37240b8",
|
||||
"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/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/intel/Scripts/Game/ERR/ERR_IntelService.c": "482839434b94e7f8c345d5fd96490aeebb765f3dd0c1bb25fceea2f435c0e722",
|
||||
"addons/intel/addon.gproj": "d0ced242cefb220a5cccd6779d61fda9bc55581701b9f78bcf13c09d92ddbcbe",
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
---------------------------------------------
|
||||
Log Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-45-05\console.log started at 2026-09-19 07:45:05 (2026-09-19 05:45:05 UTC)
|
||||
|
||||
07:45:05.690 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-45-05' to filesystem under name logs
|
||||
07:45:05.690 ENGINE : FileSystem: Adding relative directory 'Z:\tmp\erri-game-profile\profile' to filesystem under name profile
|
||||
07:45:05.690 ENGINE : FileSystem: Current working directory: 'Z:\home\jakub\.local\share\Steam\steamapps\common\Arma Reforger\'
|
||||
07:45:05.691 ENGINE : Initializing engine, version 192142
|
||||
07:45:05.691 ENGINE : CLI Params: -addonsDir Z:/home/jakub/devel/escapistsrereintroduced/addons -addons 2528466DE220D91C -profile Z:/tmp/erri-game-profile -world Worlds/ERR_Everon.ent -noBackend -noSound -noSplash -noThrow -logconsole
|
||||
07:45:05.698 ENGINE : Addon dirs:
|
||||
07:45:05.698 ENGINE : dir: 'Z:/home/jakub/devel/escapistsrereintroduced/addons'
|
||||
07:45:05.698 ENGINE : dir: './addons'
|
||||
07:45:05.698 ENGINE : dir: 'Z:/tmp/erri-game-profile/addons'
|
||||
07:45:05.698 ENGINE : Available addons:
|
||||
07:45:05.698 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/ai/addon.gproj' guid: '5192138CB9D5B911'
|
||||
07:45:05.698 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/chat/addon.gproj' guid: 'FA804F411BDDF2C6'
|
||||
07:45:05.698 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:45:05.698 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/intel/addon.gproj' guid: 'D31039C7C53E348A'
|
||||
07:45:05.698 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/map/addon.gproj' guid: '9AAEE9041D79809E'
|
||||
07:45:05.699 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C' (packed)
|
||||
07:45:05.699 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859' (packed)
|
||||
07:45:05.699 ENGINE : FileSystem: Adding relative directory 'Z:\home\jakub\devel\escapistsrereintroduced\addons\core' to filesystem under name ERR_Core
|
||||
07:45:05.826 ENGINE : FileSystem: Adding package './addons/data/' (pak count: 14) to filesystem under name ArmaReforger
|
||||
07:45:05.831 ENGINE : FileSystem: Adding package './addons/core/' (pak count: 2) to filesystem under name core
|
||||
07:45:05.831 ENGINE : CPU vendor : AuthenticAMD
|
||||
07:45:05.831 ENGINE : CPU type : 2
|
||||
07:45:05.831 ENGINE : CPU name : AMD Ryzen 7 3800XT 8-Core Processor
|
||||
07:45:05.831 ENGINE : CPU cache info : L1 [Inst 32KB, Data 32KB], L2 [Unif 512KB], L3 [Unif 16384KB]
|
||||
07:45:05.831 ENGINE : CPU count logical : 16
|
||||
07:45:05.831 ENGINE : CPU count physical : 8
|
||||
07:45:05.831 ENGINE : CPU features : mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcnt aesni pclmulqdq osxsave avx sha avx2
|
||||
07:45:05.831 RESOURCES : ResourceDB: loading cache (id=0 name=ERR_Core path=Z:\home\jakub\devel\escapistsrereintroduced\addons\core/resourceDatabase.rdb)
|
||||
07:45:05.832 RESOURCES : ResourceDB: loading cache (id=1 name=ArmaReforger path=./addons/data/resourceDatabase.rdb)
|
||||
07:45:05.970 RESOURCES : ResourceDB: loading cache (id=2 name=core path=./addons/core/resourceDatabase.rdb)
|
||||
07:45:05.972 RESOURCES : ResourceDB: loading cache (id=3 name=profile path=Z:\tmp\erri-game-profile\profile/resourceDatabase.rdb)
|
||||
07:45:05.972 RESOURCES : ResourceDB: loading cache (id=4 name=logs path=Z:\tmp\erri-game-profile\logs\logs_2026-09-19_07-45-05/resourceDatabase.rdb)
|
||||
07:45:06.118 ENGINE : GameProject load
|
||||
07:45:06.118 ENGINE : Loaded addons:
|
||||
07:45:06.118 ENGINE : gproj: './addons/core/core.gproj' guid: '5614BBCCBB55ED1C'
|
||||
07:45:06.118 ENGINE : gproj: './addons/data/ArmaReforger.gproj' guid: '58D0FB3206B6F859'
|
||||
07:45:06.118 ENGINE : gproj: 'Z:/home/jakub/devel/escapistsrereintroduced/addons/core/addon.gproj' guid: '2528466DE220D91C'
|
||||
07:45:06.120 ENGINE : Loading custom engine user config '$profile:.save/app1874880_user76561198020202999/settings/ReforgerEngineSettings.conf'
|
||||
07:45:06.120 ENGINE : No Enfusion settings file loaded. Continuing with defaults
|
||||
07:45:06.120 ENGINE : Locale info: system en-US (English), user en-US (English)
|
||||
07:45:06.240 RENDER : (OK) Adapter 'AMD Radeon RX 6950 XT (RADV NAVI21)' supports feature level 12_0
|
||||
07:45:06.242 RENDER : Basic screen setup:
|
||||
07:45:06.242 RENDER : Back buffer width x height: 1280x720
|
||||
07:45:06.242 RENDER : Back buffer format : TEXFMT_R8G8B8A8_SRGB (29)
|
||||
07:45:06.242 RENDER : MSAA : none
|
||||
07:45:06.255 RENDER : AMD AGS library initialized, version 6.1.0 x DLL 6.1.0
|
||||
07:45:06.255 RENDER : Extendeded AMD info for AMD Radeon RX 6950 XT (RADV NAVI21) (primary device)
|
||||
07:45:06.255 RENDER : * architecture RDNA2, 80 CUs, 40 WGPs (for RDNA), 64 ROPs
|
||||
07:45:06.255 RENDER : * core clocks 2720 MHz, memory 1124 MHz
|
||||
07:45:06.255 RENDER : * TFlops 27.9, memory bandwidth (562.0 GB/s)
|
||||
07:45:06.255 RENDER : AMD AGS correctly initialized
|
||||
07:45:06.255 RENDER : GPU_ATI (0x1002) (AMD Radeon RX 6950 XT (RADV NAVI21)) with 1 GPU detected, VRAM 16128MB (fast 0MB), shared 64362MB, driver version 99.19.02-230831a-396538C-AMD-Software-Adrenalin-Edition
|
||||
07:45:06.255 RENDER : Detected output devices:
|
||||
07:45:06.255 RENDER : * 1 device/s connected to AMD Radeon RX 6950 XT (RADV NAVI21):
|
||||
07:45:06.255 RENDER : Generic Non-PnP Monitor (\\.\DISPLAY1), 1280x720 (offset 0x0), 30Hz
|
||||
07:45:06.256 RENDER : Concurrent frames limit 2
|
||||
07:45:06.331 RENDER : DX12 device successfully created by AMD AGS library
|
||||
07:45:06.331 RENDER : * user markers not supported in this version AMD SW
|
||||
07:45:06.331 RENDER : Graphics device features
|
||||
07:45:06.331 RENDER : Needed:
|
||||
07:45:06.331 RENDER : * Highest supported shader model: 6.8 (6.0 needed)
|
||||
07:45:06.331 RENDER : Optional:
|
||||
07:45:06.331 RENDER : * Allow tearing (VSYNC) : 1
|
||||
07:45:06.331 RENDER : * 16 bits : 1
|
||||
07:45:06.331 RENDER : * Resource heap tier : 3
|
||||
07:45:06.331 RENDER : * Persistent heaps (DRED) : 1
|
||||
07:45:06.331 RENDER : * DRED 1.2 is supported by compiler
|
||||
07:45:06.353 RENDER : Main RT format setup.
|
||||
07:45:06.353 RENDER : Main RT format for quality 0 : TEXFMT_R11G11B10_FLOAT (26)
|
||||
07:45:06.353 RENDER : Main RT format for quality 1 : TEXFMT_R16G16B16A16_FLOAT (10)
|
||||
07:45:06.357 ENGINE : Job system settings: coreCount=16, shortJobContextCount=16, shortJobThreadCount=15, longJobThreadCount=7
|
||||
07:45:06.387 PROFILING : Settings changed took: 0.980900 ms
|
||||
07:45:06.393 RENDER : RENDER : Reload shaders
|
||||
07:45:06.394 RENDER : Enfusion shader version 13
|
||||
07:45:06.394 INIT : INIT : ShaderListReload
|
||||
07:45:06.394 PROFILING : ShaderListReload took: 0.000400 ms
|
||||
07:45:06.995 RENDER : Loaded 3383 newer shader binaries
|
||||
07:45:06.995 PROFILING : Reload shaders took: 601.631900 ms
|
||||
07:45:06.998 ENGINE : Initializing inputs.
|
||||
07:45:07.012 NETWORK : Initializing networking.
|
||||
07:45:07.012 NETWORK : Using new GameRplScheduler.
|
||||
07:45:07.012 SCRIPT : SCRIPT : Initializing scripts
|
||||
07:45:07.013 SCRIPT : SCRIPT : ScriptProjectManager init
|
||||
07:45:07.013 PROFILING : ScriptProjectManager init took: 0.010800 ms
|
||||
07:45:07.043 PROFILING : Initializing scripts took: 30.611300 ms
|
||||
07:45:07.043 BACKEND : Backend Services are disabled.
|
||||
07:45:07.043 ENGINE : Enfusion engine successfully created.
|
||||
07:45:07.050 DEFAULT (W): LogiLED: Cannot initialize! (service not running or no compatible device detected)
|
||||
07:45:07.071 GUI : Using default language (en_us)
|
||||
07:45:07.071 GUI : Loading 'en_us' localization file.
|
||||
07:45:07.071 INIT : INIT : Loading StringTable
|
||||
07:45:07.094 PROFILING : Loading StringTable took: 22.666100 ms
|
||||
07:45:07.094 SCRIPT : SCRIPT : Compiling GameLib scripts
|
||||
07:45:07.135 SCRIPT : Module: GameLib; loaded 465x files; 607x classes; used 665K of static memory; defines: "PLATFORM_WINDOWS,ENF_ENABLE_VHC_OVERRIDE,ENF_ENABLE_RPLCOMPONENT_IN_GAMECODE"; CRC32: 4507af04
|
||||
07:45:07.136 PROFILING : Compiling GameLib scripts took: 41.819700 ms
|
||||
07:45:07.136 RESOURCES : GetResourceObject @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:45:07.136 GUI : Layout load @"{1C71B463B3B66BAB}UI/layouts/Menus/MainMenu/IntroSplashScreen.layout"
|
||||
07:45:07.136 GUI (E): Unknown class 'SCR_WidgetExportRuleRoot' at offset 282(0x11a)
|
||||
07:45:07.209 SCRIPT : SCRIPT : Compiling Game scripts
|
||||
07:45:08.176 SCRIPT : Compiling Game scripts
|
||||
07:45:08.176 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,785": 'GetPlayerPlatformKind' is obsolete
|
||||
07:45:08.176 SCRIPT (W): @"Scripts/Game/Editor/Components/EditableEntity/SCR_EditableEntityComponent.c,786": 'GetPlayerPlatformId' is obsolete
|
||||
07:45:08.403 SCRIPT (W): @"Scripts/Game/ERR/ERR_SiteService.c,189": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
|
||||
07:45:08.414 SCRIPT (W): @"Scripts/Game/Workshop/SCR_AddonManager.c,876": 'GetRefCount' is obsolete: Will be removed
|
||||
07:45:08.440 SCRIPT (W): @"Scripts/Game/Campaign/SCR_PlayerProfileManagerComponent.c,142": 'PlayerData' is obsolete
|
||||
07:45:08.537 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,159": 'GetDSSession' is obsolete
|
||||
07:45:08.537 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,162": 'RoomID' is obsolete
|
||||
07:45:08.537 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,197": 'GetDSSession' is obsolete
|
||||
07:45:08.537 SCRIPT (W): @"Scripts/Game/UI/Backend/CareerBackend.c,201": 'RoomID' is obsolete
|
||||
07:45:08.566 SCRIPT (W): @"Scripts/Game/ERR/ERR_CasualtyGroundSupport.c,21": 'GetBoneIndex' is obsolete: Use GetAnimation().GetBoneIndex() instead
|
||||
07:45:08.621 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,481": 'GetStorage' is obsolete
|
||||
07:45:08.621 SCRIPT (W): @"Scripts/Game/DataCollection/SCR_DataCollectorComponent.c,483": 'GetOnlineWritePrivilege' is obsolete
|
||||
07:45:08.622 SCRIPT (W): @"Scripts/Game/Utilities/SCR_PlayerIdentityUtils.c,20": 'GetPlayerIdentityId' is obsolete
|
||||
07:45:08.659 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,45": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
|
||||
07:45:08.659 SCRIPT (W): @"Scripts/Game/ERR/ERR_ExtractionService.c,56": 'GetCompartmentType' is obsolete: Use GetType() on the compartment instance directly.
|
||||
07:45:08.661 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,643": 'GetNotifyCount' is obsolete: Will be substitued by Notification Api.
|
||||
07:45:08.661 SCRIPT (W): @"Scripts/Game/UI/Menu/MainMenuUI.c,645": 'GetNotifyItem' is obsolete: Will be substitued by Notification Api.
|
||||
07:45:08.721 SCRIPT (W): @"Scripts/Game/DataCollection/PlayerData/SCR_PlayerData.c,210": 'PlayerData' is obsolete
|
||||
07:45:08.839 SCRIPT : Module: Game; loaded 5728x files; 11108x classes; used 26696K of static memory; defines: "PLATFORM_WINDOWS,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: e19cf2b0
|
||||
07:45:08.869 PROFILING : Compiling Game scripts took: 1659.723800 ms
|
||||
07:45:08.869 INIT : Creating game instance(ArmaReforgerScripted), version 1.8.0.13 built 2026-08-21 14:30:18 UTC.
|
||||
07:45:08.897 ENGINE : Game successfully created.
|
||||
07:45:08.939 PLATFORM : Save data from container 'settings' have been loaded
|
||||
07:45:09.039 PLATFORM : Save data from container 'sessions' have been loaded
|
||||
07:45:09.440 PLATFORM : System language differs from the saved one - using new language {new: 'en_us'; old: ''}
|
||||
07:45:09.440 PLATFORM : Save data transaction to 'settings' started.
|
||||
07:45:09.538 DEFAULT : [SaveGameManager] Starting new playthrough nr.0 '' for mission 'Worlds/ERR_Everon.ent'.
|
||||
07:45:09.539 WORLD : WORLD : Entities load 'Worlds/ERR_Everon.ent'
|
||||
07:45:10.473 PROFILING : Entities load took: 934.092700 ms
|
||||
07:45:10.475 WORLD : WORLD : Game::LoadEntities
|
||||
07:45:10.475 WORLD : WORLD : Initializing world systems
|
||||
07:45:10.476 NETWORK : Enabled lag compensation, 29 frames with 100 FPS and 280 ms rewind limits.
|
||||
07:45:10.476 WORLD : WORLD : CreateEntities
|
||||
07:45:10.476 WORLD : WORLD : CreateEntities
|
||||
07:45:10.476 WORLD : WORLD : NotifyBeforeEntitiesCreated
|
||||
07:45:10.480 RESOURCES : Loaded mission headers from 7 addon(s)!
|
||||
07:45:10.480 PROFILING : NotifyBeforeEntitiesCreated took: 3.697400 ms
|
||||
07:45:10.480 WORLD : WORLD : Wait for preloading data
|
||||
07:45:10.487 PROFILING : Wait for preloading data took: 7.117200 ms
|
||||
07:45:10.605 ENTITY : Create entity @"ENTITY:2" ('Eden', GenericTerrainEntity) at <0.000000 0.000000 0.000000> @"{5AD924374E8C7AF6}Prefabs/World/Game/Eden/GenericTerrain_Eden.et"
|
||||
07:45:10.605 PROFILING : PROFILING : Terrain load
|
||||
07:45:12.142 PROFILING : Terrain load took: 1536.789000 ms
|
||||
07:45:14.028 WORLD : Game::LoadEntities
|
||||
07:45:14.028 WORLD : CreateEntities
|
||||
07:45:14.028 WORLD : CreateEntities
|
||||
07:45:14.028 ENTITY : Create entity @"ENTITY:398117" ('GenericEntity') at <0.000000 0.000000 0.000000> @"{434AFBBE90F2B078}Prefabs/Sounds/Environment/AmbientSounds_Everon.et"
|
||||
07:45:14.028 SCRIPT (W): AMBIENT LIFE: SCR_AmbientInsectsComponent: Missing SCR_AmbientSoundsComponent
|
||||
07:45:14.793 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"
|
||||
07:45:14.793 ENTITY : CreateComponent 'ScriptedRadioComponent'
|
||||
07:45:14.793 DEFAULT (W): World doesn't contain RadioManagerEntity to support any BaseRadioComponent.
|
||||
07:45:19.770 WORLD : WORLD : NotifyBeforeEntitiesInitialized
|
||||
07:45:19.770 PROFILING : NotifyBeforeEntitiesInitialized took: 0.036200 ms
|
||||
07:45:20.323 WORLD : InitEntities 'world'
|
||||
07:45:20.323 ENTITY : Init entity @"ENTITY:2305843009213693953" ('Rereintroduced', ERR_GameMode) at <1076.468018 51.000999 1325.246948> @"{978E045E53EF36C8}Prefabs/ERR/GameMode.et"
|
||||
07:45:20.323 SCRIPT (W): SCR_PerceivedFactionManagerComponent trying to set fall back faction 'CIV' but this faction could not be found so it is null instead.
|
||||
07:45:20.342 WORLD : WORLD : NotifyEntitiesInitialized
|
||||
07:45:20.342 TERRAIN : TERRAIN : Initializing road networks...
|
||||
07:45:20.345 PROFILING : Initializing road networks... took: 2.708900 ms
|
||||
07:45:20.345 DEFAULT : DEFAULT : WorldVolumesCollection
|
||||
07:45:20.404 PROFILING : WorldVolumesCollection took: 58.649400 ms
|
||||
07:45:20.404 INIT : INIT : SoundWorldInit
|
||||
07:45:20.418 PROFILING : SoundWorldInit took: 13.733600 ms
|
||||
07:45:20.418 PROFILING : NotifyEntitiesInitialized took: 75.239000 ms
|
||||
07:45:20.418 PROFILING : CreateEntities took: 9941.304100 ms
|
||||
07:45:20.418 PROFILING : CreateEntities took: 9941.488500 ms
|
||||
07:45:20.419 WORLD : WORLD : Wait for preloading data around camera
|
||||
07:45:20.719 PROFILING : Wait for preloading data around camera took: 300.409600 ms
|
||||
07:45:20.719 WORLD : WORLD : EOnActivate
|
||||
07:45:20.746 PROFILING : EOnActivate took: 26.909900 ms
|
||||
07:45:20.746 PROFILING : Game::LoadEntities took: 10270.904800 ms
|
||||
07:45:21.163 DEFAULT : Entered offline game state.
|
||||
07:45:21.263 PROFILING : Settings changed took: 0.851900 ms
|
||||
07:45:21.264 NETWORK : Player connected: connectionID=2147483646
|
||||
07:45:21.264 NETWORK : ### Connecting player: connectionID=2147483646, Name=
|
||||
07:45:21.264 NETWORK : ### Creating player: PlayerId=1, Name=jakub
|
||||
07:45:21.269 ENTITY : SpawnEntityPrefab @"{225E51284CC95CFA}Prefabs/Characters/Core/DefaultPlayerControllerMP.et"
|
||||
07:45:21.269 ENTITY : Create entity @"ENTITY:4611686018427388381" ('SCR_PlayerController') at <0.000000 0.000000 0.000000>
|
||||
07:45:21.269 ENTITY : EntityPrefabUse @"{225E51284CC95CFA}Prefabs/Characters/Core/DefaultPlayerControllerMP.et"
|
||||
07:45:21.269 SCRIPT (W): Notification data in 'SCR_NotificationsLogDisplay' has duplicate notification info key: 'EDITOR_PERCEIVED_FACTION_PUNISHMENT_KILLING_SET'. There should only be one of each key!
|
||||
07:45:21.269 SCRIPT (W): Notification data in 'SCR_NotificationsLogDisplay' has duplicate notification info key: 'EDITOR_PERCEIVED_FACTION_TYPE_DISABLED'. There should only be one of each key!
|
||||
07:45:21.271 SCRIPT (W): Can't open config file ""
|
||||
07:45:21.271 SCRIPT (W): Cannot update game blocklist. Backend is offline.
|
||||
07:45:21.274 WORLD : InitEntities 'world'
|
||||
07:45:21.274 ENTITY : Init entity @"ENTITY:4611686018427388381" ('SCR_PlayerController') at <0.000000 0.000000 0.000000> @"{225E51284CC95CFA}Prefabs/Characters/Core/DefaultPlayerControllerMP.et"
|
||||
07:45:21.274 GUI : WidgetManager: CrateWidgets @"{3C9DCDD76AB83157}UI/layouts/HUD/HUDLayouts/HUDManager_Root.layout"
|
||||
07:45:21.274 SCRIPT (W): Slot_WeaponInfo Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_Chat Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_VON Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_AvailableActions Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_Vehicle Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_GameVersion Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_Notifications Has no Content!
|
||||
07:45:21.274 SCRIPT (W): Slot_Hints Has no Content!
|
||||
07:45:21.280 NETWORK : ### Updating player: PlayerId=1, Name=jakub, rplIdentity=0xFFFFFFFE, IdentityId=00000000-0000-0000-0000-000000000000
|
||||
07:45:21.280 SCRIPT (E): Rereintroduced: player identity could not be bound; spawn withheld
|
||||
07:45:21.280 SCRIPT (W): Ban Settings could not be loaded from BE Storage: Relying on default config
|
||||
07:45:21.280 NETWORK : Players connecting: 0
|
||||
07:45:21.280 NETWORK : Players connected: 1 / 1
|
||||
07:45:21.290 WORLD : Frame start
|
||||
07:45:21.290 SCRIPT : ScenarioFramework: Available tasks are empty, no new tasks will be generated.
|
||||
07:45:21.301 WORLD : UpdateEntities
|
||||
07:45:21.301 WORLD : Frame
|
||||
07:45:21.301 SCRIPT : SCR_BaseGameMode::OnGameStateChanged = GAME
|
||||
07:45:21.449 WORLD : UpdateEntities
|
||||
07:45:21.449 WORLD : PostFrame
|
||||
07:45:21.449 GUI : WidgetManager: CrateWidgets @"{D89BBA18F99053D6}UI/layouts/HUD/Chat/ChatHud.layout"
|
||||
07:45:21.449 SCRIPT (W): EditBoxFilterComponent used on invalid widget type.
|
||||
07:45:21.495 RESOURCES : GetResourceObject @"{20A6917D2114E29A}UI/layouts/HUD/Hint/HintInfoDisplay.layout"
|
||||
07:45:21.495 GUI : Layout load @"{20A6917D2114E29A}UI/layouts/HUD/Hint/HintInfoDisplay.layout"
|
||||
07:45:21.495 GUI : Widget prefab @"{EA1CC57D868E94F9}UI/layouts/HUD/Hint/Hint.layout"
|
||||
07:45:21.495 GUI (W): Overridden prefab member (GUID: '{661AB14E0F471C66}' type: ButtonWidgetClass) no longer exists in prefab
|
||||
07:45:21.665 RENDER : RENDER : ObjectsHeightMap::Build
|
||||
07:45:21.665 RENDER : RENDER : MeshOccupancyGridManager::GenerateAllForWorld
|
||||
07:45:21.842 PROFILING : MeshOccupancyGridManager::GenerateAllForWorld took: 177.058800 ms
|
||||
07:45:21.849 PROFILING : ObjectsHeightMap::Build took: 184.474900 ms
|
||||
07:45:22.957 SCRIPT : Rereintroduced [sites]: cache clearance position=<6086,211.538,7160> clear=1
|
||||
07:45:22.971 SCRIPT : Rereintroduced [sites]: authored everon-prison-1 at <6090,211.444,7160>
|
||||
07:45:22.972 SCRIPT : Rereintroduced [sites]: cache clearance position=<6150,203.288,7050> clear=1
|
||||
07:45:22.996 SCRIPT : Rereintroduced [sites]: authored everon-supply-1 at <6150,203.288,7050>
|
||||
07:45:22.998 SCRIPT : Rereintroduced [sites]: authored everon-radio-1 at <6500,159.756,7200>
|
||||
07:45:23.047 SCRIPT : Rereintroduced [sites]: authored everon-extraction-1 at <7000,65.2562,7500>
|
||||
07:45:23.047 SCRIPT : Rereintroduced [sites]: cache clearance position=<5960,220.256,7220> clear=1
|
||||
07:45:23.053 SCRIPT : Rereintroduced [sites]: transport parking=<5960,220.256,7212> radius=4 terrainRange=0.8125 obstructed=0 clear=1
|
||||
07:45:23.087 SCRIPT : Rereintroduced [sites]: authored everon-supply-2 at <5960,220.256,7220>
|
||||
07:45:23.087 SCRIPT : Rereintroduced [sites]: cache clearance position=<6340,175.788,7400> clear=1
|
||||
07:45:23.088 SCRIPT : Rereintroduced [sites]: authored everon-medical-1 at <6340,175.788,7400>
|
||||
07:45:23.088 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.6,7300> clear=1
|
||||
07:45:23.091 SCRIPT : Rereintroduced [sites]: cache clearance position=<6740,140.913,7296> clear=1
|
||||
07:45:23.092 SCRIPT : Rereintroduced [sites]: cache clearance position=<6736,140.975,7300> clear=1
|
||||
07:45:23.092 SCRIPT : Rereintroduced [sites]: cache clearance position=<6744,140.288,7300> clear=1
|
||||
07:45:23.093 SCRIPT : Rereintroduced [sites]: authored everon-outpost-1 at <6740,140.6,7300>
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-prison-1 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-1 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-radio-1 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-extraction-1 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-supply-2 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.093 SCRIPT : Rereintroduced [guards]: initial site=everon-outpost-1 requested=6 physical=0 conscious=0 nativeComplete=0
|
||||
07:45:23.921 WORLD : UpdateEntities
|
||||
07:45:23.921 WORLD : Frame
|
||||
07:45:23.921 ENTITY : SpawnEntityPrefab @"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"
|
||||
07:45:23.921 ENTITY : Create entity @"ENTITY:4611686018427388723" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <6125.000000 209.937500 7160.000000> @"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"
|
||||
07:45:23.921 ENGINE (F): Crashed
|
||||
07:45:24.362 WORLD : UpdateEntities
|
||||
07:45:24.362 WORLD : Frame
|
||||
07:45:24.362 ENTITY : SpawnEntityPrefab @"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"
|
||||
07:45:24.362 ENTITY : Create entity @"ENTITY:4611686018427388723" ('SCR_ChimeraCharacter','Assets/Characters/Basebody/Basebody_Male_01.xob') at <6125.000000 209.937500 7160.000000> @"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"
|
||||
07:45:24.362 RENDER : ----------------------------------------------------------------
|
||||
07:45:24.362 RENDER : ----------------------------------------------------------------
|
||||
07:45:24.362 RENDER : Rend: Fps:1000000.00 (0.00ms) | Present 0.00ms | Wait4GPU 0.00ms (graphical 0.00 + copy 0.00) | defrag 0.00ms
|
||||
07:45:24.362 RENDER : Rend: DP:0000 DPI:0000 DPR:0000 DPID:0000 Tri:00000 Vert:000000 CSRun:00|AllV:00x(00000) AllI:00x(00000) BegV:00x(00000) BegI:00x(00000)|TRes:0138
|
||||
07:45:24.362 RENDER : GPU DXGI: VRAM 1222MB(13176MB) | System 142MB(63702MB) | AMD Radeon RX 6950 XT (RADV NAVI21)
|
||||
07:45:24.362 RENDER : ----------------------------------------------------------------
|
||||
07:45:25.048 ENGINE (E): Application crashed! Generated memory dump: Z:/tmp/erri-game-profile/logs/logs_2026-09-19_07-45-05\ArmaReforgerSteam_2026-09-19_07-45-24.mdmp
|
||||
07:45:25.447 CRASH REPORT : Crash reporter started!
|
||||
07:45:25.449 CRASH REPORT : Sending analytical data.
|
||||
07:45:25.449 CRASH REPORT : Sending Request...
|
||||
07:45:25.722 CRASH REPORT : Crash Analytics: OK
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user