Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"hq.patch": "3d49bf30d224270d510f7f33c0a53a9ed84422138864c8328f0dee9b317ffa3e",
|
||||
"native-stock.patch": "edf981a2964a6880e8ab50ee017b4cddc7eafaca90932993e55e8299478b3737",
|
||||
"registration.patch": "1f3c0032e4b760e30e48ee84b1dad4dcc1c339472f2a35a2d24f339ac53859e8",
|
||||
"integrated.json": "918ea93a757010b293d395e0d54874bb674a91673f760c01d4449d0762006b40",
|
||||
"suite-inputs.json": "027cca967e11a10aa2ba88d90b525c27565e47aa248b079d4d2c4bac675b0bc1",
|
||||
"suite-result.json": "0d52088f3d9812a473de424cc623a895ed6e0d92f1b65d3054e7d2f5780dff19",
|
||||
"full-suite.log": "a3c4651724c1d4b926d42255938bf95541400d08fef9d9a88f893abbd2a6ca64",
|
||||
"preservation.json": "58aa186893f3c093215e9a8004a24a91649b5045e90cda59e63db50bb5b83f94",
|
||||
"normal.log": "2c2df456c7a647421091d7c6c1d5f28b56ef6dccdafe6d3de23b8c17c916f389",
|
||||
"review.json": "96ada10e5aab7e214fcd562e439575fe0bfb85f9eba9e2666a58ebc71c9896d0",
|
||||
"stock/fix.patch": "c7273b6800da3600cc49348000b139a5caaf50bc6395640d5ff59c674c0fdb43",
|
||||
"stock/source-manifest.json": "b89783db5e2ad1d70942a3b106d34400e65ec3fda3bc2e62e3386d572c740e68",
|
||||
"stock/report.json": "5abf69a94be0cd4490f8b9d473ee031876af4f317ff2b6dc53805b31cc4a0f3e",
|
||||
"stock/provenance-green.log": "e26ca35beb9bdd2800680a97f46df2693145f8ed2d63e42c745c73e3238d2205",
|
||||
"stock/baseline-feature-absence.log": "ee96c32a45ad254096dd0046f4d4411d7c7d8b7b71a2e17754665abb23d4bcf4",
|
||||
"stock/mutation-magazine-demand.log": "ab0fe2ac580e35331683845aeb0b42f7b0e57bfd3840f5e1cba3be57557da5b1",
|
||||
"stock/planning-green.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21",
|
||||
"courier/fix.patch": "c01e2c03b54a64c7546e291261418ec6524e79fc74bfa550b16a6c88620deaa3",
|
||||
"courier/source-manifest.json": "16efa4bc1772e09dc652537767f6f82b922977ea61650665c2cf8e70d9168c72",
|
||||
"courier/finding.json": "5e71cf4d8af368b7e44f14a443928edc278d3a2a882266a7ed88c0cec33b58ca",
|
||||
"courier/test-results.json": "ecbacd2cfd019fbff122ef67e2360bb93ab6d702ce976481e70010a759687de7",
|
||||
"courier/leaf-green.log": "897cec0577c062d00bb7ff774b52bb5147193d2752088deed78b84a2b235f4d5",
|
||||
"courier/loader-green.log": "491d5709202ea176318751587693c7929ef8f4710bbc00a1a27f3aa45ba0158b",
|
||||
"courier/lifecycle-green.log": "bd1d802374adb3a8f79548092031c42afa35f851b3219519a6f9b54aa77bfa9d",
|
||||
"courier/mutation-postcall.log": "a508e1e58b3d2608f6d86189bcd68dc3696b647aa0f46940021642c4f4e458bc",
|
||||
"courier/mutation-type.log": "c39e9864c4d77f1db02944be618c3641424ff3a6bd9b351d66b7c2ec20d27cf4",
|
||||
"independent/review.json": "765ab44f9534516bef448aeb2e9d1620d48b26452c34a79ce36afe7c4fd7cf6c",
|
||||
"independent/test.patch": "6489fe922e28489cf934536973275930fbbbe727c9f67da2592ac34233730a00",
|
||||
"independent/green.log": "54c4f20daef8efe2927372f274a749d4e9a5c7d87332233d6b2d18994adb0a78",
|
||||
"independent/mutation-red.log": "d75b0e11420dae2fbe88afa2375cb7b1e0a738f8b10eee32f6c147c5247d6ae6",
|
||||
"tested/tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
|
||||
"tested/tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
|
||||
"tested/tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
|
||||
"tested/tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083",
|
||||
"tested/tools/check.py": "6c1b5b24e759f7855058c9d82956f9ca0107a5311fdf9f7217129a86ecb62f5e",
|
||||
"tested/addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"tested/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"tested/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"tested/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"tested/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"tested/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"tested/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"scope": "Two existing production files and two existing tests; no native or target edits.",
|
||||
"behavior": [
|
||||
"One inert ready PMN4 follows existing magazine courier lifecycle with fixed MineCargo flag in job and each native leaf.",
|
||||
"Original paired magazine-worker compatibility remains default; mine porter requires same original/fit/ownership/utility guards but no rifle.",
|
||||
"Combined original site identities use same finite source/spent reservation; class-specific need controls planning and native delivery claim.",
|
||||
"DeliveredTo gates exact service/item/type and confirmed leaf; upstream AdmitDepotMine receives true type, verifies inert cargo/current demand/custody and uses separate mine import allowance.",
|
||||
"Every active job phase and pre/post native leaf submission verifies cargo readiness; native arming/change/Stop cannot admit/restart. Ambiguous surviving native identity retains old quarantine, terminal custody/deletion settles cleanup only.",
|
||||
"Radio hold/new stopped report/porter downlink, two native custody proofs, original worker return,96lifetime source cap and original deadlines unchanged."
|
||||
],
|
||||
"tests": {
|
||||
"loader": "actual SelectWorker/Plan/Tick/TransferValid/ClaimDelivery/DeliveredTo and upstream AdmitDepotMine; existing tests retained; green",
|
||||
"leaf": "complete actual class and callbacks/finite reservation; existing tests retained; green",
|
||||
"lifecycle": "unchanged existing actual HQ Tick/Stop test green against installed source; new HQ cargo admission test owned independently by player reviewer",
|
||||
"mutations": {
|
||||
"remove_post_native_cargo_check": {
|
||||
"exit": 1,
|
||||
"compiled_runtime_failure": true
|
||||
},
|
||||
"remove_import_type_gate": {
|
||||
"exit": 1,
|
||||
"compiled_runtime_failure": true
|
||||
},
|
||||
"existing_hq_lifecycle": {
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"boundaries": [
|
||||
"ReadyMine native component predicate is a documented boundary double; existing infantry-mine suite covers that predicate.",
|
||||
"Loader Valid/ownership and leaf APIs have declared native/service doubles; tests execute changed controller methods and actual import with current upstream source.",
|
||||
"No physical courier movement, PMN4 inventory transfer/arming, MP or performance claim.",
|
||||
"No native callbacks or force/state/stock mutation introduced outside existing one-item paths."
|
||||
],
|
||||
"external_api_dependencies": [
|
||||
"SiteService.DepotItemCount/DepotItem with combined DepotStock/DepotOriginal",
|
||||
"InfantryResupply.DepotMineNeeded/AdmitDepotMine calls DeliveredTo(service,item,true)",
|
||||
"GroundDepotHQ.ReserveGroundDepot optional final mineCargo=false"
|
||||
],
|
||||
"logs": {
|
||||
"leaf-green.log": "897cec0577c062d00bb7ff774b52bb5147193d2752088deed78b84a2b235f4d5",
|
||||
"loader-green.log": "491d5709202ea176318751587693c7929ef8f4710bbc00a1a27f3aa45ba0158b",
|
||||
"lifecycle-green.log": "bd1d802374adb3a8f79548092031c42afa35f851b3219519a6f9b54aa77bfa9d",
|
||||
"mutation-postcall.log": "a508e1e58b3d2608f6d86189bcd68dc3696b647aa0f46940021642c4f4e458bc",
|
||||
"mutation-type.log": "c39e9864c4d77f1db02944be618c3641424ff3a6bd9b351d66b7c2ec20d27cf4"
|
||||
},
|
||||
"compiler_work_finished": true
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c
|
||||
@@ -96,6 +96,8 @@
|
||||
protected bool m_PickedUp;
|
||||
protected bool m_DeliveryClaimed;
|
||||
protected bool m_Imported;
|
||||
+ protected bool m_MineCargo;
|
||||
+ bool MineCargo() { return m_MineCargo; }
|
||||
void ERR_GroundDepotLoading(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; m_Mode = mode; }
|
||||
bool Busy() { return m_State != 0; }
|
||||
bool Unresolved() { return m_Move && m_Move.Unresolved(); }
|
||||
@@ -138,6 +140,7 @@
|
||||
}
|
||||
protected bool Valid()
|
||||
{
|
||||
+ if (!ERR_GroundDepotTransfer.Cargo(m_Item, m_MineCargo)) return false;
|
||||
if (!Active() || !m_Service || m_Service.Task() != m_Task || !m_Service.DepotCurrent() || m_Service.DepotTruck() != m_Truck) return false;
|
||||
if (!m_Task || !m_Task.Receipt || !m_Task.Receipt.Consumed || m_Task.Vehicles.Count() != 6 || m_Task.Vehicles[1] != m_Truck) return false;
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Task);
|
||||
@@ -174,7 +177,7 @@
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
return items.Count() <= 128 && items.Contains(item);
|
||||
}
|
||||
- protected bool SelectWorker(ERR_HQUnit crew, IEntity item)
|
||||
+ protected bool SelectWorker(ERR_HQUnit crew, IEntity item, bool mineCargo = false)
|
||||
{
|
||||
if (!item || !Quiet(crew) || crew.HomeGuard || crew.ReservedForSupport || crew.LogisticsReservation > 0) return false;
|
||||
if (crew.Assignment || crew.Task || crew.PendingTask || crew.PendingOrder || crew.Downlink || crew.Waypoint) return false;
|
||||
@@ -186,7 +189,7 @@
|
||||
if (!actor || !crew.StatusSampler.CanAttribute(slot, actor, false) || !ERR_EnemyEquipmentRules.Eligible(m_Mode, crew.Group, actor) || CompartmentAccessComponent.GetVehicleIn(actor)) continue;
|
||||
SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(actor));
|
||||
if (!agent || !agent.m_UtilityComponent || !agent.m_UtilityComponent.m_AIInfo) continue;
|
||||
- if (!ERR_InfantryAmmoTransfer.Compatible(actor, item)) continue;
|
||||
+ if (!mineCargo && !ERR_InfantryAmmoTransfer.Compatible(actor, item)) continue;
|
||||
m_Worker = actor; m_WorkerSlot = slot; m_Utility = agent.m_UtilityComponent; return true;
|
||||
}
|
||||
return false;
|
||||
@@ -198,7 +201,7 @@
|
||||
for (int index = 0; index < m_HQ.GroundSupplyCount() && index < 20; index++)
|
||||
{
|
||||
ERR_InfantryResupply service = m_HQ.GroundSupplyAt(index);
|
||||
- if (!service || !service.DepotNeeded()) continue;
|
||||
+ if (!service || (!service.DepotNeeded() && !service.DepotMineNeeded())) continue;
|
||||
ERR_ConvoyVehicle truck = service.DepotTruck();
|
||||
if (!truck || truck.SupplyToken > 0) continue;
|
||||
ERR_HQUnit donor = m_HQ.GroundUnit(truck.Group);
|
||||
@@ -208,28 +211,32 @@
|
||||
for (int siteIndex = 0; siteIndex < m_Mode.Sites().Count() && siteIndex < 64; siteIndex++)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().At(siteIndex);
|
||||
- if (!site || !site.Definition || m_Mode.Sites().DepotMagazineCount(site) <= 0) continue;
|
||||
+ if (!site || !site.Definition || m_Mode.Sites().DepotItemCount(site) <= 0) continue;
|
||||
// The camp is an authored own location; only the truck position is reported.
|
||||
if (vector.DistanceXZ(site.Definition.Position, report.Position) > 150) continue;
|
||||
ERR_HQUnit crew = m_HQ.GroundUnit(site.Responders.Group);
|
||||
- for (int itemIndex = 0; itemIndex < m_Mode.Sites().DepotMagazineCount(site) && itemIndex < 96; itemIndex++)
|
||||
+ for (int itemIndex = 0; itemIndex < m_Mode.Sites().DepotItemCount(site) && itemIndex < 96; itemIndex++)
|
||||
{
|
||||
- IEntity item = m_Mode.Sites().DepotMagazine(site, itemIndex);
|
||||
- if (!m_Original.Contains(item) || m_Spent.Contains(item) || !ERR_GroundDepotTransfer.Magazine(item) || !Stored(item, site.Container)) continue;
|
||||
+ IEntity item = m_Mode.Sites().DepotItem(site, itemIndex);
|
||||
+ bool mineCargo = ERR_InfantryMineTransfer.ReadyMine(item);
|
||||
+ if (mineCargo) { if (!service.DepotMineNeeded()) continue; }
|
||||
+ else if (!service.DepotNeeded()) continue;
|
||||
+ if (!m_Original.Contains(item) || m_Spent.Contains(item) || !ERR_GroundDepotTransfer.Cargo(item, mineCargo) || !Stored(item, site.Container)) continue;
|
||||
// Select an original worker for this exact item; an incompatible first
|
||||
// member must not hide a later eligible carrier of finite camp stock.
|
||||
- if (!SelectWorker(crew, item)) continue;
|
||||
+ if (!SelectWorker(crew, item, mineCargo)) continue;
|
||||
int token = 300000 + m_Attempts + 1;
|
||||
- if (!m_HQ.ReserveGroundDepot(crew, donor, service, token)) continue;
|
||||
+ if (!m_HQ.ReserveGroundDepot(crew, donor, service, token, mineCargo)) continue;
|
||||
m_Reservation = new ERR_FiniteMagazineReservation(m_Original, m_Spent, item);
|
||||
if (!m_Reservation.Reserve()) { m_HQ.ReleaseGroundDepot(crew, donor, truck, token); continue; }
|
||||
+ m_MineCargo = mineCargo;
|
||||
m_Attempts++; m_Token = token; m_Crew = crew; m_Donor = donor; m_Service = service; m_Task = service.Task(); m_Truck = truck;
|
||||
m_Site = site; m_Cache = site.Container; m_CachePosition = m_Cache.GetOrigin(); m_Item = item;
|
||||
m_CacheInventory = InventoryStorageManagerComponent.Cast(m_Cache.FindComponent(InventoryStorageManagerComponent));
|
||||
m_CrewRecord = m_Mode.Forces().FindGroup(crew.Group);
|
||||
m_PickedUp = false; m_DeliveryClaimed = false; m_Imported = false; m_HeldAt = -1;
|
||||
m_Deadline = Math.Min(now + 180000, report.ObservedAt + 240000); m_State = 1;
|
||||
- m_Order = m_HQ.Downlink(donor.Group, "DEPOT HOLD", "hold original truck for one finite camp magazine", report.MessageId);
|
||||
+ m_Order = m_HQ.Downlink(donor.Group, "DEPOT HOLD", "hold original truck for one finite camp item", report.MessageId);
|
||||
if (!m_Order) Abort("truck radio unavailable"); else Note("one original camp item reserved; awaiting truck hold radio");
|
||||
return;
|
||||
}
|
||||
@@ -260,7 +267,7 @@
|
||||
ClearAction();
|
||||
if (m_Reservation) m_Reservation.ReleaseUnsubmitted();
|
||||
if (m_HQ) m_HQ.ReleaseGroundDepot(m_Crew, m_Donor, m_Truck, m_Token);
|
||||
- m_State = 0; m_Token = 0; m_Order = null; m_Move = null; m_Reservation = null;
|
||||
+ m_State = 0; m_MineCargo = false; m_Token = 0; m_Order = null; m_Move = null; m_Reservation = null;
|
||||
m_Crew = null; m_Donor = null; m_Service = null; m_Task = null; m_Truck = null;
|
||||
m_Worker = null; m_Utility = null; m_Site = null; m_Cache = null; m_Item = null; m_CacheInventory = null; m_CrewRecord = null;
|
||||
}
|
||||
@@ -274,18 +281,20 @@
|
||||
void Stop() { if (m_Stopped) return; m_Stopped = true; Abort("depot service stopped; any submitted uncertainty retains original claims"); }
|
||||
bool TransferValid(ERR_GroundDepotTransfer operation)
|
||||
{
|
||||
- if (!operation || operation != m_Move || operation.Item() != m_Item || !Valid() || !Stationary() || !m_Truck.SupplyHeld) return false;
|
||||
+ if (!operation || operation != m_Move || operation.Item() != m_Item || operation.MineCargo() != m_MineCargo || !Valid() || !Stationary() || !m_Truck.SupplyHeld) return false;
|
||||
if (operation.Delivery()) return m_PickedUp && m_State == 5 && ERR_GroundDepotAccess.Clear(m_Truck.Entity, m_Worker);
|
||||
return !m_PickedUp && m_State == 4 && ERR_GroundDepotAccess.Clear(m_Cache, m_Worker);
|
||||
}
|
||||
bool ClaimDelivery(ERR_GroundDepotTransfer operation)
|
||||
{
|
||||
if (!TransferValid(operation) || !operation.Delivery() || m_DeliveryClaimed || !m_Reservation.CommittedFor(m_Item)) return false;
|
||||
+ if (m_MineCargo) { if (!m_Service.DepotMineNeeded()) return false; }
|
||||
+ else if (!m_Service.DepotNeeded()) return false;
|
||||
m_DeliveryClaimed = true; return true;
|
||||
}
|
||||
- bool DeliveredTo(ERR_InfantryResupply service, IEntity item)
|
||||
- {
|
||||
- return !m_Imported && m_State == 5 && service == m_Service && item == m_Item && m_Move && m_Move.Delivery()
|
||||
+ bool DeliveredTo(ERR_InfantryResupply service, IEntity item, bool mineCargo = false)
|
||||
+ {
|
||||
+ return mineCargo == m_MineCargo && !m_Imported && m_State == 5 && service == m_Service && item == m_Item && m_Move && m_Move.Delivery() && m_Move.MineCargo() == m_MineCargo
|
||||
&& m_Move.Confirmed() && m_Reservation && m_Reservation.CommittedFor(item) && Valid();
|
||||
}
|
||||
void Tick(float now)
|
||||
@@ -315,7 +324,7 @@
|
||||
if (!ERR_InfantryResupplyRules.Fresh(report, now) || report.ObservedAt < m_HeldAt) return;
|
||||
if (vector.DistanceXZ(report.Position, m_Site.Definition.Position) > 150) { Abort("reported stopped truck outside camp service range"); return; }
|
||||
m_TruckPosition = report.Position + "3 0 0";
|
||||
- m_Order = m_HQ.Downlink(m_Crew.Group, "DEPOT COURIER", string.Format("carry one existing magazine from camp to stopped truck at %1", m_TruckPosition), report.MessageId);
|
||||
+ m_Order = m_HQ.Downlink(m_Crew.Group, "DEPOT COURIER", string.Format("carry one existing item from camp to stopped truck at %1", m_TruckPosition), report.MessageId);
|
||||
if (!m_Order) { Abort("porter radio unavailable"); return; }
|
||||
m_State = 3; return;
|
||||
}
|
||||
@@ -333,7 +342,7 @@
|
||||
if (delivery) { source = m_Worker; destination = m_Truck.Entity; }
|
||||
IEntity access = m_Cache; if (delivery) access = m_Truck.Entity;
|
||||
if (!ERR_GroundDepotAccess.Clear(access, m_Worker)) return;
|
||||
- m_Move = new ERR_GroundDepotTransfer(this, source, destination, m_Item, m_Reservation, delivery);
|
||||
+ m_Move = new ERR_GroundDepotTransfer(this, source, destination, m_Item, m_Reservation, delivery, m_MineCargo);
|
||||
}
|
||||
int moved = m_Move.Tick(now);
|
||||
if (moved == 0) return;
|
||||
@@ -344,9 +353,12 @@
|
||||
if (!Walk(m_TruckPosition)) { Abort("porter cannot walk to reported truck"); return; }
|
||||
m_State = 5; return;
|
||||
}
|
||||
- if (!m_Service.AdmitDepot(this, m_Item)) { Abort("proved physical delivery could not enter finite truck allowance"); return; }
|
||||
+ bool admitted;
|
||||
+ if (m_MineCargo) admitted = m_Service.AdmitDepotMine(this, m_Item);
|
||||
+ else admitted = m_Service.AdmitDepot(this, m_Item);
|
||||
+ if (!admitted) { Abort("proved physical delivery could not enter finite truck allowance"); return; }
|
||||
m_Imported = true; m_Delivered++; m_Move = null;
|
||||
- Note("one original camp magazine physically delivered and admitted; porter returning to camp");
|
||||
+ Note("one original camp item physically delivered and admitted; porter returning to camp");
|
||||
if (!Walk(m_CachePosition + "2 0 0")) { Cleanup(); return; }
|
||||
m_State = 6;
|
||||
}
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c
|
||||
@@ -23,6 +23,7 @@
|
||||
protected ref ERR_FiniteMagazineReservation m_Reservation;
|
||||
protected ref ERR_GroundDepotCallback m_Callback;
|
||||
protected bool m_Delivery;
|
||||
+ protected bool m_MineCargo;
|
||||
protected bool m_Submitted;
|
||||
protected int m_Ack;
|
||||
protected int m_State;
|
||||
@@ -30,9 +31,9 @@
|
||||
protected int m_Capacity;
|
||||
protected float m_Started = -1;
|
||||
protected float m_Last = -1;
|
||||
- void ERR_GroundDepotTransfer(ERR_GroundDepotLoading owner, IEntity source, IEntity destination, IEntity item, ERR_FiniteMagazineReservation reservation, bool delivery)
|
||||
+ void ERR_GroundDepotTransfer(ERR_GroundDepotLoading owner, IEntity source, IEntity destination, IEntity item, ERR_FiniteMagazineReservation reservation, bool delivery, bool mineCargo = false)
|
||||
{
|
||||
- m_Owner = owner; m_From = source; m_To = destination; m_Item = item; m_Reservation = reservation; m_Delivery = delivery;
|
||||
+ m_Owner = owner; m_From = source; m_To = destination; m_Item = item; m_Reservation = reservation; m_Delivery = delivery; m_MineCargo = mineCargo;
|
||||
if (!source || !destination || !item) return;
|
||||
m_Source = InventoryStorageManagerComponent.Cast(source.FindComponent(InventoryStorageManagerComponent));
|
||||
m_Destination = InventoryStorageManagerComponent.Cast(destination.FindComponent(InventoryStorageManagerComponent));
|
||||
@@ -51,6 +52,19 @@
|
||||
return magazine && !magazine.IsUsed() && magazine.GetMagazineWell() && magazine.GetAmmoCount() > 0
|
||||
&& magazine.GetAmmoCount() <= magazine.GetMaxAmmoCount() && magazine.GetMaxAmmoCount() <= 100000;
|
||||
}
|
||||
+ static bool Cargo(IEntity item, bool mineCargo = false)
|
||||
+ {
|
||||
+ if (mineCargo) return ERR_InfantryMineTransfer.ReadyMine(item);
|
||||
+ return Magazine(item);
|
||||
+ }
|
||||
+ protected bool CargoUnchanged()
|
||||
+ {
|
||||
+ if (!Cargo(m_Item, m_MineCargo)) return false;
|
||||
+ if (m_MineCargo) return true;
|
||||
+ BaseMagazineComponent magazine = BaseMagazineComponent.Cast(m_Item.FindComponent(BaseMagazineComponent));
|
||||
+ return magazine.GetAmmoCount() == m_Rounds && magazine.GetMaxAmmoCount() == m_Capacity;
|
||||
+ }
|
||||
+ bool MineCargo() { return m_MineCargo; }
|
||||
bool Submitted() { return m_Submitted; }
|
||||
bool Delivery() { return m_Delivery; }
|
||||
IEntity Item() { return m_Item; }
|
||||
@@ -102,18 +116,16 @@
|
||||
return true;
|
||||
}
|
||||
void Stop() { if (m_State == 0) m_State = -1; }
|
||||
- bool Confirmed() { return m_State == 1 && m_Ack == 1 && PhysicalProof(); }
|
||||
+ bool Confirmed() { return m_State == 1 && m_Ack == 1 && CargoUnchanged() && PhysicalProof(); }
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_State != 0) return m_State;
|
||||
if (!ERR_ForceRules.Finite(now) || now < 0 || now < m_Last) { Stop(); return m_State; }
|
||||
if (m_Started < 0) m_Started = now;
|
||||
m_Last = now;
|
||||
- if (now - m_Started >= 8000 || !m_Owner || !m_Owner.TransferValid(this) || !Magazine(m_Item)) { Stop(); return m_State; }
|
||||
+ if (now - m_Started >= 8000 || !m_Owner || !m_Owner.TransferValid(this) || !CargoUnchanged()) { Stop(); return m_State; }
|
||||
if (!m_From || !m_To || m_From.FindComponent(InventoryStorageManagerComponent) != m_Source
|
||||
|| m_To.FindComponent(InventoryStorageManagerComponent) != m_Destination) { Stop(); return m_State; }
|
||||
- BaseMagazineComponent magazine = BaseMagazineComponent.Cast(m_Item.FindComponent(BaseMagazineComponent));
|
||||
- if (magazine.GetAmmoCount() != m_Rounds || magazine.GetMaxAmmoCount() != m_Capacity) { Stop(); return m_State; }
|
||||
if (!m_Submitted)
|
||||
{
|
||||
if (!m_Reservation || !OriginalProof()) { Stop(); return m_State; }
|
||||
@@ -129,7 +141,7 @@
|
||||
}
|
||||
// Native callbacks may synchronously cancel the owner or this exact leaf.
|
||||
if (m_State != 0) return m_State;
|
||||
- if (!m_Owner || !m_Owner.TransferValid(this)) { Stop(); return m_State; }
|
||||
+ if (!m_Owner || !m_Owner.TransferValid(this) || !CargoUnchanged()) { Stop(); return m_State; }
|
||||
if (m_Ack < 0) { Stop(); return m_State; }
|
||||
if (m_Ack == 1 && PhysicalProof()) m_State = 1;
|
||||
return m_State;
|
||||
--- a/tests/test_ground_depot_loading.py
|
||||
+++ b/tests/test_ground_depot_loading.py
|
||||
@@ -4,9 +4,10 @@
|
||||
from policy_harness import ROOT,body,run
|
||||
BASE=Path(os.environ.get('ERR_DEPOT_ROOT',ROOT))
|
||||
P=BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c'
|
||||
-S=BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'
|
||||
+S=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
source=P.read_text()
|
||||
valid=body(P,'protected bool Valid(')
|
||||
+assert 'ERR_GroundDepotTransfer.Cargo(m_Item, m_MineCargo)' in valid
|
||||
assert 'm_Service.DepotCurrent()' in valid and 'DepotAvailable()' not in valid and 'DepotNeeded()' not in valid
|
||||
for forbidden in ('Teleport(', 'TrySpawn', 'SetAmmoCount', 'SetOrigin(', 'SetTransform('):assert forbidden not in source
|
||||
|
||||
@@ -15,12 +16,13 @@
|
||||
for t in ('ERR_HQUnit','ERR_InfantryResupply','ERR_ConvoyVehicle','ERR_HQWatchEntry','ERR_SiteRuntime','ERR_GroundDepotTransfer','ERR_GroundDepotLoading','ERR_FiniteMagazineReservation','SCR_ChimeraAIAgent'):
|
||||
s=re.sub(r'\b'+t+r' (\w+)',t+r'* \1',s)
|
||||
s=s.replace('ERR_FiniteMagazineReservation(m_Original, m_Spent, item)','ERR_FiniteMagazineReservation(&m_Original, &m_Spent, item)')
|
||||
- for ns in ('ERR_ForceRules','ERR_InfantryResupplyRules','ERR_GroundDepotTransfer','ERR_InfantryAmmoTransfer','ERR_GroundDepotAccess','ERR_Actors','ERR_EnemyEquipmentRules','CompartmentAccessComponent','Math'):
|
||||
+ for ns in ('ERR_ForceRules','ERR_InfantryResupplyRules','ERR_GroundDepotTransfer','ERR_InfantryAmmoTransfer','ERR_GroundDepotAccess','ERR_Actors','ERR_EnemyEquipmentRules','CompartmentAccessComponent','ERR_InfantryMineTransfer','Math'):
|
||||
s=s.replace(ns+'.',ns+'::')
|
||||
for n in ('m_HQ','m_Mode','m_Service','m_Move','m_Reservation','m_Order','m_Truck','m_Crew','m_Donor','m_Worker','m_Site','m_Cache','service','truck','donor','report','site','crew','operation','actor','agent'):
|
||||
s=re.sub(r'\b'+n+r'\.',n+'->',s)
|
||||
s=s.replace('crew->StatusSampler.', 'crew->StatusSampler->').replace('agent->m_UtilityComponent.', 'agent->m_UtilityComponent->')
|
||||
s=s.replace('SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(actor))', 'actor->agent')
|
||||
+ s=s.replace('InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent))','item->carried').replace('InventoryItemComponent carried','InventoryItem* carried').replace('carried.GetParentSlot()', 'carried->GetParentSlot()').replace('GetParentSlot().','GetParentSlot()->')
|
||||
s=s.replace('Sites().','Sites()->').replace('Watch().','Watch()->').replace('Forces().','Forces()->')
|
||||
s=s.replace('site->Responders.Group','site->Responders->Group').replace('site->Definition.Position','site->Definition->Position').replace('m_Site->Definition.Position','m_Site->Definition->Position')
|
||||
s=s.replace('m_Truck->Entity.GetOrigin()', 'm_Truck->Entity->GetOrigin()')
|
||||
@@ -28,8 +30,8 @@
|
||||
s=s.replace('InventoryStorageManagerComponent.Cast(m_Cache->FindComponent(InventoryStorageManagerComponent))','m_Cache->inventory')
|
||||
s=s.replace('"3 0 0"','Vec{3}').replace('"2 0 0"','Vec{2}')
|
||||
return s
|
||||
-methods='\n'.join(cpp(body(P,x)) for x in ('protected bool SelectWorker(', 'void Plan(', 'void Tick(', 'protected void Abort(', 'void Stop(', 'bool TransferValid(', 'bool ClaimDelivery(', 'bool DeliveredTo('))
|
||||
-admit=cpp(body(S,'bool AdmitDepot(')).replace('job.','job->').replace('m_Stock.Insert(item); Audit(', 'm_Stock.Insert(item); Audit(')
|
||||
+methods='\n'.join(cpp(body(P,x)) for x in ('bool MineCargo(', 'protected bool SelectWorker(', 'void Plan(', 'void Tick(', 'protected void Abort(', 'void Stop(', 'bool TransferValid(', 'bool ClaimDelivery(', 'bool DeliveredTo('))
|
||||
+admit=(cpp(body(S,'bool AdmitDepot('))+cpp(body(S,'bool AdmitDepotMine('))).replace('job.','job->').replace('m_Stock.Insert(item); Audit(', 'm_Stock.Insert(item); Audit(')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
@@ -42,13 +44,14 @@
|
||||
template<class...T>string Format(string s,T...){return s;}
|
||||
struct ERR_ForceRules{static bool Finite(float f){return std::isfinite(f);}};
|
||||
struct Math{static float Min(float a,float b){return std::min(a,b);}};
|
||||
+struct Entity;struct Slot{Entity*attached=nullptr;Entity*GetAttachedEntity(){return attached;}};struct InventoryItem{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct Group{int faction=1;};struct Inventory{};struct Utility{bool m_AIInfo=true;};struct SCR_ChimeraAIAgent{Utility*m_UtilityComponent=nullptr;};
|
||||
-struct Entity{Vec pos;Inventory*inventory=nullptr;bool stock=true,compatible=true,alive=true,player=false,aboard=false,attributed=true,equipmentEligible=true;int faction=1,well=1,rounds=30,maxRounds=30;Group*group=nullptr;SCR_ChimeraAIAgent*agent=nullptr;Vec GetOrigin(){return pos;}};using IEntity=Entity*;
|
||||
+struct Entity{Vec pos;Inventory*inventory=nullptr;bool stock=true,compatible=true,alive=true,player=false,aboard=false,attributed=true,equipmentEligible=true,mine=false,armed=false,defaultArmed=false,collision=true;InventoryItem*carried=nullptr;Entity*parent=nullptr;int faction=1,well=1,rounds=30,maxRounds=30;Group*group=nullptr;SCR_ChimeraAIAgent*agent=nullptr;Vec GetOrigin(){return pos;}};using IEntity=Entity*;
|
||||
struct Sampler{Array<IEntity>members;Group*group=nullptr;bool owns=true;int InitialStrength(){return members.Count();}bool OwnsRoster(Group*g){return owns&&g==group;}IEntity InitialMember(int i){return members[i];}bool CanAttribute(int i,IEntity a,bool){return a&&members[i]==a&&a->attributed&&a->group==group&&!a->player&&a->faction==group->faction;}};
|
||||
struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->alive;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity a){return a&&a->aboard;}};
|
||||
struct Definition{Vec Position;};struct ERR_SiteRuntime{struct Definition*Definition=nullptr;ERR_SiteRuntime*Responders=nullptr;struct Group*Group=nullptr;IEntity Container=nullptr;Array<IEntity>items;};
|
||||
-struct Sites{Array<ERR_SiteRuntime*>sites;int Count(){return sites.Count();}ERR_SiteRuntime*At(int i){return sites[i];}int DepotMagazineCount(ERR_SiteRuntime*s){return s?s->items.Count():0;}IEntity DepotMagazine(ERR_SiteRuntime*s,int i){return s->items[i];}};
|
||||
+struct Sites{Array<ERR_SiteRuntime*>sites;int Count(){return sites.Count();}ERR_SiteRuntime*At(int i){return sites[i];}int DepotItemCount(ERR_SiteRuntime*s){return s?s->items.Count():0;}IEntity DepotItem(ERR_SiteRuntime*s,int i){return s->items[i];}};
|
||||
struct ERR_HQUnit{struct Group*Group=nullptr;int ForceSourceId=0,LogisticsReservation=0;float NextStatus=0;bool eligible=true,HomeGuard=false,ReservedForSupport=false,Assignment=false,Task=false,PendingTask=false,PendingOrder=false,Downlink=false,Waypoint=false;Sampler*StatusSampler=nullptr;};
|
||||
struct ERR_ConvoyTask{};
|
||||
struct ERR_ConvoyVehicle{struct Group*Group=nullptr;IEntity Entity=nullptr;int SupplyToken=0;bool SupplyHeld=false;int clears=0;void ClearOrder(){clears++;}};
|
||||
@@ -63,36 +66,50 @@
|
||||
struct Route{int outcome=1,calls=0;int Advance(float,void*){calls++;return outcome;}};
|
||||
struct HQ{Array<ERR_InfantryResupply*>services;ERR_HQUnit*crew=nullptr,*donor=nullptr;struct Watch watch;Route route;bool claim=true,radio=true;int orders=0,releases=0,claims=0;
|
||||
int GroundSupplyCount(){return services.Count();}ERR_InfantryResupply*GroundSupplyAt(int i){return services[i];}ERR_HQUnit*GroundUnit(Group*g){return crew&&crew->Group==g?crew:donor&&donor->Group==g?donor:nullptr;}struct Watch*Watch(){return &watch;}void*Journal(){return this;}
|
||||
- bool ReserveGroundDepot(ERR_HQUnit*,ERR_HQUnit*,ERR_InfantryResupply*,int);
|
||||
+ bool ReserveGroundDepot(ERR_HQUnit*,ERR_HQUnit*,ERR_InfantryResupply*,int,bool=false);
|
||||
void ReleaseGroundDepot(ERR_HQUnit*c,ERR_HQUnit*d,ERR_ConvoyVehicle*t,int token){releases++;if(c&&c->LogisticsReservation==token)c->LogisticsReservation=0;if(d&&d->LogisticsReservation==token)d->LogisticsReservation=0;if(t&&t->SupplyToken==token){t->SupplyToken=0;t->SupplyHeld=false;}}
|
||||
Route*Downlink(Group*,string,string,int){orders++;return radio?&route:nullptr;}
|
||||
};
|
||||
// Native compatibility boundary double: pair-specific carried weapon well,
|
||||
// supported weapon flag, and sane positive ammo. Real Compatible's full native
|
||||
// weapon/muzzle/type/ownership logic remains covered by the transfer/planning suites.
|
||||
-struct ERR_InfantryAmmoTransfer{static bool Compatible(IEntity a,IEntity i){return a&&i&&i->compatible&&a->compatible&&a->well>0&&a->well==i->well&&i->rounds>0&&i->maxRounds>0&&i->rounds<=i->maxRounds;}};
|
||||
+struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity i,IEntity owner){return i&&i->parent==owner;}static bool Compatible(IEntity a,IEntity i){return a&&i&&i->compatible&&a->compatible&&a->well>0&&a->well==i->well&&i->rounds>0&&i->maxRounds>0&&i->rounds<=i->maxRounds;}};
|
||||
+struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity i){return i&&i->mine&&i->alive&&!i->armed&&!i->defaultArmed&&i->collision;}};
|
||||
struct ERR_GroundDepotAccess{static inline bool clear=true;static bool Clear(IEntity,IEntity){return clear;}};
|
||||
-struct ERR_GroundDepotTransfer{static inline int constructed=0;bool delivery=false,submitted=true,unknown=true,confirmed=false;int result=0;IEntity item;ERR_FiniteMagazineReservation*r;
|
||||
- ERR_GroundDepotTransfer(ERR_GroundDepotLoading*,IEntity,IEntity,IEntity i,ERR_FiniteMagazineReservation*q,bool d):delivery(d),item(i),r(q){constructed++;r->committed=true;}
|
||||
- static bool Magazine(IEntity i){return i&&i->stock;}bool Delivery(){return delivery;}IEntity Item(){return item;}bool Unresolved(){return submitted&&unknown;}bool Confirmed(){return confirmed;}void Stop(){result=-1;}int Tick(float){return result;}
|
||||
+struct ERR_GroundDepotTransfer{static inline int constructed=0;bool mineCargo=false,delivery=false,submitted=true,unknown=true,confirmed=false;int result=0;IEntity item;ERR_FiniteMagazineReservation*r;
|
||||
+ ERR_GroundDepotTransfer(ERR_GroundDepotLoading*,IEntity,IEntity,IEntity i,ERR_FiniteMagazineReservation*q,bool d,bool m=false):mineCargo(m),delivery(d),item(i),r(q){constructed++;r->committed=true;}
|
||||
+ static bool Magazine(IEntity i){return i&&i->stock&&!i->mine;}static bool Cargo(IEntity i,bool mine=false){return mine?ERR_InfantryMineTransfer::ReadyMine(i):Magazine(i);}bool MineCargo(){return mineCargo;}bool Delivery(){return delivery;}IEntity Item(){return item;}bool Unresolved(){return submitted&&unknown;}bool Confirmed(){return confirmed&&Cargo(item,mineCargo);}void Stop(){result=-1;}int Tick(float){return result;}
|
||||
};
|
||||
-struct ERR_InfantryResupply{bool available=true,needed=true;int m_DepotImports=0;ERR_ConvoyVehicle*truck=nullptr;ERR_ConvoyTask task;Array<IEntity>m_Stock,m_Spent;ERR_ConvoyVehicle*m_Truck=nullptr;
|
||||
- bool DepotAvailable(){return available&&m_Stock.Count()<96;}bool DepotNeeded(){return DepotAvailable()&&needed;}ERR_ConvoyVehicle*DepotTruck(){return available?truck:nullptr;}ERR_ConvoyTask*Task(){return &task;}bool Contains(IEntity,IEntity i){return i!=nullptr;}void Audit(string){}bool AdmitDepot(ERR_GroundDepotLoading*,IEntity);
|
||||
+struct ERR_InfantryResupply{bool available=true,needed=true,mineNeeded=false;int m_DepotImports=0,m_DepotMineImports=0;ERR_ConvoyVehicle*truck=nullptr;ERR_ConvoyTask task;Array<IEntity>m_Stock,m_MineStock,m_Spent;ERR_ConvoyVehicle*m_Truck=nullptr;
|
||||
+ bool DepotAvailable(){return available&&m_Stock.Count()<96;}bool DepotNeeded(){return DepotAvailable()&&needed;}bool DepotMineNeeded(){return available&&mineNeeded&&m_MineStock.Count()<96&&m_DepotMineImports==0;}ERR_ConvoyVehicle*DepotTruck(){return available?truck:nullptr;}ERR_ConvoyTask*Task(){return &task;}bool Contains(IEntity,IEntity i){return i!=nullptr;}void Audit(string){}bool AdmitDepot(ERR_GroundDepotLoading*,IEntity);bool AdmitDepotMine(ERR_GroundDepotLoading*,IEntity);
|
||||
};
|
||||
-struct ERR_GroundDepotLoading{HQ*m_HQ;Mode*m_Mode;Array<IEntity>m_Original,m_Spent;bool active=true,valid=true,stationary=true,canWalk=true,m_Stopped=false,m_Captured=false,m_PickedUp=false,m_DeliveryClaimed=false,m_Imported=false;int m_State=0,m_Attempts=0,m_Delivered=0,m_Token=0,m_WorkerSlot=0,walks=0,cleanups=0,notes=0;float m_NextPlan=0,m_Deadline=0,m_Last=-1,m_NextTick=0,m_HeldAt=-1;Vec m_CachePosition,m_TruckPosition;
|
||||
+struct ERR_GroundDepotLoading{HQ*m_HQ;Mode*m_Mode;Array<IEntity>m_Original,m_Spent;bool active=true,valid=true,stationary=true,canWalk=true,m_Stopped=false,m_Captured=false,m_PickedUp=false,m_DeliveryClaimed=false,m_Imported=false,m_MineCargo=false;int m_State=0,m_Attempts=0,m_Delivered=0,m_Token=0,m_WorkerSlot=0,walks=0,cleanups=0,notes=0;float m_NextPlan=0,m_Deadline=0,m_Last=-1,m_NextTick=0,m_HeldAt=-1;Vec m_CachePosition,m_TruckPosition;
|
||||
Utility*m_Utility=nullptr;ERR_HQUnit*m_Crew=nullptr,*m_Donor=nullptr;ERR_SiteRuntime*m_Site=nullptr;IEntity m_Worker=nullptr,m_Cache=nullptr,m_Item=nullptr;Inventory*m_CacheInventory=nullptr;void*m_CrewRecord=nullptr;ERR_InfantryResupply*m_Service=nullptr;ERR_ConvoyTask*m_Task=nullptr;ERR_ConvoyVehicle*m_Truck=nullptr;Route*m_Order=nullptr;ERR_GroundDepotTransfer*m_Move=nullptr;ERR_FiniteMagazineReservation*m_Reservation=nullptr;
|
||||
- bool Active(){return active&&!m_Stopped;}bool Busy(){return m_State!=0;}bool Unresolved(){return m_Move&&m_Move->Unresolved();}bool Valid(){return Active()&&valid&&(!m_Service||m_Service->available);}bool Stationary(){return stationary;}bool Quiet(ERR_HQUnit*u){return u&&u->eligible;}bool Stored(IEntity,IEntity){return true;}void Capture(){m_Captured=true;}void Note(string){notes++;}void ClearAction(){}bool Walk(Vec){walks++;return canWalk;}
|
||||
+ bool Active(){return active&&!m_Stopped;}bool Busy(){return m_State!=0;}bool Unresolved(){return m_Move&&m_Move->Unresolved();}bool Valid(){return Active()&&valid&&(!m_Service||m_Service->available)&&ERR_GroundDepotTransfer::Cargo(m_Item,m_MineCargo);}bool Stationary(){return stationary;}bool Quiet(ERR_HQUnit*u){return u&&u->eligible;}bool Stored(IEntity,IEntity){return true;}void Capture(){m_Captured=true;}void Note(string){notes++;}void ClearAction(){}bool Walk(Vec){walks++;return canWalk;}
|
||||
void Cleanup(){cleanups++;if(m_Reservation)m_Reservation->ReleaseUnsubmitted();m_HQ->ReleaseGroundDepot(m_Crew,m_Donor,m_Truck,m_Token);m_State=0;m_Token=0;m_Move=nullptr;m_Order=nullptr;}
|
||||
METHODS
|
||||
};
|
||||
ADMISSION
|
||||
-bool HQ::ReserveGroundDepot(ERR_HQUnit*c,ERR_HQUnit*d,ERR_InfantryResupply*s,int token){if(!claim||c->LogisticsReservation||d->LogisticsReservation||s->truck->SupplyToken)return false;claims++;c->LogisticsReservation=d->LogisticsReservation=s->truck->SupplyToken=token;return true;}
|
||||
-struct F{Mode mode;HQ hq;ERR_GroundDepotLoading job;Group cg,dg;ERR_HQUnit crew,donor;Definition def;ERR_SiteRuntime site,responders;Entity worker,second,cache,truck,item;Inventory inv;Utility workerUtility,secondUtility;SCR_ChimeraAIAgent workerAgent,secondAgent;Sampler sampler;ERR_ConvoyVehicle vehicle;ERR_InfantryResupply service;
|
||||
- F(){worker.group=second.group=&cg;workerAgent.m_UtilityComponent=&workerUtility;secondAgent.m_UtilityComponent=&secondUtility;worker.agent=&workerAgent;second.agent=&secondAgent;sampler.group=&cg;sampler.members={&worker};crew.StatusSampler=&sampler;truck.pos={20};crew.Group=&cg;donor.Group=&dg;hq.crew=&crew;hq.donor=&donor;vehicle.Group=&dg;vehicle.Entity=&truck;service.truck=service.m_Truck=&vehicle;hq.services={&service};site.Definition=&def;site.Responders=&responders;responders.Group=&cg;site.Container=&cache;site.items={&item};cache.inventory=&inv;mode.sites.sites={&site};job.m_HQ=&hq;job.m_Mode=&mode;job.m_Worker=&worker;job.m_Original={&item};ERR_GroundDepotAccess::clear=true;}
|
||||
+bool HQ::ReserveGroundDepot(ERR_HQUnit*c,ERR_HQUnit*d,ERR_InfantryResupply*s,int token,bool mineCargo){if(!(mineCargo?s->DepotMineNeeded():s->DepotNeeded())||!claim||c->LogisticsReservation||d->LogisticsReservation||s->truck->SupplyToken)return false;claims++;c->LogisticsReservation=d->LogisticsReservation=s->truck->SupplyToken=token;return true;}
|
||||
+struct F{Mode mode;HQ hq;ERR_GroundDepotLoading job;Group cg,dg;ERR_HQUnit crew,donor;Definition def;ERR_SiteRuntime site,responders;Entity worker,second,cache,truck,item;Inventory inv;Slot itemSlot;InventoryItem carriedItem;Utility workerUtility,secondUtility;SCR_ChimeraAIAgent workerAgent,secondAgent;Sampler sampler;ERR_ConvoyVehicle vehicle;ERR_InfantryResupply service;
|
||||
+ F(){itemSlot.attached=&item;carriedItem.slot=&itemSlot;item.carried=&carriedItem;item.parent=&truck;worker.group=second.group=&cg;workerAgent.m_UtilityComponent=&workerUtility;secondAgent.m_UtilityComponent=&secondUtility;worker.agent=&workerAgent;second.agent=&secondAgent;sampler.group=&cg;sampler.members={&worker};crew.StatusSampler=&sampler;truck.pos={20};crew.Group=&cg;donor.Group=&dg;hq.crew=&crew;hq.donor=&donor;vehicle.Group=&dg;vehicle.Entity=&truck;service.truck=service.m_Truck=&vehicle;hq.services={&service};site.Definition=&def;site.Responders=&responders;responders.Group=&cg;site.Container=&cache;site.items={&item};cache.inventory=&inv;mode.sites.sites={&site};job.m_HQ=&hq;job.m_Mode=&mode;job.m_Worker=&worker;job.m_Original={&item};ERR_GroundDepotAccess::clear=true;}
|
||||
+ void Mine(){item.mine=true;service.mineNeeded=true;service.needed=false;worker.compatible=false;}
|
||||
void Start(){job.Plan(0);assert(job.m_State==1&&hq.claims==1&&hq.orders==1);}
|
||||
void Reach(){Start();job.Tick(0);assert(job.m_State==2&&vehicle.SupplyHeld&&vehicle.clears==1);job.Tick(1000);assert(donor.NextStatus==1000&&job.walks==0);job.Tick(2000);assert(job.m_State==2);hq.watch.report.ObservedAt=3000;job.Tick(3000);assert(job.m_State==3&&hq.orders==2&&job.walks==0);job.Tick(4000);assert(job.m_State==4&&job.walks==1);}
|
||||
};
|
||||
int main(){
|
||||
+ // A mine-only deficit chooses the original porter without rifle compatibility,
|
||||
+ // but still follows both delivered radio orders and exact two-leg proof.
|
||||
+ {F f;f.Mine();f.Reach();assert(f.job.MineCargo()&&f.job.m_Worker==&f.worker);f.job.Tick(5000);auto*pick=f.job.m_Move;assert(pick->MineCargo());pick->unknown=false;pick->confirmed=true;pick->result=1;f.job.Tick(6000);f.job.Tick(7000);auto*drop=f.job.m_Move;assert(drop->MineCargo());drop->unknown=false;drop->confirmed=true;drop->result=1;assert(!f.service.AdmitDepot(&f.job,&f.item));f.job.Tick(8000);assert(f.job.m_State==6&&f.service.m_Stock.empty()&&f.service.m_MineStock.Count()==1&&f.service.m_DepotMineImports==1&&f.service.m_DepotImports==0);f.job.Tick(9000);assert(!f.job.Busy());}
|
||||
+ // Armed or changed cargo aborts at each active stage; uncertain native moves
|
||||
+ // retain claims until proof settles, and never import through a late callback.
|
||||
+ for(int phase=1;phase<=5;phase++){F f;f.Mine();if(phase<=2){f.Start();if(phase==2)f.job.Tick(0);}else{f.Reach();if(phase==3)f.job.m_State=3;if(phase==5){f.job.Tick(5000);f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);}}
|
||||
+ f.item.armed=true;f.job.Tick(10000);assert(!f.job.Busy()&&f.service.m_MineStock.empty()&&f.job.m_Delivered==0);}
|
||||
+ {F f;f.Mine();f.Reach();f.job.Tick(5000);auto*leaf=f.job.m_Move;f.item.armed=true;f.job.Tick(6000);assert(f.job.m_State==7&&f.crew.LogisticsReservation>0);leaf->unknown=false;leaf->confirmed=true;leaf->result=1;f.job.Tick(7000);assert(!f.job.Busy()&&f.service.m_MineStock.empty()&&f.job.m_Delivered==0&&f.job.m_Spent.Count()==1);}
|
||||
+ {F f;f.Mine();f.Reach();f.job.Tick(5000);f.job.m_Move->mineCargo=false;assert(!f.job.TransferValid(f.job.m_Move));}
|
||||
+ {F f;f.Mine();f.Reach();f.job.Tick(5000);f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);f.job.Tick(7000);f.service.mineNeeded=false;assert(!f.job.ClaimDelivery(f.job.m_Move));f.job.m_Move->unknown=false;f.job.m_Move->confirmed=true;f.job.m_Move->result=1;f.job.Tick(8000);assert(f.service.m_MineStock.empty()&&f.job.m_Delivered==0);}
|
||||
+ for(int kind=0;kind<5;kind++){F f;f.Mine();if(kind==0)f.item.armed=true;if(kind==1)f.item.defaultArmed=true;if(kind==2)f.item.alive=false;if(kind==3)f.item.collision=false;if(kind==4)f.service.mineNeeded=false;f.job.Plan(0);assert(!f.job.Busy()&&f.hq.orders==0&&f.hq.claims==0&&f.job.m_Attempts==0);}
|
||||
+
|
||||
// Actual Plan must enumerate worker/item pairs: the first fit original can
|
||||
// carry the wrong weapon while a second original can use this exact magazine.
|
||||
{F f;f.worker.well=2;f.second.well=1;f.sampler.members={&f.worker,&f.second};f.job.Plan(0);assert(f.job.m_State==1&&f.hq.claims==1&&f.hq.orders==1&&"compatible second original must permit planning despite incompatible first original");assert(f.job.m_Worker==&f.second&&f.job.m_WorkerSlot==1&&f.job.m_Item==&f.item&&f.job.m_Attempts==1);}
|
||||
@@ -134,5 +151,5 @@
|
||||
// A completed physical move cannot import wrong/previously-spent/foreign identity.
|
||||
{F f;f.Reach();f.job.Tick(5000);auto*l=f.job.m_Move;l->unknown=false;l->result=1;f.job.Tick(6000);f.job.Tick(7000);f.job.m_Move->unknown=false;f.job.m_Move->confirmed=true;Entity foreign;assert(!f.service.AdmitDepot(&f.job,&foreign));f.service.m_Spent.Insert(&f.item);assert(!f.service.AdmitDepot(&f.job,&f.item));}
|
||||
}
|
||||
-'''.replace('METHODS',methods).replace('ADMISSION',admit.replace('bool AdmitDepot(', 'bool ERR_InfantryResupply::AdmitDepot(')))
|
||||
+'''.replace('METHODS',methods).replace('ADMISSION',admit.replace('bool AdmitDepot(', 'bool ERR_InfantryResupply::AdmitDepot(').replace('bool AdmitDepotMine(', 'bool ERR_InfantryResupply::AdmitDepotMine(')))
|
||||
print('PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop')
|
||||
--- a/tests/test_ground_depot_transfer.py
|
||||
+++ b/tests/test_ground_depot_transfer.py
|
||||
@@ -9,7 +9,7 @@
|
||||
for kind,field in {'InventoryStorageManagerComponent':'inventory','InventoryItemComponent':'item','BaseMagazineComponent':'magazine','DamageManagerComponent':'damage'}.items():
|
||||
code=re.sub(kind+r'\.Cast\(([^;\n]*?)\.FindComponent\('+kind+r'\)\)',lambda m:m[1]+'.'+field,code)
|
||||
code=code.replace('.FindComponent('+kind+')','.'+field)
|
||||
-for name in ('EStoragePurpose','ERR_ForceRules','ERR_InfantryAmmoTransfer'):code=code.replace(name+'.',name+'::')
|
||||
+for name in ('EStoragePurpose','ERR_ForceRules','ERR_InfantryAmmoTransfer','ERR_InfantryMineTransfer'):code=code.replace(name+'.',name+'::')
|
||||
for name in ('m_Owner','m_From','m_To','m_Item','m_Source','m_Destination','m_FromSlot','m_FromStorage','m_ToStorage','m_Reservation','m_Callback','source','destination','item','inventoryItem','magazine','damage','inventory','storage','slot'):
|
||||
code=re.sub(r'\b'+name+r'\.',name+'->',code)
|
||||
code=code.replace(').',')->').replace('ERR_FiniteMagazineReservation ', 'ERR_FiniteMagazineReservation* ').replace('ERR_GroundDepotCallback ', 'ERR_GroundDepotCallback* ')
|
||||
@@ -31,12 +31,15 @@
|
||||
using IEntity=Entity*;using InventoryStorageManagerComponent=Inventory*;using InventoryStorageSlot=Slot*;using BaseInventoryStorageComponent=Storage*;using BaseMagazineComponent=Magazine*;using ERR_GroundDepotLoading=Owner*;
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};using InventoryItemComponent=Item*;
|
||||
struct Damage{bool destroyed=false;bool IsDestroyed(){return destroyed;}};using DamageManagerComponent=Damage*;
|
||||
-struct Entity{Entity*parent=nullptr;Item*item=nullptr;Magazine*magazine=nullptr;Damage*damage=nullptr;Inventory*inventory=nullptr;};
|
||||
+struct Entity{Entity*parent=nullptr;Item*item=nullptr;Magazine*magazine=nullptr;Damage*damage=nullptr;Inventory*inventory=nullptr;bool mine=false,armed=false,defaultArmed=false,collision=true;};
|
||||
struct Slot{Storage*storage=nullptr;IEntity attached=nullptr;Storage*GetStorage(){return storage;}IEntity GetAttachedEntity(){return attached;}};
|
||||
struct Storage{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
|
||||
struct Magazine{bool used=false,well=true;int rounds=30,capacity=30;bool IsUsed(){return used;}bool GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}};
|
||||
struct ERR_ForceRules{static bool Finite(float x){return std::isfinite(x);}};
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity e,IEntity root){for(int i=0;e&&i<16;i++,e=e->parent)if(e==root)return true;return false;}};
|
||||
+// ReadyMine is an explicit native-component boundary; its complete implementation
|
||||
+// is covered by infantry mine transfer tests. This models exact inert PMN4 state.
|
||||
+struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity e){return e&&e->mine&&e->damage&&!e->damage->destroyed&&!e->armed&&!e->defaultArmed&&e->collision;}};
|
||||
struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
|
||||
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnAllComplete(){}virtual void OnFailed(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
|
||||
struct ERR_GroundDepotTransfer;
|
||||
@@ -48,14 +51,35 @@
|
||||
bool TryMoveItemToStorage(IEntity,Storage*,int,ScriptedInventoryOperationCallback*cb){calls++;last=cb;if(effect)effect();if(ack==1)cb->OnComplete();if(ack==-1)cb->OnFailed();return accept;}};
|
||||
'''
|
||||
main=r'''
|
||||
-struct Fixture{Owner owner;Entity cache,porter,truck,mag,foreign;Inventory source,carry,cargo;Storage cs,ps,ts;Slot cslot,pslot,tslot;Item item;Magazine magazine;Damage damage;Array<IEntity>original,spent;ERR_FiniteMagazineReservation reservation;
|
||||
+struct Fixture{bool mine=false;Owner owner;Entity cache,porter,truck,mag,foreign;Inventory source,carry,cargo;Storage cs,ps,ts;Slot cslot,pslot,tslot;Item item;Magazine magazine;Damage damage;Array<IEntity>original,spent;ERR_FiniteMagazineReservation reservation;
|
||||
Fixture():reservation(&original,&spent,&mag){cache.inventory=&source;porter.inventory=&carry;truck.inventory=&cargo;source.owner=&cache;carry.owner=&porter;cargo.owner=&truck;cs.owner=&cache;ps.owner=&porter;ts.owner=&truck;source.storages={&cs};carry.storages={&ps};cargo.storages={&ts};carry.selected=&ps;cargo.selected=&ts;cslot.storage=&cs;pslot.storage=&ps;tslot.storage=&ts;cslot.attached=&mag;item.slot=&cslot;mag.item=&item;mag.magazine=&magazine;mag.damage=&damage;source.items={&mag};original={&mag};assert(reservation.Reserve());}
|
||||
- ERR_GroundDepotTransfer Pickup(){return {&owner,&cache,&porter,&mag,&reservation,false};}
|
||||
- ERR_GroundDepotTransfer Delivery(){return {&owner,&porter,&truck,&mag,&reservation,true};}
|
||||
+ ERR_GroundDepotTransfer Pickup(){return {&owner,&cache,&porter,&mag ,&reservation,false,mine};}
|
||||
+ ERR_GroundDepotTransfer Delivery(){return {&owner,&porter,&truck,&mag ,&reservation,true,mine};}
|
||||
void Pick(){source.items.clear();carry.items={&mag};cslot.attached=nullptr;pslot.attached=&mag;item.slot=&pslot;}
|
||||
void Deliver(){carry.items.clear();cargo.items={&mag};pslot.attached=nullptr;tslot.attached=&mag;item.slot=&tslot;}
|
||||
};
|
||||
int main(){
|
||||
+ // Ready inert PMN4 uses the same exact native two-leg custody protocol,
|
||||
+ // shared reservation and isolated callbacks, without a magazine component.
|
||||
+ {Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto a=f.Pickup();assert(a.MineCargo()&&a.Tick(0)==0&&a.Unresolved());f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==1&&a.Confirmed());auto b=f.Delivery();assert(b.MineCargo()&&b.Tick(2)==0&&f.owner.claims==1);f.Deliver();f.carry.last->OnComplete();assert(b.Tick(3)==1&&b.Confirmed()&&!b.Unresolved()&&f.spent.Count()==1);}
|
||||
+ // Every phase refuses changed/armed/default-armed/non-PMN4/destroyed identity.
|
||||
+ for(int phase=0;phase<3;phase++)for(int kind=0;kind<5;kind++){Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto a=f.Pickup();
|
||||
+ if(phase==1)assert(a.Tick(0)==0);
|
||||
+ if(phase==2){assert(a.Tick(0)==0);f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==1);}
|
||||
+ if(kind==0)f.mag.armed=true;
|
||||
+ if(kind==1)f.mag.defaultArmed=true;
|
||||
+ if(kind==2)f.mag.mine=false;
|
||||
+ if(kind==3)f.damage.destroyed=true;
|
||||
+ if(kind==4)f.mag.collision=false;
|
||||
+ if(phase==2){auto b=f.Delivery();assert(b.Tick(2)==-1&&!b.Submitted()&&f.carry.calls==0&&!a.Confirmed());}
|
||||
+ else{assert(a.Tick(1)==-1);assert(f.source.calls==(phase==1?1:0));if(phase==1)assert(a.Unresolved());}
|
||||
+ }
|
||||
+ // Inline native mutation after initial ready check cannot promote success.
|
||||
+ {Fixture f;f.mine=f.mag.mine=true;auto a=f.Pickup();f.source.ack=1;f.source.effect=[&]{f.Pick();f.mag.armed=true;};assert(a.Tick(0)==-1&&!a.Confirmed()&&!a.Unresolved());}
|
||||
+ {Fixture f;f.mine=f.mag.mine=true;auto a=f.Pickup();assert(a.Tick(0)==0);a.Stop();f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==-1&&!a.Confirmed()&&!a.Unresolved()&&f.source.calls==1&&f.spent.Count()==1);}
|
||||
+ {Fixture f;f.mine=f.mag.mine=true;f.source.accept=false;auto a=f.Pickup();assert(a.Tick(0)==-1&&a.Unresolved());f.damage.destroyed=true;assert(a.Unresolved());a.m_Item=nullptr;assert(!a.Unresolved()&&f.spent.Count()==1);}
|
||||
+ {Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto wrong=ERR_GroundDepotTransfer(&f.owner,&f.cache,&f.porter,&f.mag,&f.reservation,false,false);assert(wrong.Tick(0)==-1&&!wrong.Submitted()&&f.source.calls==0);}
|
||||
+
|
||||
{Fixture f;auto a=f.Pickup();a.Acknowledge(true);assert(a.m_Ack==0);assert(a.Tick(0)==0&&a.Submitted()&&a.Unresolved());assert(f.reservation.CommittedFor(&f.mag));f.source.last->OnComplete();assert(a.Tick(1)==0);f.Pick();assert(a.Tick(2)==1&&a.Confirmed()&&!a.Unresolved());auto b=f.Delivery();assert(b.Tick(3)==0&&f.owner.claims==1);f.source.last->OnAllComplete();assert(b.Tick(4)==0);f.Deliver();assert(b.Tick(5)==0);f.carry.last->OnAllComplete();assert(b.Tick(6)==1&&b.Confirmed()&&!b.Unresolved());assert(f.source.calls==1&&f.carry.calls==1&&f.spent.Count()==1);}
|
||||
{Fixture f;f.source.ack=1;f.source.accept=false;f.source.effect=[&]{assert(f.reservation.CommittedFor(&f.mag));assert(!f.reservation.ReleaseUnsubmitted());f.Pick();};auto a=f.Pickup();assert(a.Tick(0)==1&&!a.Unresolved());}
|
||||
{Fixture f;f.source.accept=false;auto a=f.Pickup();assert(a.Tick(0)==-1&&a.Unresolved());a.Stop();f.Pick();f.source.last->OnComplete();assert(!a.Unresolved()&&!a.Confirmed()&&a.Tick(1)==-1);}
|
||||
@@ -78,4 +102,4 @@
|
||||
'''.replace('switch(bad){case0:break;}','')
|
||||
main=main.replace(';if(bad', ';\n if(bad')
|
||||
run(pre+translated_reservation()+code+'\n'.join(callbacks)+main)
|
||||
-print('PASS: actual full depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified')
|
||||
+print('PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified')
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual depot HQ lifecycle, existing planner priority, server/mode/owner gates, idempotent polling and owner replacement
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop
|
||||
@@ -0,0 +1,12 @@
|
||||
check: /tmp/err-policy-98yuq0_j/check.cpp:252: int main(): Assertion `a.Tick(0)==-1&&!a.Confirmed()&&!a.Unresolved()' failed.
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-depot-mines-courier-1116/tests/test_ground_depot_transfer.py", line 104, in <module>
|
||||
run(pre+translated_reservation()+code+'\n'.join(callbacks)+main)
|
||||
~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-98yuq0_j/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1,19 @@
|
||||
check: /tmp/err-policy-7cwi9k0v/check.cpp:243: int main(): Assertion `!f.service.AdmitDepot(&f.job,&f.item)' failed.
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-depot-mines-courier-1116/tests/test_ground_depot_loading.py", line 35, in <module>
|
||||
run(r'''
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<116 lines>...
|
||||
}
|
||||
^
|
||||
'''.replace('METHODS',methods).replace('ADMISSION',admit.replace('bool AdmitDepot(', 'bool ERR_InfantryResupply::AdmitDepot(').replace('bool AdmitDepotMine(', 'bool ERR_InfantryResupply::AdmitDepotMine(')))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-7cwi9k0v/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": {
|
||||
"baseline_sha256": "dbc699f63d826aa6c57122483927e5092840f3fa6470f17f0acba710447b00ce",
|
||||
"proposed_sha256": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d"
|
||||
},
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": {
|
||||
"baseline_sha256": "1946db0615130b0039b42ec80db12d9cc89b1b3ca5a7eca7d9112eb69c3bdcea",
|
||||
"proposed_sha256": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652"
|
||||
},
|
||||
"tests/test_ground_depot_loading.py": {
|
||||
"baseline_sha256": "30bdc7b45671826296565908b313c0cdfff41698a2fc08deb519f96dafe6b43c",
|
||||
"proposed_sha256": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755"
|
||||
},
|
||||
"tests/test_ground_depot_transfer.py": {
|
||||
"baseline_sha256": "fc37626765919dd449432d445a17ec25a390ed687807571a1c5e2570c4ecddb7",
|
||||
"proposed_sha256": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36"
|
||||
}
|
||||
},
|
||||
"patch_sha256": "c01e2c03b54a64c7546e291261418ec6524e79fc74bfa550b16a6c88620deaa3"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"remove_post_native_cargo_check": {
|
||||
"exit": 1,
|
||||
"compiled_runtime_failure": true
|
||||
},
|
||||
"remove_import_type_gate": {
|
||||
"exit": 1,
|
||||
"compiled_runtime_failure": true
|
||||
},
|
||||
"existing_hq_lifecycle": {
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
PASS: actual objective overlay lifecycle preserves separate ownership, late readiness/reopen, data refresh, pan/zoom/culling, supported sibling/shared-frame parents, coordinate offsets, native task-clear isolation and terminal cleanup; native rendering remains unverified
|
||||
PASS: actual map element initializes each widget, retries missing widgets, updates position and changes only stale text/icon data; no native image-load claim
|
||||
PASS: actual native fixture root/config ownership and idempotent cleanup preserve foreign map, selector excludes ordinary route, fixed budgets/screenshots/UGC boundaries retained; native operations not executed
|
||||
PASS: actual full Inspect rejects canvas parenting, wrong active container/canvas, omitted origin offset, wrong rendered box and stale coordinates; differing origins and DPI accepted
|
||||
PASS: actual long-warning phases retain visible label through1500ms checkpoint then restore radio before close; synthetic marker separated from unmoved player
|
||||
PASS: actual Center places marker100screenpx left of pan center at both fixture zooms without altering disclosed coordinates
|
||||
PASS: missing, child-only, malformed, zero and duplicate prefab root IDs rejected
|
||||
PASS: delayed scene/inventory arrival, deferred preload, identity checks, stale replies, timeout and observer cleanup
|
||||
PASS: actual inventory manifest, delayed/missing/wrong-owner item links, finite cap, consumed-stock refresh and preload ordering
|
||||
PASS: spawn scene remains held through final acknowledgement and nearby use; leaving, reassignment, disconnect and teardown release it
|
||||
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
|
||||
PASS: actual protected/capped damage plus exact-actor terminal fixture bypass through delayed native damage, fail-closed ownership and untouched ordinary actor; no native claim
|
||||
PASS: actual full planner selection/commit body, 360 equivalence scenarios, orders/reservations/cooldowns identical; one128-unit scan vs >10000 repeated unit visits; no FPS claim
|
||||
PASS: actual observer monitor/recovery/cleanup rejects retained old controller, preserves new camera/editor/hints/timer, restarts once and retains normal recovery; native effects modeled from SDK, no runtime claim
|
||||
PASS: former chat controller releases only its own callbacks and preserves replacement menu; current-owner stop/scope and repeated teardown remain intact
|
||||
PASS: wrong observer fixture selector rejected before runtime/profile setup; no engine launched
|
||||
PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop
|
||||
PASS: actual depot HQ lifecycle, existing planner priority, server/mode/owner gates, idempotent polling and owner replacement
|
||||
PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled
|
||||
PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified
|
||||
PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption
|
||||
PASS: actual five random-radius diagnostic wrappers, disabled transparency, cached opt-in, exact zero and exclusion branch, native arguments/returns/outarg preservation, single superclass call and shared16-log cap
|
||||
PASS: zero-radius trace disabled by default, scoped before setup, exact opt-in emission; no native launch
|
||||
PASS: complete actual supply-travel probe, immutable 6+2 formations and 25 actors, admission/travel deadlines, six observed native-boundary moves, stop/ownership/partial-substitution refusals
|
||||
PASS: actual distinct supply-travel hook, fixed420s selector, original observer protection/restoration, failure/terminal cleanup and no legacy convoy setup
|
||||
PASS: actual supply-travel selector requires Chat, one round and480s; existing outcomes unaffected; no native launch
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept and --convoy-cover are mutually exclusive
|
||||
PASS: actual native interception witness requires real radio cursor/lineage, original actor identities, fixed movement/hold/expiry/resume and immutable deadline; no movement/delivery injection
|
||||
PASS: actual CLI rejects wrong mode/project/rounds/899s/conflict before runtime; valid flag and terminal branch identify synthetic-observation qualification
|
||||
PASS: visible base hook and actual fixture override delegate once; delivery proof uses retained pre-super route only on successful production transition
|
||||
actual mounted HQ dispatch planning, radio, ownership and lifecycle checks passed
|
||||
PASS: actual mounted intercept eligibility/order chronology, fixed destinations, native road selection bounds, width, segment heading, clearance and settlement delegation; no native driving claim
|
||||
PASS: actual paired arc geometry,40m/80m spacing, separate original polylines, both-position validation and128road/4096segment budget; no native driving proof
|
||||
PASS: actual pair admission, rollback, native allocation/revocation boundaries, per-member ownership, hold and expiry
|
||||
PASS: actual Tick clock initialization admits fractional first ticks and expires without extending the original start
|
||||
PASS: actual finite conservation/deadline/callback policies; read-only selection, bounded once-only inventory submission and no can refill; native transfer not executed
|
||||
PASS: actual exact-context membership, bounded identity/reach gates, native start/cache/eligibility ordering and no duplicate/foreign action start; fuel manager identity and empty-can headroom guards checked
|
||||
PASS: actual detached node/value snapshot and conservation refuse mismatched lengths before indexed reads, retain original identities under native out-array aliasing and log bounded counts once; native cause remains unknown
|
||||
PASS: actual mine evidence sealing/recovery, historical coarse publication, caps, canonical ownership, marker join retry/owner-change/stop; native arming and replicated vector-array transport untested
|
||||
PASS: actual full document recovery retains authored/sealed targets, one shared spent ledger, retry/exhaustion semantics and canonical multi-player ownership alongside supplemental mine intel
|
||||
PASS: actual infantry search suspension, quiet grace, finite resume, expiry/replacement and defensive/ownership boundaries
|
||||
PASS: infantry combat gate precedes radio delivery and preserves non-task transports
|
||||
PASS: actual HQ contact transition wakes only fit squad members, cancels only task orders and logs changes once
|
||||
PASS: actual finite medicine grants, authored stock deduction, full-backpack refusal/pouch fallback, no loot replenishment, unresolved-operation quarantine and ownership/stop guards
|
||||
PASS: only recent native detected/identified threats suspend hunter travel; stale/disarmed/destroyed contacts cannot strand patrols
|
||||
PASS: actual hunter combat transition cancels only its travel once, holds through renewed contact and resumes after quiet; unregistered startup preserved
|
||||
PASS: captured sighting retention, immutable details, expiry, replay rejection, bounded sound uncertainty/cooldown, radio loss, priority and overdue-status fairness
|
||||
PASS: arrow press/release, held keys, opposing keys, disabled/menu input and firearm-only retention
|
||||
PASS: town trigger and hard 700m exclusion for all observers, empty/invalid positions and final-check crossings
|
||||
PASS: exact finite site squads, invalid roster/count rejection, committed-site spacing and safe fallback boundary
|
||||
PASS: mortar couriers use the mobile site team and refuse permanent-only garrisons
|
||||
PASS: omitted preferred mortar depot selects a surviving owned camp/mobile team; no camp, foreign cache and permanent-only sites are unavailable; historical priority retained
|
||||
PASS: real-session mortar deadline, failed-support convoy admission and hunter survivor/recovery gates
|
||||
PASS: native-route retry preserves delivered target, limits attempts and suspends during combat
|
||||
PASS: stale/deleted AI utility cannot receive Complete; mortar HQ preflight withholds unsafe orders; mounted convoy cover never creates infantry Defend
|
||||
PASS: flight crew affiliation and group precede native boarding; preparation remains bounded even while passengers wait
|
||||
PASS: factionless/deleted map targets do not abort perception; faction lookup tolerates teardown; deleting helicopter releases without capture/engine access
|
||||
PASS: shoot adapter waits for a physical round; bounded same-shell retries, interrupted/never-started loads, committed no-retry, order/owner changes and normal native delegation
|
||||
PASS: missing/invalid faction crew defers before any native spawn or allowance insertion; all registered RHS factions have explicit soldier and medic profiles
|
||||
PASS: vehicle radio issued once; pending, refusal and looting cannot duplicate or fabricate a physical radio link
|
||||
PASS: actual vehicle-radio link requires the original seated crew, physical manpack and live uncaptured mission vehicle; looting, dismount, release and teardown remove it
|
||||
PASS: actual hunter release preserves survivors/HQ, releases driving ownership once, delegates capture/teardown, and excludes prison/patrol/mortar from generic objective defence
|
||||
PASS: actual player-entry hook latches original hunter capture before native callbacks; both release layers cancel ownership without new entities/refund; bounded current-owner guards and prior-release policy
|
||||
PASS: real opening road geometry enforces wide azimuths; fresh delivered contact preempts patrol cooldown, respects radio failures and does not starve in-flight interception
|
||||
PASS: actual scoped 10% tighter REGULAR aim error and alert perception; preserves equipment multiplier and restores vanilla behavior when unbound
|
||||
PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay
|
||||
PASS: bounded same-group empty-spawn retries, no casualty refill, queue retirement, delivery-gated intel, prepared-team reuse, throttled diagnostics and LOD release
|
||||
PASS: production airborne memory confidence, persistence, ground coverage, confirmed losses, artillery veto, cooldown and invalid-input rules
|
||||
PASS: production cover retains the carried HQ target until its deadline; airport reload waits until the drop pass and cover have finished
|
||||
PASS: air logistics reservation preserves delivered search until radio handoff, excludes guards/combat/in-flight orders, and quarantines unresolved native loads/moves
|
||||
PASS: actual ammunition cargo selector handles empty rifle/machinegun/sniper magazines, preserves loaded variants, excludes auxiliary launchers and tolerates missing native metadata
|
||||
PASS: original 15-minute launch/loss cadence, active/captured timer disarm, saved delay reset, stop, 300m orbit and bounded close-contact standoff at 30/60/120 Hz
|
||||
PASS: actual aircraft-removal notification guards owner/server/active/stop and schedules one full delay without replay extension
|
||||
PASS: actual helicopter delay applies resolved Random values, preserves countdown on save failure, and leaves active flights running
|
||||
PASS: hill prominence/elevation, actual road edges/heights/bends and server-only finite scout admission, pending stock, timeout and no replacements/refills
|
||||
PASS: mortar duty scope excludes players, other crews, stopped/client/inactive states; only destruction releases an active assignment, while the gunner may approach the gun
|
||||
PASS: random mode restrictions, full numeric ranges, independent calendar dates and strict daylight boundaries
|
||||
PASS: actual killais eligibility includes the 1000m boundary, excludes players/retained bodies/dead/non-character entities and checks full 3D distance
|
||||
PASS: actual generation scheduler bounds each tick, enforces deadline/candidate ceiling, validates fallback, commits only accepted positions, skips only dispensable sites, preserves required objectives/intel, and resets the next search budget
|
||||
PASS: terrain placement samples world bounds, retains streaming candidates, bounds waits/work, rejects foreign fallbacks, preserves objectives/intel and validates completion
|
||||
PASS: actual navigation readiness supports static meshes, yields only for loadable streaming tiles and refuses unreachable positions
|
||||
PASS: real sampling handles absent airports and extraction clearance preserves geometry/navigation/flatness while selecting the correct aircraft survey
|
||||
PASS: universal connector, embedded/standalone exports, multiple terrains, stable IDs, native nav configs, missing-nav visibility, path validation and overwrite protection
|
||||
PASS: airfield detection accepts physical runways/towers and bounded authored markers, rejects unrelated props, water and out-of-world markers, and samples terrain height
|
||||
PASS: configured airport parsing, bounded readiness, stale admission rejection and cleanup wiring
|
||||
PASS: automatic default, explicit header/CLI opt-out, editor/authored-mode guards, optional airport override precedence and fresh-round saving guard
|
||||
PASS: singleton identity guards, paired faction deserialization and client world-cleanup wiring
|
||||
PASS: task/map/respawn getters survive delayed old destruction and preserve ordinary-mode behavior
|
||||
PASS: replication hierarchy refuses absent/aliased nodes and establishes delivery dependencies idempotently
|
||||
PASS: standalone old faction delegates collected once, with null/deleted owners ignored
|
||||
PASS: actual terrain takeover startup skips mode-less/menu worlds, always forwards super, retains eligible/unsupported/authored/client/editor semantics
|
||||
PASS: native name callback preserves authored modes, opt-outs and failures; terrain suffix follows world changes, cached resolution and confirmed takeover metadata restores on cleanup without changing scenario resource or overwriting later titles
|
||||
PASS: actual terrain parent traversal, Armenhof/Nogova names, Everon alias, missing-resource fallback, empty names and bounded cycles/depth
|
||||
PASS: saved terrain GUIDs, defaults, restart persistence, clearing, backup recovery, corrupt-file preservation, write failures, and client write denial
|
||||
PASS: startup terrain capture protects client/editor/menu worlds, default behavior, same-map loads and reload-loop recovery
|
||||
PASS: actual transition waits for native startup, disconnects without bans, requires an empty session, retains every loaded mod, bounds waiting and consumes requests once
|
||||
PASS: actual faction resolution reserves explicit roles, samples without replacement, substitutes disabled selections, and rejects duplicate/unknown/missing choices and insufficient pools
|
||||
PASS: Random all submits persistent random roles immediately; manual mixed choices, stale/unauthorized UI guards and debounce preserved
|
||||
PASS: actual content policy gates parent packs, individual factions, faction identity and finite group rotation with vanilla fallback
|
||||
PASS: actual delivered road eligibility, ahead projection without chords, reservations, stock road query bounds, terrain/water/obstruction refusal and clean outputs
|
||||
PASS: actual delivered-task lineage, expiry, old-order retention, native commit, release, road precision expiry and duplicate delivery
|
||||
PASS: actual original-roster local handoff,100m3D bound,busy carrier/budget exclusion,origin interruption including deletedsource,normal radio delivery and per-source replay history
|
||||
PASS: actual visual intake retains source/time/position/id, rejects replay, prefers usable own route, excludes simultaneous callers and conservatively resets negative-sweep dwell
|
||||
PASS: actual fixture local/radio gating, immutable source/time/position, interrupted-report exclusion and exact-owner cleanup
|
||||
PASS: local-handoff runner refuses wrong project/round count/insufficient deadline before runtime work
|
||||
PASS: actual fixture allocator terminal/unsubmitted guard, original-group lookup and both candidate gates
|
||||
PASS: actual report-derived waypoint insertion/order and tighter positive radii; no formation navigation claim
|
||||
PASS: actual Place/Stop waits native pose update, bounds four attempts, preserves original position, restores pending/settled placement and respects ownership/accepted-move quarantine
|
||||
PASS: actual fixture current/original recipient ownership, unresolved transfer cleanup, exact-token release and idempotent Stop
|
||||
PASS: actual fixture phased-cargo readiness, bounded callbacks, captured-stock mixed-caliber selection/continuation, reservation cleanup and component magazine counts
|
||||
PASS: actual inventory-fixture setup uses ordinary prison unlock before constructing its convoy-waiting probe; failed unlock cannot run fixture
|
||||
PASS: actual authored storage anchors, native trace flags, own-hierarchy exclusion, external wall/vehicle obstruction, range, unknown geometry and bounded context refusal
|
||||
PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup
|
||||
PASS: actual finite convoy supply pool; immutable slots, shared demand state, sparse/capped discovery and permanent shutdown
|
||||
PASS: actual HQ rotates finite donors, skips unavailable/contacted trucks, uses delivered reports and dispatches at most one trip per planning cadence
|
||||
PASS: actual original turret identity, native/canonical guards, scoped maximum-skill profile, reset, dismount/reboard, requested-skill preservation and restoration
|
||||
PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines
|
||||
PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths
|
||||
PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged
|
||||
PASS: actual read migrates old valid settings, preserves explicit disabled state, rejects invalid data; next-round feedback and fixed menu remain honest
|
||||
PASS: actual automatic convoy timing/authority/admission/one-attempt/manual-task/stop policy; native deployment unproved
|
||||
PASS: late authoritative failure reason refreshes open result; detach, mode change and success subscriptions preserved
|
||||
infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed
|
||||
PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership
|
||||
PASS: actual designated zero/one original carrier selection, settled startup, shared finite claims, no refund after submission
|
||||
PASS: actual HQ startup grant readiness forwarding is authoritative and fail-closed
|
||||
PASS: actual finite PMN4 designated-zero/one entitlement, pinned original ownership, shared commit, physical custody, callback quarantine/deletion and no retry
|
||||
PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries
|
||||
PASS: actual shared finite identity reservation; competing consumers, submission permanence, stale cleanup and96-item bound
|
||||
PASS: actual carried-mounted swap, shared committed claim, physical slot reach, exact two-way proof, uncertainty and terminal cleanup
|
||||
PASS: actual mounted pickup, exact finite ownership, pre-submission commit, physical custody, bounded callback and quarantine lifecycle; no native coverage claim
|
||||
PASS: actual mounted courier admission, radio, individual orders, two-stage transfer, reboarding, token cleanup and quarantine lifecycle
|
||||
PASS: actual scoped crew permit and native board completion/failure preserves foreign seats without teleport fallback
|
||||
PASS: actual shared mounted stock/history ownership, atomic exact HQ pair claim, and bounded stopped-owner proof polling
|
||||
PASS: actual carried/mounted early ammunition policy and status-first shared uplink; complete threshold, phases, cooldown, failures requested check-ins and non-urgent detached carried-mine status
|
||||
PASS: actual group radio startup preservation, finite native grants, callback quarantine, frozen selection/actor ownership and bounded observation
|
||||
PASS: actual maintenance native-stock check rejects missing/duplicate/wrong-identity/unowned/depleted/malformed stock and is read-only; native runtime not executed
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 0.231s
|
||||
|
||||
OK
|
||||
PASS: actual radio node rejects current incapacitation, death, ownership and faction changes despite cached inventory; one-second capability refresh remains explicit
|
||||
PASS: Southern finite maintenance stock preserves weapons/clues and optional transport, historical Western fixture stays separate; native capacity/consumption untested
|
||||
PASS: optional transport deferred behind required readiness, bounded once-only spawn/omission, isolated cleanup, occupied-candidate retention and required-default preservation
|
||||
PASS: actual diagnostic fallback runs only on failed missing-context call, derives unique native pilot door, preserves stock eligibility and restores prior index on success/failure; diagnostics mutate no game state.
|
||||
PASS: actual native-prelude cleanup restores only original changed damage, refuses stale/incapacitated/aboard teleport; bounded five-seat/four-door fixture wiring checked. Native execution remains pending.
|
||||
PASS: actual CreateTransport requires successful scoped Configure after handbrake, preserves ordinary vehicles, tracks spawned entity before failures and never treats failed lock registration as ready.
|
||||
PASS: actual preparation Configure guards/idempotence/breach preservation, security eligibility/final current-body server mutation and all scoped action guards; all five seat/four door resource overrides. Native hold, prefab merge, replication and boarding remain unverified.
|
||||
PASS: production vehicle alarm single trigger/replica completion/no replay, fixed deadline/readiness wait, failed audio, dedicated server, moving exact handle, destruction/native end/deletion/clock and mission teardown. Native sound and multiplayer delivery require engine qualification.
|
||||
PASS: production alarm emitter/receiver original time/location, explicit native queue only, 32-entry cap, 50m local witness eligibility, bound perception, native-super preservation; actual engine broadcast/hearing remains unverified.
|
||||
PASS: actual optional candidate barrier, exact callback/custody proof and unchanged mine/primary snapshots; no native transfer claim
|
||||
Native finite mine-stock runner: parser, scope, exclusions and command pass
|
||||
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
|
||||
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
|
||||
PASS: actual once-only native dry query, exact before/after slots, native refusal, shutdown; shared bounded discovery and distinct opt-in verdict
|
||||
PASS: actual completion selector and pre-cleanup variant capture preserve separate radio and eligibility verdicts
|
||||
PASS: actual cargo diagnostic stages separate absent/foreign magazines, used/empty/invalid rounds, well mismatch and exact truck storage/attachment without mutation
|
||||
PASS: actual native courier witness rejects missing radio/custody/swap/reboard evidence; CLI opt-in bounded; native success remains unqualified
|
||||
PASS: actual courier constructor/Tick waits for preparation, returns before physical checks, preserves fixed deadline and sticky stop/failure; Enfusion startup awaits native verification
|
||||
PASS: actual arranged native alarm fixture deadline, single emit, natural-route observation, original timestamp/area/detail assertions, natural observer proximity/activation wait, failure cleanup and independent canonical-body restoration; native delivery itself remains unqualified.
|
||||
PASS: actual convoy cover observation/snapshot/uplink/HOLD/RESUME/cleanup transitions; native boundaries mocked, non-convoy runner opt-in refused
|
||||
Enemy optics actual-service ownership, preservation, callback, deadline and bounded-inspection policies passed
|
||||
PASS: actual delivered cover freshness/lineage/replay and canonical executor; owned waypoint-only hold, one resume at preserved route index, invalid ownership/crew/ledger refusal and fail-closed native recreation
|
||||
PASS: actual Stinger show/set/help state precise actor-roll effects; read-only help, bounded values, malformed syntax and failed-save preservation; no rerolls/gameplay edits and no native persistence claim
|
||||
PASS: new/retasked search and radio delivery ammo gates; active tasks and delivered release preserved
|
||||
HQ convoy delivered-report planning and downlink regressions passed
|
||||
PASS: actual own-inventory ammo inspection deduplicates loaded/carried/shared wells, separates chambers/launchers, freezes scalar snapshots and treats unsupported/capped/foreign inventory as unknown
|
||||
PASS: actual carried PMN4 inventory, original-owner guards, bounded deduplication, independent unknown state and detached counts
|
||||
PASS: actual mounted hierarchy sampling, ownership exclusion, deduplication, completeness/caps, quarter threshold and detached validation; no runtime policy or ammunition mutation
|
||||
PASS: WORKBENCH opt-in diagnostics distinguish cycles/cap/storage/manager/mount failures without repeated native traversal
|
||||
PASS: actual HQ original convoy-root admission rejects wrong force/server/group and never supplies replacement lookup
|
||||
PASS: production mounted structural seat scan ignores >128 carried/cargo descendants, shares exact native mount/magazine ownership, preserves attachment seats and exact occupants, rejects unknown/cyclic/oversize structures; native binding still requires qualification.
|
||||
PASS: native body fixture uses existing immutable actors, real production LOS/queued uplink, pre-delivery isolation, actual status overlap, bounded cleanup and no fabricated reports/spawns
|
||||
PASS: actual native fixture lookup selects exact BODY kind/identity/message from bounded evaluations, never sighting-only Get
|
||||
PASS: actual ammo snapshot comparison checks every scalar/category flag; native probe requires real roster rescan, loaded-round lower bound and separate immutable pending/Watch objects
|
||||
PASS: actual delivered slot-union bodies preserve overlap/disjoint evidence, replay idempotence, status subset integrity, full-wipe closure and formation-local bounds
|
||||
test_review_added_allowed_media_invalidates_snapshot (__main__.ReviewTests.test_review_added_allowed_media_invalidates_snapshot) ... ok
|
||||
test_review_added_source_directory_rejected (__main__.ReviewTests.test_review_added_source_directory_rejected) ... ok
|
||||
test_review_loose_root_resource_and_symlink_rejected (__main__.ReviewTests.test_review_loose_root_resource_and_symlink_rejected) ... ok
|
||||
test_review_metadata_media_and_sidecars_remain_allowed_and_bound (__main__.ReviewTests.test_review_metadata_media_and_sidecars_remain_allowed_and_bound) ... ok
|
||||
test_review_missing_link_rejected (__main__.ReviewTests.test_review_missing_link_rejected) ... ok
|
||||
test_review_package_guard_sees_new_scripts (__main__.ReviewTests.test_review_package_guard_sees_new_scripts) ... ok
|
||||
test_review_retargeted_private_link_rejected (__main__.ReviewTests.test_review_retargeted_private_link_rejected) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.066s
|
||||
|
||||
OK
|
||||
PASS: actual report methods reproduce old starvation; status-first scheduler delivers check-ins and requires 30s without combat or actual visible contacts before negative reports
|
||||
PASS: actual actor group lookup retains controlled character membership when seated/inherited vehicle agents differ; missing control or parent refuses
|
||||
.................
|
||||
----------------------------------------------------------------------
|
||||
Ran 17 tests in 3.363s
|
||||
|
||||
OK
|
||||
PASS: actual convoy motion thresholds, native-only proof boundaries, physical cargo/crew ownership and pre-launch runner restrictions
|
||||
PASS: actual filled rotated-footprint TraceBox and nine terrain/water samples; broad tree/cable bounds alone accepted, actual collision/nonfinite trace refused, nonzero sweep and ENTS/OCEAN flags, bounded diagnostic query and reset
|
||||
PASS: actual road interpolation/projection/orientation, six35m starts,200m forward tail, preserved bends, short/far/degenerate/nonfinite/overdense/hairpin refusal and deterministic candidate ties
|
||||
PASS: actual authenticated convoy dispatch, active/ready admission gates, canonical receipt, safe unconsumed preflight retry, pool refusal, retained partial failure and consumed no-retry
|
||||
PASS: actual native readiness exact membership, one-time per-vehicle ledger admission/reservation, partial readiness retry without duplicate records and one-pass56-item cargo allocation without replenishment
|
||||
PASS: actual per-vehicle readiness reasons, native agent/activity counts, intended-seat diagnostics, five-second throttle and read-only observation
|
||||
PASS: actual convoy dispatch validates before receipt consumption, consumes once before native mutation, retains all12 partial-failure paths, accepts the selected non-USSR enemy, and allocates exact19 bodies without capacity shrinking
|
||||
PASS: own memberless prefab disables automatic spawn before initialization; actual admission rejects populated, immediate or authored-slot templates before finite crew creation
|
||||
PASS: actual native seated-group arrival outside35m, native waypoint removal, idempotent advance, and convoy waypoint idempotence/arrival/deadline, missing/dead/captured/reparented crew refusal, failed native waypoint release, original vehicle/member preservation and no replacement
|
||||
PASS: actual convoy/team Release retains original active survivors and HQ identity, rejects takeover/terminal/unknown roster, preserves exact logistics quarantine and normal eligibility
|
||||
PASS: actual convoy receipt identity/one-use, shared60-body and128-formation caps, outstanding/native-ledger accounting, exact19-body composition, source reuse, mode/client guards and no consumed receipt refunds
|
||||
PASS: actual supply route cycling/arrival/stops, finite startup bounds, contact freshness, dismount hold, quiet interval, interrupted boarding, timeout and lost-truck release
|
||||
PASS: moving-convoy perception boundaries and scoped individual/group abandonment priorities
|
||||
PASS: actual supply startup reasons expose unchanged body budget/requirement, journal only failure changes, preserve retry cadence/caps and report the true final refusal
|
||||
PASS: actual combat start releases only exact intercept claims before owning route/orders; foreign claim defers combat takeover
|
||||
PASS: actual StartOne plus actual pool preserve unconsumed receipt retry, reject consumed replay, skip impossible new-budget surveys, retain equality, retry caps and journal dedup; no FPS claim
|
||||
PASS: actual admission seeds use exact installed loaded prefab, reject replacement/foreign/projectile paths and preserve bounded immutable identity
|
||||
PASS: actual primary-before-mounted one-shot batch, shared96/128 caps, physical snapshot headroom, original ownership, callback refusal and admission pinning
|
||||
PASS: actual bounded HQ query validates only existing original binding without admission or replacement lookup
|
||||
PASS: exact optional PMN4 startup, primary callback independence, original owner,128 capacity/callback limits, terminal no-retry and callback-proven freeze
|
||||
PASS: production convoy spacing, physical arrival, stable follower targets, supply ownership, leader promotion and bounded stuck recovery
|
||||
PASS: convoy combat keeps native manoeuvres for unchanged contacts and refreshes when contact moves
|
||||
PASS: native convoy proof excludes pre-departure movement and ends via explicit fixture reset, not prohibited player death
|
||||
PASS: boarding retries only after approach/seat progress stops, capped at three, with delayed native reissue and completed-team preservation
|
||||
PASS: slow only owned vehicles near fit dismounted infantry; ignore passengers, casualties and released teams/vehicles
|
||||
PASS: restore missing native driving registration only for healthy owned seated crews; preserve existing association and refuse invalid/released vehicles
|
||||
PASS: actual body observer enforces owned physical roster, local death-only candidates, native trace gating, budget/cadence/caps, immutable body-only snapshots, radio retries and confirmed suppression
|
||||
PASS: own initial roster, explicit retained corpse evidence, unconscious/missing/ref transfer guards, fixed strength, no replacement adoption, detached samples, surviving radio sender, immutable convoy root/ledger, mounted capture release and lost-root unknown
|
||||
PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence, detached/validated mounted payload replacement 256-record cap and detached carried-mine radio delivery/chronology
|
||||
PASS: actual failed-retask deadline rollback plus assignment cancellation/release preserves radio ownership, native waypoint lifecycle and failed-order retry boundaries
|
||||
PASS: actual force ledger, finite casualties/identity/cap, routes/arrival/elevation/overshoot, server and physical guards, staggered 256-record simulated hour without world queries
|
||||
PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 256-group bound
|
||||
PASS: actual percentage selection, native/preferred launcher preservation, failure/removal fallback, pending-operation quarantine, capture, finite two-mine grants and no replenishment
|
||||
PASS: automatic inventory one-shot roll, exact item ownership, finite compatible ammo, rejection, capture/stop, deletion, loot and late callback quarantine
|
||||
PASS: enabled/valid catalog eligibility, category restrictions, content filtering, GUID deduplication across factions and bounded catalogs
|
||||
PASS: actual engineer native group-envelope admission and phase cancellation, preparation/deadline, original custody/identity, once-only callback removal, cancellation quarantine, withdrawal/clearance, native refusal and owned-action cleanup; native execution untested
|
||||
PASS: actual mine selector respects road and settlement flank safety; native boundaries doubled
|
||||
PASS: actual HQ and post ledger: second delivered post, one query/tick,2 active/32 jobs,4 consumed lifetime attempts, no-stock/query refusal consumption, pending old job and original identity constraints
|
||||
PASS: actual mine post ledger immutable history, strict chronology/evidence, aliases, >160m separation, detached sites and finite4/32 consumed attempts
|
||||
PASS: actual objective heading/threat/approach rules, persistent doctrine weight, fresh-contact coverage invalidation, stale-sweep rejection and atomic radio retask ownership
|
||||
PASS: actual bounded delivered-negative coverage, replay/freshness/expiry/invalid guards, oldest eviction, small-circle and nearest-unswept selection, reserved-cell exclusion and cleanup
|
||||
PASS: actual HQ active/pending reservations, interruption, committed replacement, bounded coverage and unchanged force counts
|
||||
PASS: actual bounded pursuit roles/objectives/scores, stale search degradation, physical/busy/home guards, finite lifetime and two-bearing escape gap; no hidden player reads or spawning
|
||||
PASS: actual HQ memory rules/service preserve delivered snapshots, chronology, replay bounds, decay, motion limits, identity and negative-search revisions
|
||||
.......
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.029s
|
||||
|
||||
OK
|
||||
PASS: actual session Tick + journal router delivers each grant completion and new HQ line once, without repeats on empty/unavailable feeds or unauthorized ticks
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.380s
|
||||
|
||||
OK
|
||||
PASS: actual current-controller/admin/mode authorization, per-round anti-replay, token-rotation refusal, command/snapshot throttles and client scope; owner-only replies and player-tool cleanup wiring
|
||||
PASS: mission provider registration is idempotent, optional dispatch is ordered, status aggregates, journals preserve cursors, aliases stay with their addons and topic help is bounded
|
||||
PASS: actual menu command routing covers all fifteen settings, rejects unsupported keys, gates companions, and matches unique authored widgets
|
||||
PASS: explicit weapon retention buttons use the same ready/authorized server command path
|
||||
PASS: item editor, preset controls and dynamic item-row layout are structurally valid
|
||||
PASS: catalog requests use authenticated sessions, independent admin page selections, loaded-mod allowlisting, bounded pages and allowlisted item mutations
|
||||
PASS: actual item rules, shared-source conflicts, missing/returning mods, bulk reset, independent named presets, bounds, malformed data and failed-save state preservation
|
||||
PASS: actual summaries preserve queued/delivered meaning, clear counts and IDs; raw records, legacy display, cursor gaps and RPC limits remain intact
|
||||
PASS: actual admin body authorization, god restoration, vanilla item deposit, callback completion/failure, timeout quarantine and stop/revocation paths
|
||||
PASS: same-body revoke/regrant preserves pending insertions and timeout quarantine; new-body binding isolates late callbacks and never inherits god mode
|
||||
PASS: actual Intel commands distinguish status/start/failure, preserve authorization gate and reject malformed requests; spent ledger is idempotent, server-only and bounded
|
||||
PASS: actual reroll snapshot, authority, cancellation, ownership, accepted operations, quarantine, bounded work and stop methods; no native runtime claim
|
||||
PASS: production Intel feedback coalescing, rough secrecy, rate limit, bounded dedupe, local/remote delivery and round cleanup; native UI/RPC not exercised
|
||||
PASS: actual per-squad bounded report selector rotates visible targets, survives ordering/turnover, records only queued attempts, and preserves radio intake ordering
|
||||
PASS: actual action denial/clearing, server request failure, single submitted-result feedback, current rescuer identity and terminal/stop suppression; native UI/RPC pending
|
||||
PASS: actual physical denial precedence and transport-seat occupancy/reservation/access/lock checks
|
||||
PASS: actual initial admission exhaustion and ServerTick grace; new/pending/empty/controller/life guards, normal death preserved
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 0.226s
|
||||
|
||||
OK
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 22.926s
|
||||
|
||||
OK
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 2.588s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 2.128s
|
||||
|
||||
OK
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 1.068s
|
||||
|
||||
OK
|
||||
PASS: actual field result/braking observer and Chat dispatch rules; one finite fixed candidate, deferred callback failure and guarded cleanup; no native measurement
|
||||
PASS: actual opt-in terrain audit records one fixed1681-point grid, preserves original survey refusal/success and exact no-allocation scope; malformed heights stop without retry; no native data acquired
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.560s
|
||||
|
||||
OK
|
||||
PASS: actual field PI/ramp/vector caps, antiwindup, braking hypothesis, immutable admission limits and segment bounds; no native physics tested
|
||||
PASS: actual100m whole-field survey sampling/4096cap, rotated coverage, all-node terrain and native trace refusal; original certificate lineage retained; no native qualification
|
||||
PASS: actual QualifyField preserves original identity/footprint/time, orders complete surveys before issuance, and refuses failed stages/moved body/expired or changed world; native boundaries faked
|
||||
PASS: WORKBENCH first-refusal diagnostics preserve ordinary predicates, query order/count/budget and opt-in scope; no native logging run
|
||||
PASS: actual field startup delegation, immutable lease/target, braking/settling/cancel transitions, early abort, callback scope, physical terminal policy and shared landing demand; native boundaries faked
|
||||
PASS: actual inherited airborne pre-CLIMB cancellation enables verified native autohover once, refuses failed enable and never writes after capture
|
||||
PASS: actual Core maintenance/default/tick/stop methods; empty/populated authority, terminal reentry, no tactical resume or new scheduler; native boundaries substituted
|
||||
PASS: actual finite registration, unique claims/tokens, retention/cancel/stop, readiness gating, capture/expiry retirement and bounded cross-kind order history and typed field/route construction; native boundaries faked
|
||||
PASS: actual WORKBENCH route observer returns exact retained route subtype and refuses absent/field controllers
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.714s
|
||||
|
||||
OK
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 0.164s
|
||||
|
||||
OK
|
||||
................
|
||||
----------------------------------------------------------------------
|
||||
Ran 16 tests in 9.550s
|
||||
|
||||
OK
|
||||
......
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 0.017s
|
||||
|
||||
OK
|
||||
PASS: actual production bridge lookup, lease/world/mode/seat/capture guards, no allocation, native super ordering and read-only fixture hooks
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 0.050s
|
||||
|
||||
OK
|
||||
.............
|
||||
----------------------------------------------------------------------
|
||||
Ran 13 tests in 4.432s
|
||||
|
||||
OK
|
||||
PASS: actual route gain/caps/braking, callback selection, old landing/cancellation control and matching read-only telemetry
|
||||
..............................
|
||||
----------------------------------------------------------------------
|
||||
Ran 30 tests in 0.370s
|
||||
|
||||
OK
|
||||
..............
|
||||
----------------------------------------------------------------------
|
||||
Ran 14 tests in 0.177s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.101s
|
||||
|
||||
OK
|
||||
PASS: actual gate observer binds native registered action/context and current life, reads accumulated progress, refuses stale bindings and never revives outside original bounds
|
||||
PASS: actual read-only look observer methods enforce explicit scope, pinned native camera/body/identity, normalized pose, terminal cancellation and original sample/time bounds
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.063s
|
||||
|
||||
OK
|
||||
.......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 23 tests in 0.031s
|
||||
|
||||
OK
|
||||
PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending
|
||||
........
|
||||
----------------------------------------------------------------------
|
||||
Ran 8 tests in 0.011s
|
||||
|
||||
OK
|
||||
PASS: actual inventory adapter scope, grid placement, sole compatible host, refresh reuse, rollback, foreign hierarchy refusal and exactly-once native delegation; native compatibility pending
|
||||
.................................................................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 81 tests in 0.480s
|
||||
|
||||
OK
|
||||
......
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 0.074s
|
||||
|
||||
OK
|
||||
.................
|
||||
----------------------------------------------------------------------
|
||||
Ran 17 tests in 0.005s
|
||||
|
||||
OK
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.077s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.299s
|
||||
|
||||
OK
|
||||
PASS: actual observer nonce, admission pins, baseline/menu sequencing, snapshots, bounded clocks/samples, cleanup and one-attempt latch; native untested
|
||||
PASS: actual corridor caps/height/hold and whole-rectangle survey bounds, terrain refusal, native trace refusal and exact certificate lineage; native route unqualified
|
||||
PASS: actual route entry, fixed corridor/target, hover hold, cancellation landing freeze, shared lease/capture/deadline gate and unchanged native startup/tick sequence
|
||||
PASS: finite opt-in route fixture, original native input order, meaningful physical-arrival evidence and guarded cleanup; no native launch
|
||||
PASS: actual Chat route step result dispatch and scoped completion/cleanup wiring; six real early-parser refusal paths leave no prefix/profile output
|
||||
PASS: actual retained-service fixture entry, immutable controller/token/deadline/count bindings, observer getter and cleanup ownership ordering; native route validation pending
|
||||
PASS: actual measured cancellation gate, one-shot retained service Stop, no premature drain, immutable lease, fresh real controller readback and separate physical cancellation result policy
|
||||
PASS: actual rough-intel objective selection, exact precedence, source grid dimensions and unchanged other-phase dispatch; native UI pending
|
||||
.................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 33 tests in 0.083s
|
||||
|
||||
OK
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 0.029s
|
||||
|
||||
OK
|
||||
PASS: actual preparation status scope, persistent updates, spinner restoration, placeholder replacement/deletion/destruction, native observation persistence/timeout; rendering remains native-pending
|
||||
PASS: actual guide ownership and scoped timer cancellation, current-controller preservation/reacquisition, hint retry/dedup and observer boundaries; native UI not exercised
|
||||
PASS: actual native-end shutdown, existing terminal snapshots, reentrancy, unchanged native end data and stale preparation guards
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 1.192s
|
||||
|
||||
OK
|
||||
PASS: actual three-state result wording and UI refresh; stale winner IDs never manufacture escape
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.095s
|
||||
|
||||
OK
|
||||
PASS: actual immutable target, bounded autohover demand, drift refusal, five-second hold and unchanged qualification/deadline
|
||||
PASS: actual admission attempt budget bounds blocked/missing prerequisites; preparation, spent life and async pending remain protected
|
||||
PASS: delayed admission retry retains controller ownership across same-account recycled connection IDs
|
||||
PASS: actual scene deadline overrides delayed native preload only for rejection; late completion cannot assign, ordinary verified admission preserved
|
||||
PASS: actual action permission matrix unchanged; useful phase/intel/consciousness denials, stale reason cleared, native door denial preserved; no native UI claim
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.206s
|
||||
|
||||
OK
|
||||
PASS: actual aircraft cancellation/stage rules, ground-only completion, expiry/capture faults, input ownership and no physical shortcuts
|
||||
PASS: actual exact-instance single-use qualification, native-clock staleness/movement refusal, footprint bounds and ownership-safe ground/fault cleanup
|
||||
PASS: actual optional screenshot helper flag/identity/world/life revalidation, one queued attempt, delayed capture and mission/world cleanup; no native image/presentation claim
|
||||
PASS: actual yard diagnostic exact registered prison ownership, eight native-bound corner projections, no root-sibling escape, bounded duplicate/deep/wide hierarchy traversal; native projection/mask still unmeasured
|
||||
PASS: actual CurrentActor, SpawnPosition and observer-selection methods reject pending/unregistered/replaced/recycled/foreign/dead bodies; canonical selection/cycling, unconscious following and prison/geometry fallback preserved; native boundaries adapted
|
||||
PASS: actual native-map fixture ownership, cleanup and callback evidence fail closed; native execution remains separate
|
||||
PASS: actual shared-map callbacks bind exact map/config/root, preserve replacement UI/camera, defer focus, and remove only owned delayed work
|
||||
PASS: actual Intel/HQ methods and one-shot qualified readiness handoff deliver late actors once; duplicate readiness, accepted spawn, pickup/drop, death and original negative rolls do not mint assignments
|
||||
PASS: Workbench-only read accessor rejects unknown/nonserver identities; Chat observes all distinct ready crew before existing shell-depletion mutation
|
||||
PASS: actual native-event latch survives deselection, requires exact activity/order, detaches before cleanup, preserves failure/timeout and never infers completion from physical shot count
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.096s
|
||||
|
||||
OK
|
||||
PASS: actual refresh-fixture gates pin immutable observations/actual downlinks/original activity, reject unaccepted or relabelled commits, stop queueing early and require all queued contacts claimed before replay
|
||||
..........................
|
||||
----------------------------------------------------------------------
|
||||
Ran 26 tests in 0.176s
|
||||
|
||||
OK
|
||||
PASS: actual refresh scheduler/delivery/cancellation/projectile methods reject interrupted or replayed reports, retain committed ownership, preserve immutable snapshots/aim geometry and isolate stopped or replaced orders; native radio/crew behavior remains separate
|
||||
.....................
|
||||
----------------------------------------------------------------------
|
||||
Ran 21 tests in 0.031s
|
||||
|
||||
OK
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.038s
|
||||
|
||||
OK
|
||||
PASS: actual full-salvo gates require eight fresh committed physical launches, natural closure and exact finite inventory; reject partial/extra/replayed events
|
||||
PASS: actual reason/availability guidance and refresh matrix; no-target copy omits cycling, hint retry retained, existing command/admin paths unchanged; native UI pending
|
||||
PASS: actual client camera policy closes immediately on healing or mission end; late unconscious metadata cannot keep the view active
|
||||
PASS: actual input dispatch, one press per edge, menu-held suppression; actual revival camera handoff with editor close/retry, missing camera, replacement body and stopped round
|
||||
PASS: first-person pose survives missing samples without drift, follows body motion/rotation, resumes fresh pose and cannot leak between targets
|
||||
................usage: test_native_package.py [-h] [--project {core}] --session SESSION
|
||||
--compat COMPAT [--steam STEAM]
|
||||
[--timeout TIMEOUT]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
[--silent-workbench | --exit-after-init]
|
||||
[--continue-on-failure]
|
||||
test_native_package.py: error: argument --exit-after-init: not allowed with argument --silent-workbench
|
||||
................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 48 tests in 12.167s
|
||||
|
||||
OK
|
||||
.......
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.220s
|
||||
|
||||
OK
|
||||
..............
|
||||
----------------------------------------------------------------------
|
||||
Ran 14 tests in 2.246s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.280s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.050s
|
||||
|
||||
OK
|
||||
PASS: actual finite-courier age, token, exact ownership/callback and delivered-status admission reject stale, replayed, captured, canceled and ambiguous work
|
||||
PASS: actual native-gun ownership gate rejects player/foreign/replaced/dead occupant, faction change, missing seat and missing registry
|
||||
PASS: four-battery courier selection preserves pending trip/report/transfer identity, skips unavailable crews, and selects the next depleted battery without new stock
|
||||
PASS: 64 bounded distinct storage candidates; native gates, five-store barrier and finite-stock ownership retained; native placement pending
|
||||
PASS: 128 coarse+80 local refinement+169 airport grid candidates retain all native clearance gates; real terrain untested
|
||||
PASS: actual prison registration/crossing policies reject missing/duplicate/destroyed initial gate, incomplete ownership/scan, outside-only body, jumps and stale samples; physical exit independent of later gate damage
|
||||
PASS: actual prison door execution blocks direct AI/UI bypass while locked and delegates unchanged native action once after unlock and permission approval
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 1.824s
|
||||
|
||||
OK
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 1.106s
|
||||
|
||||
OK
|
||||
PASS: native local-admission snapshot rejects changed life/key/body/participant/pending state; authentication is not simulated
|
||||
PASS: actual mortar report ledger prevents duplicate response after cancellation, expiry and interleaved reports; native scheduler separate
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.012s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.139s
|
||||
|
||||
OK
|
||||
PASS: actual aim renewal requires fresh same-report solve and original-command equivalence; native firing untested
|
||||
........
|
||||
----------------------------------------------------------------------
|
||||
Ran 8 tests in 0.011s
|
||||
|
||||
OK
|
||||
PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation
|
||||
PASS: rapid mortar cycle counts eight physical rounds once and waits for native completion without a ninth aim or shell
|
||||
PASS: actual probe binds native events to fresh immutable commits, permits delayed emission, rejects unrelated expiry closure and premature stop
|
||||
PASS: actual noSplash Load body requires both explicit diagnostic and noSplash, preserves vanilla otherwise, and handles repeated Load/reload
|
||||
PASS: actual fixture method permits one native resilience operation and restores either prior protection state, including failure paths
|
||||
PASS: actual safe-exit boundary policy, native action/door selection, stop/cache cleanup, separate old mechanism and opt-in runner contracts
|
||||
PASS: actual one-shot deadline/stability policies and preparation ownership, fuel, cleanup integration contracts
|
||||
PASS: pending-only cancellation retires copied instance intent, preserves physical/control actors, and stops once
|
||||
PASS: actual short-cast hit, upward support normal, no self support and no dynamic support
|
||||
PASS: actual committed-ticket structure preserves reservation after death, rejects missing bodies/seats and ends at observation expiry
|
||||
PASS: actual pending callback expires an empty-server reservation once, preserves its full lease, and cancels on completion/Stop
|
||||
PASS: rescue lease expiry/reordering, fresh five-second settling, independent rescue ranges and grounded upright aircraft motion boundaries
|
||||
PASS: requested guard population requires complete physical conscious membership before deadline
|
||||
......................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 38 tests in 0.017s
|
||||
|
||||
OK
|
||||
..........
|
||||
----------------------------------------------------------------------
|
||||
Ran 10 tests in 0.002s
|
||||
|
||||
OK
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.909s
|
||||
|
||||
OK
|
||||
PASS: authored radio/optional-site bounds and physical horizontal/vertical boundaries
|
||||
...
|
||||
----------------------------------------------------------------------
|
||||
Ran 3 tests in 0.001s
|
||||
|
||||
OK
|
||||
PASS: all phase transitions, terminal states, defence boundaries, stale/future observations, intel discovery
|
||||
PASS: Core document-discovery alias, companion-only alias exclusion, strict integer parsing and setting boundaries
|
||||
PASS: player admission phase/life/identity/controller matrix, preload displacement limits, pending reservation overlap and owner exclusion
|
||||
PASS: actual gate and pre-inventory document guards reject noncanonical/faction/life/disconnect/server mismatches; canonical reconnect and unconscious carried intel preserved
|
||||
PASS: WB-only native fault injection restores both body mutations before checks/returns and requires eligible held-document negative/positive proof; runtime pending
|
||||
PASS: actual discovery coordinates disclose stable 500m cell center until identified, then exact point, including negative/boundary coordinates
|
||||
PASS: actual local admission context/selection/latch, same-round late identity, replacement/mode failure, fresh round and untouched network path
|
||||
PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance
|
||||
PASS: physical body occupancy rejects overlap, permits diagonal neighboring slots, and excludes own body and unrelated broad-phase bounds
|
||||
PASS: recovery state excludes dead bodies, preserves reservations, requires controlled rescuers and distinguishes empty/all-dead teams
|
||||
PASS: authority-scoped slow recovery, bleeding pauses resilience, medicine unaffected, player-only lethal damage cap without healing
|
||||
PASS: bleeding severity survives low health, retains armour, causes no knockout and restores the actual damage/blood-loss cap
|
||||
PASS: viable passive recovery survives native delay; bleeding, disabled/full effects and low-blood resilience do not block defeat
|
||||
PASS: every minute round-trips, malformed clocks rejected, defaults limited to added keys, progression bounds and day duration aligned
|
||||
PASS: native settings policy matches calendar boundaries 1900-2050, date/profile parsing is strict, authored defaults preserve old worlds
|
||||
PASS: view-distance bounds, default, save failures, command parsing, temporary ownership, server/platform limits and lifecycle wiring
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.517s
|
||||
|
||||
OK
|
||||
.
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 test in 0.363s
|
||||
|
||||
OK
|
||||
PASS: radio authorization/discovery/phase matrix, exact distance limits, defender handover, interruption, empty samples, clock regression and duration boundary
|
||||
PASS: actual radio feedback policy, initial wait, interruption persistence, resumption and terminal/new-round reset
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 2.008s
|
||||
|
||||
OK
|
||||
..............................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 46 tests in 0.787s
|
||||
|
||||
OK
|
||||
PASS: legacy values preserved, unsupported fields reported, invalid data rejected, existing files protected, runtime bounds aligned
|
||||
PASS: failed initial settings promotion leaves defaults writable after restart; prior/fallback saves survive copy, readback and mismatch faults
|
||||
PASS: real-carrier shortest-hop paths, 500m boundary, three-hop cap, no-manpack failure, three-second originating-call interruption, unchanged downlink hop timing, completed-hop survival, interrupted final uplink, radio loss, capture, motion, timeout, reset and network bounds
|
||||
PASS: migrated aircraft availability policy (controller migration still pending)
|
||||
PASS: migrated salvo offsets are deterministic, spread and bounded (native firing and complete salvo qualification are separate)
|
||||
PASS: 35 prefabs have unique saved root entity IDs
|
||||
PASS: 299 original script entries tracked across 18 unfinished responsibilities
|
||||
PASS: 1 isolated addons, acyclic dependencies, 58 unique resources, exact vanilla/authorized external references
|
||||
All repository checks passed. Native compilation and multiplayer tests are separate requirements.
|
||||
Suite exit 0 programs 301 unchanged True
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c
|
||||
@@ -18,12 +18,14 @@
|
||||
foreach (ERR_HQUnit unit : m_Units) if (unit && unit.Group == group) return unit;
|
||||
return null;
|
||||
}
|
||||
- bool ReserveGroundDepot(ERR_HQUnit crew, ERR_HQUnit donor, ERR_InfantryResupply service, int token)
|
||||
+ bool ReserveGroundDepot(ERR_HQUnit crew, ERR_HQUnit donor, ERR_InfantryResupply service, int token, bool mineCargo = false)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopping || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return false;
|
||||
if (m_Mode.Command() != this) return false;
|
||||
if (token <= 300000 || token > 300096 || !crew || !donor || crew == donor || !m_Units.Contains(crew)) return false;
|
||||
- if (!service || !service.DepotNeeded() || !MountedLogisticsEligible(donor)) return false;
|
||||
+ if (!service || !MountedLogisticsEligible(donor)) return false;
|
||||
+ if (mineCargo) { if (!service.DepotMineNeeded()) return false; }
|
||||
+ else if (!service.DepotNeeded()) return false;
|
||||
ERR_ConvoyVehicle truck = service.DepotTruck();
|
||||
if (!truck || truck.Group != donor.Group || truck.SupplyToken > 0) return false;
|
||||
if (crew.HomeGuard || crew.ReservedForSupport || crew.Task || crew.PendingTask || crew.PendingCheckin || crew.PendingConvoyOrder) return false;
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled
|
||||
@@ -0,0 +1,19 @@
|
||||
check: /tmp/err-policy-14q1vh4d/check.cpp:59: int main(): Assertion `accepted==(mines==cargo)' failed.
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-depot-mines-review-1116/tests/test_ground_depot_mine_claim.py", line 18, in <module>
|
||||
run(r'''
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<25 lines>...
|
||||
}
|
||||
^
|
||||
'''.replace('DEMAND',demand).replace('HQMETHODS',hq))
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-14q1vh4d/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"complete": true,
|
||||
"test_frozen": true,
|
||||
"registration": "tests/test_ground_depot_mine_claim.py",
|
||||
"test_scope": "Actual HQ ReserveGroundDepot/ReleaseGroundDepot and actual service DepotNeeded/DepotMineNeeded. Native availability/current/batch boundaries explicitly doubled.",
|
||||
"result": "PASS; wrong mine-vs-magazine gate mutation compiles and fails accepted cargo assertion.",
|
||||
"source_review": "No remaining blocker in exact reviewed bytes. Core captures exact authored resource identity without AI reference. Upper layers pin cargo class, require ReadyMine at each phase/submission/after native callbacks and final import, separate typed demand counters, exact original custody and reciprocal slots. Existing reservation/claim retention survives cancellation; state7 only settles old proof, never imports. No engineer grant or downstream entitlement policy changed.",
|
||||
"native_witness": "Root WB-only stock assertion reviewed clean; read-only initial stock identity/inert/custody proof, not courier proof.",
|
||||
"limits": "No native launch, no autonomous delivery/MP/physical navigation claim. No broad suite.",
|
||||
"hashes": {
|
||||
"/tmp/erri-depot-mines-review-1116/tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083",
|
||||
"/tmp/erri-depot-mines-root-1116/proposal/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"/tmp/erri-depot-mines-stock-1116/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "85841b8179e7bf54f475617596292bc590a20438accf9ef74f265e1469dfc2f9",
|
||||
"/tmp/erri-depot-mines-review-1116/green.log": "54c4f20daef8efe2927372f274a749d4e9a5c7d87332233d6b2d18994adb0a78",
|
||||
"/tmp/erri-depot-mines-review-1116/mutation-red.log": "d75b0e11420dae2fbe88afa2375cb7b1e0a738f8b10eee32f6c147c5247d6ae6",
|
||||
"/tmp/erri-depot-mines-review-1116/test.patch": "6489fe922e28489cf934536973275930fbbbe727c9f67da2592ac34233730a00",
|
||||
"/tmp/erri-depot-mines-courier-1116/source-manifest.json": "16efa4bc1772e09dc652537767f6f82b922977ea61650665c2cf8e70d9168c72",
|
||||
"/tmp/erri-depot-mines-courier-1116/fix.patch": "c01e2c03b54a64c7546e291261418ec6524e79fc74bfa550b16a6c88620deaa3",
|
||||
"/tmp/erri-depot-mines-stock-1116/fix.patch": "c7273b6800da3600cc49348000b139a5caaf50bc6395640d5ff59c674c0fdb43",
|
||||
"/tmp/erri-depot-mines-stock-1116/source-manifest.json": "b89783db5e2ad1d70942a3b106d34400e65ec3fda3bc2e62e3386d572c740e68",
|
||||
"/tmp/erri-depot-mines-stock-1116/report.json": "5abf69a94be0cd4490f8b9d473ee031876af4f317ff2b6dc53805b31cc4a0f3e",
|
||||
"/tmp/erri-depot-mines-root-1116/proposal/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e"
|
||||
},
|
||||
"reviewed_artifact_hashes": {
|
||||
"/tmp/erri-depot-mines-stock-1116/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"/tmp/erri-depot-mines-stock-1116/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"/tmp/erri-depot-mines-stock-1116/addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"/tmp/erri-depot-mines-stock-1116/tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
|
||||
"/tmp/erri-depot-mines-stock-1116/provenance-green.log": "e26ca35beb9bdd2800680a97f46df2693145f8ed2d63e42c745c73e3238d2205",
|
||||
"/tmp/erri-depot-mines-courier-1116/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"/tmp/erri-depot-mines-courier-1116/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"/tmp/erri-depot-mines-courier-1116/tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
|
||||
"/tmp/erri-depot-mines-courier-1116/tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
|
||||
"/tmp/erri-depot-mines-courier-1116/leaf-green.log": "897cec0577c062d00bb7ff774b52bb5147193d2752088deed78b84a2b235f4d5",
|
||||
"/tmp/erri-depot-mines-courier-1116/loader-green.log": "491d5709202ea176318751587693c7929ef8f4710bbc00a1a27f3aa45ba0158b"
|
||||
},
|
||||
"core_layering_resolved": true,
|
||||
"owner_test_review": "Loader actual Plan/SelectWorker/Tick/ClaimDelivery/DeliveredTo+import covers mine-only success, wrong-class rejection, armed-state interruptions, vanished demand and lateproof no-import. Full leaf harness retains original custody/Stop cases and adds PMN4 Cargo controls. Source provenance/import actual harness green. Native boundaries remain doubled.",
|
||||
"approval_scope": "Exact hashes recorded; any later source/test changes require recheck. Owner final manifests may be issued after this review; reviewed bytes are authoritative.",
|
||||
"compiler_work_finished": true,
|
||||
"courier_final_manifest_checked": true,
|
||||
"stock_final_manifest_checked": true,
|
||||
"final_hash_drift_review": "Service byte reconstruction confirms only Status initial\u2192allowance. Final provenance test reread in full: explicit feature absence assertion, authored-resource Core capture adapter and Core-to-AI dependency assertion, actual typed mine demand/import with custody/cap/cancellation controls; no blocker. Not claiming test drift was solely one assertion. Root read-only native stock witness hash also bound."
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
--- /dev/null
|
||||
+++ b/tests/test_ground_depot_mine_claim.py
|
||||
@@ -0,0 +1,47 @@
|
||||
+"""Actual HQ cargo-class reservation and service demand; native availability doubled."""
|
||||
+import os,re
|
||||
+from pathlib import Path
|
||||
+from policy_harness import ROOT,body,run
|
||||
+H=Path(os.environ.get('ERR_DEPOT_HQ_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c'))
|
||||
+S=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
+def cpp(s):
|
||||
+ s=s.replace('protected ','').replace('null','nullptr').replace('int committed;', 'int committed = 0;')
|
||||
+ for typ in ('ERR_HQUnit','ERR_InfantryResupply','ERR_ConvoyVehicle'):
|
||||
+ s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s)
|
||||
+ for name in ('m_Mode','crew','donor','service','truck'):
|
||||
+ s=re.sub(r'\b'+name+r'\.',name+'->',s)
|
||||
+ s=s.replace('Replication.IsServer()', 'server').replace('ERR_GameMode.Get()', 'current')
|
||||
+ s=s.replace('foreach (IEntity item : m_Spent)', 'for (IEntity item : m_Spent)')
|
||||
+ return s
|
||||
+hq='\n'.join(cpp(body(H,x)) for x in ('bool ReserveGroundDepot(', 'void ReleaseGroundDepot('))
|
||||
+demand='\n'.join(cpp(body(S,x)) for x in ('bool DepotNeeded(', 'bool DepotMineNeeded('))
|
||||
+run(r'''
|
||||
+#include <cassert>
|
||||
+#include <vector>
|
||||
+#include <algorithm>
|
||||
+struct Entity{};using IEntity=Entity*;
|
||||
+template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}};
|
||||
+struct Group{};struct HQ;
|
||||
+struct Mode{HQ*owner=nullptr;bool active=true;bool Active(){return active;}HQ*Command(){return owner;}};
|
||||
+bool server=true;Mode*current=nullptr;
|
||||
+struct ERR_HQUnit{struct Group*Group=nullptr;bool HomeGuard=false,ReservedForSupport=false,Task=false,PendingTask=false,PendingCheckin=false,PendingConvoyOrder=false;int LogisticsReservation=0;};
|
||||
+struct ERR_ConvoyVehicle{struct Group*Group=nullptr;int SupplyToken=0;bool SupplyHeld=false;};
|
||||
+struct ERR_InfantryResupply{bool magAvailable=true,mineAvailable=true,captured=true;int m_DepotImports=0,m_DepotMineImports=0;Array<IEntity>m_Stock,m_MineStock,m_Spent;ERR_ConvoyVehicle*truck=nullptr;bool DepotAvailable(){return magAvailable;}bool DepotMineAvailable(){return mineAvailable;}bool CaptureMines(){return captured;}ERR_ConvoyVehicle*DepotTruck(){return truck;}
|
||||
+DEMAND
|
||||
+};
|
||||
+struct HQ{Mode*m_Mode=nullptr;bool m_Stopping=false,eligible=true,reserve=true;Array<ERR_HQUnit*>m_Units;int claims=0,releases=0;bool MountedLogisticsEligible(ERR_HQUnit*){return eligible;}bool ReserveLogistics(Group*g,int token){if(!reserve)return false;for(auto*u:m_Units)if(u->Group==g){if(u->LogisticsReservation)return false;u->LogisticsReservation=token;claims++;return true;}return false;}void ReleaseLogistics(Group*g,int token){for(auto*u:m_Units)if(u->Group==g&&u->LogisticsReservation==token){u->LogisticsReservation=0;releases++;}}
|
||||
+HQMETHODS
|
||||
+};
|
||||
+struct F{Mode mode;HQ h;Group cg,dg;ERR_HQUnit crew,donor;ERR_ConvoyVehicle truck;ERR_InfantryResupply s;Entity mine,mag,foreign;F(){server=true;current=&mode;mode.owner=&h;h.m_Mode=&mode;crew.Group=&cg;donor.Group=truck.Group=&dg;h.m_Units={&crew,&donor};s.truck=&truck;s.m_Stock={&mag};s.m_MineStock={&mine};}void Unclaimed(){assert(h.claims==0&&crew.LogisticsReservation==0&&donor.LogisticsReservation==0&&truck.SupplyToken==0&&!truck.SupplyHeld);}};
|
||||
+int main(){
|
||||
+ // Mine-only expenditure authorizes mine cargo only. Magazine-only is inverse.
|
||||
+ for(bool mines:{false,true})for(bool cargo:{false,true}){F f;f.s.m_Spent={mines?&f.mine:&f.mag};bool accepted=f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001,cargo);assert(accepted==(mines==cargo));if(!accepted)f.Unclaimed();else{assert(f.h.claims==1&&f.crew.LogisticsReservation==300001&&f.donor.LogisticsReservation==300001&&f.truck.SupplyToken==300001);assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300002,cargo));f.truck.SupplyHeld=true;f.h.ReleaseGroundDepot(&f.crew,&f.donor,&f.truck,300002);assert(f.truck.SupplyToken==300001&&f.truck.SupplyHeld);f.h.ReleaseGroundDepot(&f.crew,&f.donor,&f.truck,300001);assert(!f.crew.LogisticsReservation&&!f.donor.LogisticsReservation&&!f.truck.SupplyToken&&!f.truck.SupplyHeld);}}
|
||||
+ // Null/deleted/unrelated spent identities and satisfied imported demand never count.
|
||||
+ for(bool mines:{false,true})for(int k=0;k<4;k++){F f;if(k==0){f.s.m_Spent={nullptr};f.s.m_Stock.push_back(nullptr);f.s.m_MineStock.push_back(nullptr);}if(k==1)f.s.m_Spent={&f.foreign};if(k==2){f.s.m_Spent={mines?&f.mine:&f.mag};if(mines)f.s.m_DepotMineImports=1;else f.s.m_DepotImports=1;}if(k==3){f.s.m_Spent={mines?&f.mine:&f.mag};if(mines)f.s.mineAvailable=false;else f.s.magAvailable=false;}assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001,mines));f.Unclaimed();}
|
||||
+ // Existing authority, task ownership and token gates apply equally to mine jobs.
|
||||
+ for(int k=0;k<15;k++){F f;f.s.m_Spent={&f.mine};int token=300001;if(k==0)server=false;if(k==1)f.h.m_Stopping=true;if(k==2)current=nullptr;if(k==3)f.mode.active=false;if(k==4)f.mode.owner=nullptr;if(k==5)token=300000;if(k==6)token=300097;if(k==7)f.h.m_Units.clear();if(k==8)f.h.eligible=false;if(k==9)f.crew.HomeGuard=true;if(k==10)f.crew.ReservedForSupport=true;if(k==11)f.crew.PendingCheckin=true;if(k==12)f.crew.PendingConvoyOrder=true;if(k==13)f.h.reserve=false;if(k==14)f.truck.Group=&f.cg;assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,token,true));f.Unclaimed();}
|
||||
+ // Legacy default remains magazine demand; distinct import counters don't cross classes.
|
||||
+ {F f;f.s.m_Spent={&f.mag,&f.mine};f.s.m_DepotMineImports=1;assert(!f.s.DepotMineNeeded()&&f.s.DepotNeeded());assert(f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001));}
|
||||
+}
|
||||
+'''.replace('DEMAND',demand).replace('HQMETHODS',hq))
|
||||
+print('PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled')
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
|
||||
"tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
|
||||
"tools/check.py": "6c1b5b24e759f7855058c9d82956f9ca0107a5311fdf9f7217129a86ecb62f5e",
|
||||
"tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
|
||||
@@ -2,6 +2,33 @@
|
||||
#ifdef WORKBENCH
|
||||
modded class ERR_GameMode
|
||||
{
|
||||
+ // Read-only normal-route stock witness; no courier, movement or arming action.
|
||||
+ protected bool ERR_DepotMineStockReady()
|
||||
+ {
|
||||
+ if (!Sites() || Sites().Count() > 64) return false;
|
||||
+ int camps;
|
||||
+ array<IEntity> seen = {};
|
||||
+ for (int index = 0; index < Sites().Count(); index++)
|
||||
+ {
|
||||
+ ERR_SiteRuntime site = Sites().At(index);
|
||||
+ if (!site || !site.Definition || site.Definition.Kind != ERR_LocationKind.OUTPOST || site.Definition.RevealOnEscape) continue;
|
||||
+ if (!site.Container || site.DepotMines.Count() != 2) return false;
|
||||
+ InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(site.Container.FindComponent(InventoryStorageManagerComponent));
|
||||
+ if (!inventory || inventory.GetOwner() != site.Container) return false;
|
||||
+ array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
+ if (items.Count() > 128) return false;
|
||||
+ foreach (IEntity mine : site.DepotMines)
|
||||
+ {
|
||||
+ if (!Sites().DepotOriginal(site, mine) || !ERR_InfantryMineTransfer.ReadyMine(mine) || !items.Contains(mine)
|
||||
+ || !ERR_InfantryAmmoTransfer.StoredUnder(mine, site.Container) || seen.Contains(mine)) return false;
|
||||
+ seen.Insert(mine);
|
||||
+ }
|
||||
+ camps++;
|
||||
+ }
|
||||
+ PrintFormat("ERR DEPOT MINE STOCK: original camps=%1 inert stored identities=%2; no physical courier claim", camps, seen.Count());
|
||||
+ return camps > 0 && seen.Count() == camps * 2;
|
||||
+ }
|
||||
+
|
||||
protected bool m_ERRTestPatrolHQ;
|
||||
protected ref ERR_NativePatrolProbe m_ERRHQPatrolMovement;
|
||||
protected ref ERR_NativePatrolHQProbe m_ERRHQPatrolOrder;
|
||||
@@ -837,6 +864,7 @@
|
||||
string routeOutcome; System.GetCLIParam("errSmokeOutcome", routeOutcome);
|
||||
if (routeOutcome == "normal-escape-route")
|
||||
{
|
||||
+ if (!ERR_Check(ERR_DepotMineStockReady(), "normal camps retain two original inert PMN4 mines in each cache")) return;
|
||||
ERR_SiteRuntime clueSite = Sites().Find("everon-supply-1");
|
||||
ERR_NativeTransportProbe maintenanceProbe = new ERR_NativeTransportProbe(this, m_ERRSmokePlayer);
|
||||
if (!ERR_Check(maintenanceProbe.MaintenanceStock(clueSite), "normal Southern cache holds finite maintenance stock")) return;
|
||||
@@ -0,0 +1,64 @@
|
||||
Test audio routed to silent output and muted (stream 754185)
|
||||
{
|
||||
"stopped_unix": 1791020318.4961236,
|
||||
"console_sha256": "a801e7b2d1824751785c76487e735650cca20513acb1f18c9d5675e52463e25b",
|
||||
"end_source_sha256": "05a98e2f31c84d0c67ce4a2408307c441e9cbe9a5cc6554cbe946079e41b66cb",
|
||||
"source_unchanged_after_run": true,
|
||||
"source_provenance": "launch_snapshot",
|
||||
"launch_id": "a79873ef-ccd2-4d48-a376-9416fcfb370e",
|
||||
"launch_source_manifest": "launch-source-sha256.json",
|
||||
"launch_source_metadata": "launch-source.json",
|
||||
"launch_source_sha256": "05a98e2f31c84d0c67ce4a2408307c441e9cbe9a5cc6554cbe946079e41b66cb",
|
||||
"external_addons_unchanged_after_run": true,
|
||||
"external_addon_count": 7,
|
||||
"external_addon_inputs": "external-addons-inputs.json",
|
||||
"started_unix": 1791020141.4604342,
|
||||
"result": "smoke-completed",
|
||||
"result_before_cleanup": "smoke-completed",
|
||||
"cleanup_confirmed": true,
|
||||
"cleanup_report": {
|
||||
"cleanup_confirmed": true,
|
||||
"idle_verified": true,
|
||||
"errors": [],
|
||||
"orphan_cleanup": {
|
||||
"attempted": true,
|
||||
"report": {
|
||||
"scope": "/tmp/erri-headless-compat/pfx",
|
||||
"candidates": [],
|
||||
"term_sent": [],
|
||||
"kill_sent": [],
|
||||
"cleared": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"runner_error": null,
|
||||
"session": "/tmp/erri-depot-mines-1116/logs/logs_2026-10-03_11-35-43",
|
||||
"rounds_required": 1,
|
||||
"project": "chat",
|
||||
"display": "headless Gamescope 1280x720/30Hz",
|
||||
"dedicated_server": false,
|
||||
"audio": "silent sink and per-test-stream mute"
|
||||
}
|
||||
{
|
||||
"log": "/tmp/erri-depot-mines-1116/logs/logs_2026-10-03_11-35-43/console.log",
|
||||
"smoke_completions": 1,
|
||||
"assertions_passed": 64,
|
||||
"script_or_runtime_failures": [],
|
||||
"engine_errors": [
|
||||
"11:35:45.265 RESOURCES (E): Wrong GUID/name for resource @\"{0AFDD005CD669892}Language/rhs_localization.st\" in property \"StringTableSource\"",
|
||||
"11:35:45.265 RESOURCES (E): Wrong GUID/name for resource @\"{41FA2A08B6971D4C}Language/wcs_armament_localization.st\" in property \"StringTableSource\"",
|
||||
"11:35:45.265 RESOURCES (E): Wrong GUID/name for resource @\"{84270E09F7A4A7A0}Language/wcs_spacecore_localization.st\" in property \"StringTableSource\"",
|
||||
"11:35:45.266 RESOURCES (E): Wrong GUID/name for resource @\"{E50E557B468C7073}Language/wcs_bmp1_localization.st\" in property \"StringTableSource\"",
|
||||
"11:36:29.568 WORLD (E): Unknown keyword/data 'Parent' at offset 35955(0x8c73)",
|
||||
"11:36:29.568 WORLD (E): Unknown keyword/data 'Parent' at offset 36915(0x9033)",
|
||||
"11:36:29.570 WORLD (E): Unknown keyword/data 'Parent' at offset 42646(0xa696)",
|
||||
"11:36:29.570 WORLD (E): Unknown keyword/data 'Parent' at offset 43645(0xaa7d)",
|
||||
"11:36:29.570 WORLD (E): Unknown keyword/data 'Parent' at offset 44617(0xae49)",
|
||||
"11:36:29.570 WORLD (E): Unknown keyword/data 'Parent' at offset 45590(0xb216)",
|
||||
"11:36:29.735 WORLD (E): Unknown keyword/data 'SlidingTrackMaterial' at offset 19441(0x4bf1)",
|
||||
"11:36:37.109 WORLD (E): Unknown keyword/data 'm_HardLandingVelocity' at offset 133(0x85)",
|
||||
"11:36:37.109 WORLD (E): Unknown keyword/data 'm_DeathLandingVelocity' at offset 163(0xa3)"
|
||||
],
|
||||
"missing_end_screen": [],
|
||||
"scope": "scripted local Workbench integration only; no multiplayer, piloting or FPS claim"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"checks": [
|
||||
{
|
||||
"name": "ground-supply development candidate",
|
||||
"files": 432,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-ground-supply/candidate-sha256.json",
|
||||
"manifest_sha256": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "original missions",
|
||||
"files": 533,
|
||||
"manifest": "/tmp/erri-heartbeat-20260930-1542-reference.json",
|
||||
"manifest_sha256": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "mine-safety development candidate",
|
||||
"files": 431,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-mine-safety/candidate-sha256.json",
|
||||
"manifest_sha256": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "mounted-pair development candidate",
|
||||
"files": 429,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-mounted-pair/candidate-sha256.json",
|
||||
"manifest_sha256": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7",
|
||||
"unchanged": true
|
||||
}
|
||||
],
|
||||
"index_diff_sha256": "670073db5d7531aca4466cc9d2827d10a46bfcfbd35f27ac97724de9d2fd3725",
|
||||
"index_unchanged": true
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/tools/check.py
|
||||
+++ b/tools/check.py
|
||||
@@ -23,6 +23,7 @@
|
||||
subprocess.run([sys.executable,str(ROOT/'tests/test_native_observer_selector.py')],check=True)
|
||||
subprocess.run([sys.executable,str(ROOT/'tests/test_ground_depot_loading.py')],check=True)
|
||||
subprocess.run([sys.executable,str(ROOT/'tests/test_ground_depot_lifecycle.py')],check=True)
|
||||
+ subprocess.run([sys.executable,str(ROOT/'tests/test_ground_depot_mine_claim.py')],check=True)
|
||||
subprocess.run([sys.executable,str(ROOT/'tests/test_ground_depot_transfer.py')],check=True)
|
||||
subprocess.run([sys.executable,str(ROOT/'tests/test_ground_depot_provenance.py')],check=True)
|
||||
ids={};graph={};resources={};paths={};owners={}
|
||||
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"feature": "Finite original Everon camp PMN4 stock can be carried by original responders through the existing radio-coordinated two-leg courier into an existing original ammunition truck.",
|
||||
"authored_stock": "Five nonopening OUTPOSTs each receive two startup PMN4s: ten total, finite, no later stock or personnel creation. Core records authored identities without an upper AI dependency.",
|
||||
"contracts": [
|
||||
"Combined original depot sources and mission attempts remain96; one job at a time. Each camp mine list is at most2 and combined items at most96.",
|
||||
"Cargo class is pinned in job and leaf; inert ReadyMine is checked in active phases, before and after native inventory submission, and at final admission. Armed/changed/foreign/cancelled cargo cannot import.",
|
||||
"Separate mine commitment/import counts prevent magazine expenditure, null/deleted identities or spare truck capacity from creating mine demand. Original closed convoy mine batch remains bound; no original mine allowance means no bootstrap.",
|
||||
"Shared outgoing spent ledger remains96; mine allowance lifetime96 includes retained spent/lost identities and imports. Import appends one exact proved identity once. Return ownership is independent of a now-filled cap.",
|
||||
"Original roster, compatible magazine porter selection, radio hold/new delivered stopped report, fixed deadline, physical access/callback custody and uncertain transfer quarantine remain. Mine porters need no matching rifle; downstream original engineer entitlement and consumed posts are unchanged."
|
||||
],
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
|
||||
"tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
|
||||
"tools/check.py": "6c1b5b24e759f7855058c9d82956f9ca0107a5311fdf9f7217129a86ecb62f5e",
|
||||
"tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083"
|
||||
},
|
||||
"regressions": {
|
||||
"programs": 301,
|
||||
"seconds": 213.4,
|
||||
"inputs_unchanged": true,
|
||||
"negative_controls": "Removing post-native readiness, import cargo type or using magazine demand for a mine each compiles then fails behavioral assertions. Predecessor feature-absence check fails explicitly before compilation; not represented as a runtime reproduction.",
|
||||
"boundaries": "Changed actual policy/controller/provenance/leaf code executes with documented native inventory/AI/radio/component boundaries doubled."
|
||||
},
|
||||
"native": {
|
||||
"archive": "docs/evidence/native-2026-10-03-depot-mines",
|
||||
"assertions": 64,
|
||||
"rounds": 1,
|
||||
"script_errors": 0,
|
||||
"engine_errors": 13,
|
||||
"initial_stock_witness": {
|
||||
"camps": 5,
|
||||
"inert_original_mines_in_caches": 10
|
||||
},
|
||||
"cleanup_confirmed": true,
|
||||
"source_unchanged": true,
|
||||
"external_addons_unchanged": true,
|
||||
"trace": {
|
||||
"enabled": true,
|
||||
"trace_lines": 0,
|
||||
"zero_radius_errors": 0
|
||||
}
|
||||
},
|
||||
"limitations": [
|
||||
"Native evidence proves initial inert original cache stock, compilation and scripted normal-route integration. It does not prove autonomous porter movement, cache-to-truck mine transfers, mine arming/detonation, engineer placement, multiplayer or FPS.",
|
||||
"Known installed-resource errors and unresolved intermittent zero-radius diagnosis keep clean release qualification open. No extra reproduction run.",
|
||||
"Finite mission stock and one-item jobs intentionally do not restore predecessor stock generation, new porter groups or bulk manifests. No full original AI parity claim."
|
||||
],
|
||||
"owned_reference": {
|
||||
"path": "/home/jakub/devel/escapists/escapists-ai/Scripts/Game/EscapistsAI/EAI_DepotLoading.c",
|
||||
"sha256": "5b608f36621c9d744bdc55829b1000af70ba9d8853b8a90828d774557a204375",
|
||||
"read_only": true
|
||||
},
|
||||
"preservation": {
|
||||
"checks": [
|
||||
{
|
||||
"name": "ground-supply development candidate",
|
||||
"files": 432,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-ground-supply/candidate-sha256.json",
|
||||
"manifest_sha256": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "original missions",
|
||||
"files": 533,
|
||||
"manifest": "/tmp/erri-heartbeat-20260930-1542-reference.json",
|
||||
"manifest_sha256": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "mine-safety development candidate",
|
||||
"files": 431,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-mine-safety/candidate-sha256.json",
|
||||
"manifest_sha256": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"name": "mounted-pair development candidate",
|
||||
"files": 429,
|
||||
"manifest": "/home/jakub/devel/escapistsrereintroduced/docs/evidence/playtest-refresh-2026-10-03-mounted-pair/candidate-sha256.json",
|
||||
"manifest_sha256": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7",
|
||||
"unchanged": true
|
||||
}
|
||||
],
|
||||
"index_diff_sha256": "670073db5d7531aca4466cc9d2827d10a46bfcfbd35f27ac97724de9d2fd3725",
|
||||
"index_unchanged": true
|
||||
},
|
||||
"package": "Previous ground-supply and older packages are unchanged and predate porter-pair correction and this feature; no staging, commit or publication."
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-depot-mines-stock-1116/tests/test_ground_depot_provenance.py", line 10, in <module>
|
||||
assert 'int DepotItemCount(' in S.read_text() and 'bool AdmitDepotMine(' in I.read_text(), 'finite authored camp mine provenance/import API is absent'
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: finite authored camp mine provenance/import API is absent
|
||||
@@ -0,0 +1,282 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c
|
||||
@@ -13,6 +13,7 @@
|
||||
ERR_LocationComponent Location;
|
||||
IEntity Container;
|
||||
ref array<IEntity> DepotMagazines = {}; // Exact authored startup identities; never refreshed from live inventory.
|
||||
+ ref array<IEntity> DepotMines = {}; // At most two authored inert PMN4 per camp, never replenished.
|
||||
SCR_AIGroup Group;
|
||||
ref ERR_SiteRuntime Responders;
|
||||
string ExpectedGuardFaction;
|
||||
@@ -58,7 +59,7 @@
|
||||
if (index < 0 || index >= m_Sites.Count()) return null;
|
||||
return m_Sites[index];
|
||||
}
|
||||
- // Optional ground loading consumes only retained original camp magazines.
|
||||
+ // Optional ground loading consumes only retained original camp items.
|
||||
int DepotMagazineCount(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || m_State != ERR_PrepareResult.READY || !site || !m_Sites.Contains(site)) return 0;
|
||||
@@ -67,11 +68,33 @@
|
||||
if (site.DepotMagazines.Count() > 96) return 0;
|
||||
return site.DepotMagazines.Count();
|
||||
}
|
||||
+ int DepotMineCount(ERR_SiteRuntime site)
|
||||
+ {
|
||||
+ if (!Replication.IsServer() || m_Stopped || m_State != ERR_PrepareResult.READY || !site || !m_Sites.Contains(site)) return 0;
|
||||
+ if (!site.Definition || site.Definition.Kind != ERR_LocationKind.OUTPOST || site.Definition.RevealOnEscape) return 0;
|
||||
+ if (!site.Container || !Owns(site.Container) || !site.Responders || !site.Responders.Group) return 0;
|
||||
+ if (site.DepotMines.Count() > 2) return 0;
|
||||
+ return site.DepotMines.Count();
|
||||
+ }
|
||||
+ int DepotItemCount(ERR_SiteRuntime site)
|
||||
+ {
|
||||
+ if (!site || site.DepotMagazines.Count() > 96 || site.DepotMines.Count() > 2) return 0;
|
||||
+ int count = DepotMagazineCount(site) + DepotMineCount(site);
|
||||
+ if (count > 96) return 0;
|
||||
+ return count;
|
||||
+ }
|
||||
+ IEntity DepotItem(ERR_SiteRuntime site, int index)
|
||||
+ {
|
||||
+ if (index < 0 || index >= DepotItemCount(site)) return null;
|
||||
+ int magazines = DepotMagazineCount(site);
|
||||
+ if (index < magazines) return site.DepotMagazines[index];
|
||||
+ return site.DepotMines[index - magazines];
|
||||
+ }
|
||||
void DepotStock(ERR_SiteRuntime site, out array<IEntity> items)
|
||||
{
|
||||
items = {};
|
||||
- int count = DepotMagazineCount(site);
|
||||
- for (int i = 0; i < count; i++) items.Insert(site.DepotMagazines[i]);
|
||||
+ int count = DepotItemCount(site);
|
||||
+ for (int i = 0; i < count; i++) items.Insert(DepotItem(site, i));
|
||||
}
|
||||
IEntity DepotMagazine(ERR_SiteRuntime site, int index)
|
||||
{
|
||||
@@ -80,7 +103,7 @@
|
||||
}
|
||||
bool DepotOriginal(ERR_SiteRuntime site, IEntity item)
|
||||
{
|
||||
- return item && DepotMagazineCount(site) > 0 && site.DepotMagazines.Contains(item);
|
||||
+ return item && DepotItemCount(site) > 0 && (site.DepotMagazines.Contains(item) || site.DepotMines.Contains(item));
|
||||
}
|
||||
bool Owns(IEntity entity) { return entity && m_Entities.Contains(entity); }
|
||||
// Snapshot only nearby mission-owned objects. Distant sites must not block
|
||||
@@ -416,7 +439,12 @@
|
||||
}
|
||||
ERR_StockPlacement placement = new ERR_StockPlacement();
|
||||
if (spec.Kind == ERR_LocationKind.OUTPOST && !spec.RevealOnEscape && stock.TargetId.IsEmpty()
|
||||
- && item.FindComponent(BaseMagazineComponent) && site.DepotMagazines.Count() < 96) site.DepotMagazines.Insert(item);
|
||||
+ && site.DepotMagazines.Count() + site.DepotMines.Count() < 96)
|
||||
+ {
|
||||
+ if (item.FindComponent(BaseMagazineComponent)) site.DepotMagazines.Insert(item);
|
||||
+ else if (stock.Prefab == "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et"
|
||||
+ && site.DepotMines.Count() < 2) site.DepotMines.Insert(item);
|
||||
+ }
|
||||
placement.Item = item;
|
||||
placement.Inventory = inventory;
|
||||
m_Placements.Insert(placement);
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c
|
||||
@@ -123,6 +123,7 @@
|
||||
// Admission uses the existing array object so an already-created mounted
|
||||
// coordinator observes this exact finite addition without a replacement ledger.
|
||||
protected int m_DepotImports;
|
||||
+ protected int m_DepotMineImports;
|
||||
bool DepotCurrent()
|
||||
{
|
||||
return Current() && m_State == 1 && !m_Move && !m_MineMove && !Unresolved()
|
||||
@@ -136,6 +137,32 @@
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_Stock.Contains(item)) committed++;
|
||||
return committed > m_DepotImports;
|
||||
+ }
|
||||
+ // Mine imports replace only proved outgoing original mine commitments.
|
||||
+ // Keep the startup batch binding and both lifetime identity/spent ceilings.
|
||||
+ bool DepotMineAvailable()
|
||||
+ {
|
||||
+ return DepotCurrent() && CaptureMines() && m_MineStock.Count() < 96 && m_Spent.Count() < 96;
|
||||
+ }
|
||||
+ bool DepotMineNeeded()
|
||||
+ {
|
||||
+ if (!DepotMineAvailable()) return false;
|
||||
+ int committed;
|
||||
+ foreach (IEntity item : m_Spent)
|
||||
+ if (item && m_MineStock.Contains(item)) committed++;
|
||||
+ return committed > m_DepotMineImports;
|
||||
+ }
|
||||
+ bool AdmitDepotMine(ERR_GroundDepotLoading job, IEntity item)
|
||||
+ {
|
||||
+ if (!job || !DepotMineNeeded() || !ERR_InfantryMineTransfer.ReadyMine(item)
|
||||
+ || m_MineStock.Contains(item) || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
+ if (!job.DeliveredTo(this, item, true) || !Contains(m_Truck.Entity, item)
|
||||
+ || !ERR_InfantryAmmoTransfer.StoredUnder(item, m_Truck.Entity)) return false;
|
||||
+ InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
+ if (!carried || !carried.GetParentSlot() || carried.GetParentSlot().GetAttachedEntity() != item) return false;
|
||||
+ m_MineStock.Insert(item); m_DepotMineImports++;
|
||||
+ Audit("one exact finite camp PMN4 admitted after proved physical courier delivery");
|
||||
+ return true;
|
||||
}
|
||||
ERR_ConvoyVehicle DepotTruck()
|
||||
{
|
||||
@@ -554,7 +581,7 @@
|
||||
string Status()
|
||||
{
|
||||
string detail = string.Format("Ground supply: state=%1 trips=%2 infantry moved=%3 stock=%4 spent=%5", State(), m_Trip, m_Delivered, m_Stock.Count(), m_Spent.Count());
|
||||
- return detail + string.Format("; mines moved=%1 initial=%2; %3", m_MinesDelivered, m_MineStock.Count(), m_Reason);
|
||||
+ return detail + string.Format("; mines moved=%1 allowance=%2; %3", m_MinesDelivered, m_MineStock.Count(), m_Reason);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
--- a/addons/core/Configs/ERR/EveronSites.conf
|
||||
+++ b/addons/core/Configs/ERR/EveronSites.conf
|
||||
@@ -131,6 +131,7 @@
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
+ ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
@@ -254,6 +255,7 @@
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
+ ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
@@ -283,6 +285,7 @@
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
+ ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
@@ -312,6 +315,7 @@
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
+ ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
@@ -341,6 +345,7 @@
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
+ ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
--- a/tests/test_ground_depot_provenance.py
|
||||
+++ b/tests/test_ground_depot_provenance.py
|
||||
@@ -5,14 +5,41 @@
|
||||
from test_finite_magazine_reservation import translated_reservation
|
||||
B=Path(os.environ.get('ERR_GROUND_DEPOT_ROOT',ROOT))
|
||||
S=Path(os.environ.get('ERR_SITE_SERVICE_SOURCE',B/'addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c'))
|
||||
-I=B/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'
|
||||
-L=B/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c'
|
||||
+I=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',B/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
+L=Path(os.environ.get('ERR_GROUND_DEPOT_LOADING_SOURCE',B/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c'))
|
||||
+assert 'int DepotItemCount(' in S.read_text() and 'bool AdmitDepotMine(' in I.read_text(), 'finite authored camp mine provenance/import API is absent'
|
||||
+# Read the actual authored configuration, not a duplicated stock fixture.
|
||||
+conf=(B/'addons/core/Configs/ERR/EveronSites.conf').read_text()
|
||||
+pmn='{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et'
|
||||
+camps=[]
|
||||
+for match in re.finditer(r' ERR_SiteDefinition \{',conf):
|
||||
+ end=match.end();depth=1
|
||||
+ while depth:
|
||||
+ if conf[end]=='{':depth+=1
|
||||
+ elif conf[end]=='}':depth-=1
|
||||
+ end+=1
|
||||
+ block=conf[match.start():end]
|
||||
+ eligible=bool(re.search(r'^ Kind 3$',block,re.M)) and not re.search(r'^ RevealOnEscape 1$',block,re.M)
|
||||
+ stocks=re.findall(r'ERR_SiteStock \{ Prefab "([^"\n]+)" Count (\d+)([^}]*?) \}',block)
|
||||
+ mines=[row for row in stocks if row[0]==pmn]
|
||||
+ if eligible:
|
||||
+ assert len(mines)==1 and mines[0][1]=='2' and 'TargetId' not in mines[0][2]
|
||||
+ camps.append(re.search(r'Id "([^"]+)"',block).group(1))
|
||||
+ else:assert not mines
|
||||
+assert len(camps)==5
|
||||
+assert 'ERR_InfantryMineTransfer' not in S.read_text(), 'Core must not depend on the AI mine transfer layer'
|
||||
source=S.read_text();start=source.index(' if (spec.Kind == ERR_LocationKind.OUTPOST');capture=source[start:source.index(' placement.Item = item;',start)]
|
||||
-access='\n'.join(body(S,k) for k in ('int DepotMagazineCount(', 'void DepotStock(', 'IEntity DepotMagazine(', 'bool DepotOriginal('))
|
||||
-admit='\n'.join(body(I,k) for k in ('bool DepotCurrent(', 'bool DepotAvailable(', 'bool DepotNeeded(', 'bool AdmitDepot('))
|
||||
+access='\n'.join(body(S,k) for k in ('int DepotMagazineCount(', 'int DepotMineCount(', 'int DepotItemCount(', 'IEntity DepotItem(', 'void DepotStock(', 'IEntity DepotMagazine(', 'bool DepotOriginal('))
|
||||
+admit='\n'.join(body(I,k) for k in ('bool DepotCurrent(', 'bool DepotAvailable(', 'bool DepotNeeded(', 'bool AdmitDepot(', 'bool DepotMineAvailable(', 'bool DepotMineNeeded(', 'bool AdmitDepotMine(', 'protected bool CaptureMines('))
|
||||
delivered=body(L,'bool DeliveredTo(')
|
||||
def adapt(s):
|
||||
s=s.replace('array<IEntity>','Array<IEntity>').replace('out Array<IEntity> items','Array<IEntity>& items').replace('ERR_SiteRuntime site','Site* site').replace('ERR_GroundDepotLoading job','Loading* job').replace('ERR_InfantryResupply service','Service* service')
|
||||
+ s=s.replace('protected ', '').replace('ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);','Supply* supply = m_Convoy;')
|
||||
+ s=s.replace('InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));','InventoryItem* carried = item->inventoryItem;')
|
||||
+ s=s.replace('foreach (IEntity item : m_MineStock)', 'for (IEntity item : m_MineStock)')
|
||||
+ s=s.replace('ERR_InfantryMineTransfer.', 'ERR_InfantryMineTransfer::').replace('ERR_InfantryAmmoTransfer.', 'ERR_InfantryAmmoTransfer::')
|
||||
+ for name in ('supply','m_MineBatch','carried'):s=s.replace(name+'.',name+'->')
|
||||
+ s=s.replace('GetParentSlot().','GetParentSlot()->')
|
||||
for name in ('site','spec','stock','item','m_Stock','m_Spent','m_Mounted','m_Truck','job','m_Move','m_Reservation'):
|
||||
if name not in ('m_Stock','m_Spent'): s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('site->Definition.', 'site->Definition->').replace('site->Responders.', 'site->Responders->')
|
||||
@@ -26,26 +53,47 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
using string=std::string;bool server=true;
|
||||
-template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}void Insert(T x){this->push_back(x);}void RemoveItem(T x){this->erase(std::remove(this->begin(),this->end(),x),this->end());}};
|
||||
-struct Entity{bool magazine=true;};using IEntity=Entity*;
|
||||
-struct Def{int Kind=3;bool RevealOnEscape=false;};struct Stock{string TargetId;};
|
||||
-struct Responders{bool Group=true;};struct Site{Def* Definition=nullptr;IEntity Container=nullptr;struct Responders* Responders=nullptr;Array<IEntity>DepotMagazines;};
|
||||
+template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}void Insert(T x){this->push_back(x);}void RemoveItem(T x){this->erase(std::remove(this->begin(),this->end(),x),this->end());}};
|
||||
+struct Entity;using IEntity=Entity*;
|
||||
+struct Slot{IEntity attached=nullptr;IEntity GetAttachedEntity(){return attached;}};
|
||||
+struct InventoryItem{Slot* slot=nullptr;Slot* GetParentSlot(){return slot;}};
|
||||
+struct Entity{bool magazine=true,ready=false,stored=true;Slot slot;InventoryItem inventory;InventoryItem*inventoryItem=&inventory;Entity(){slot.attached=this;inventory.slot=&slot;}};
|
||||
+// Native ready predicate and storage graph are doubled; actual readiness is separately tested by mine-transfer suites.
|
||||
+struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity item){return item&&item->ready;}};
|
||||
+struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity item,IEntity){return item&&item->stored;}};
|
||||
+struct Def{int Kind=3;bool RevealOnEscape=false;};struct Stock{string TargetId,Prefab;};
|
||||
+struct Responders{bool Group=true;};struct Site{Def* Definition=nullptr;IEntity Container=nullptr;struct Responders* Responders=nullptr;Array<IEntity>DepotMagazines,DepotMines;};
|
||||
struct Sites{bool m_Stopped=false;int m_State=0;Array<Site*>m_Sites;Array<IEntity>m_Entities;bool Owns(IEntity x){return m_Entities.Contains(x);}
|
||||
''' + adapt(access)+ '\nvoid Capture(Def* spec,Stock* stock,Site* site,IEntity item){'+adapt(capture)+r'''}
|
||||
};
|
||||
''' + translated_reservation()+r'''
|
||||
struct Service;
|
||||
-struct Proof{bool done=true,delivery=true;bool Confirmed(){return done;}bool Delivery(){return delivery;}};
|
||||
-struct Loading{bool m_Imported=false,valid=true;int m_State=5;Service* m_Service=nullptr;IEntity m_Item=nullptr;Proof* m_Move=nullptr;ERR_FiniteMagazineReservation* m_Reservation=nullptr;bool Valid(){return valid;}bool DeliveredTo(Service*,IEntity);};
|
||||
+struct Proof{bool done=true,delivery=true,mine=false;bool MineCargo(){return mine;}bool Confirmed(){return done;}bool Delivery(){return delivery;}};
|
||||
+struct Loading{bool m_Imported=false,valid=true,m_MineCargo=false;int m_State=5;Service* m_Service=nullptr;IEntity m_Item=nullptr;Proof* m_Move=nullptr;ERR_FiniteMagazineReservation* m_Reservation=nullptr;bool Valid(){return valid;}bool DeliveredTo(Service*,IEntity,bool=false);};
|
||||
struct Mounted{bool busy=false;bool Busy(){return busy;}};
|
||||
struct Truck{IEntity Entity=nullptr;};
|
||||
-struct Service{bool current=true,truckValid=true,unresolved=false,m_Move=false,m_MineMove=false;int m_State=1,audits=0,m_DepotImports=0;Array<IEntity>m_Stock,m_Spent,cargo;Mounted* m_Mounted=nullptr;Truck* m_Truck=nullptr;bool Current(){return current;}bool Unresolved(){return unresolved;}bool TruckValid(bool endpoint){assert(endpoint);return truckValid;}bool Contains(IEntity,IEntity item){return cargo.Contains(item);}void Audit(string){audits++;}
|
||||
+struct Batch{bool complete=true;Array<IEntity>items;bool Complete(){return complete;}int Count(){return items.Count();}IEntity At(int index){return items[index];}};
|
||||
+struct Supply{Batch*MineStock=nullptr;};
|
||||
+struct Service{Supply*m_Convoy=nullptr;Batch*m_MineBatch=nullptr;bool m_MineStockCaptured=false;Array<IEntity>m_MineStock;int m_DepotMineImports=0;bool current=true,truckValid=true,unresolved=false,m_Move=false,m_MineMove=false;int m_State=1,audits=0,m_DepotImports=0;Array<IEntity>m_Stock,m_Spent,cargo;Mounted* m_Mounted=nullptr;Truck* m_Truck=nullptr;bool Current(){return current;}bool Unresolved(){return unresolved;}bool TruckValid(bool endpoint){assert(endpoint);return truckValid;}bool Contains(IEntity,IEntity item){return cargo.Contains(item);}void Audit(string){audits++;}
|
||||
''' + adapt(admit)+r'''};
|
||||
-''' + adapt(delivered).replace('bool DeliveredTo(', 'bool Loading::DeliveredTo(')+r'''
|
||||
+''' + adapt(delivered).replace('bool DeliveredTo(', 'bool Loading::DeliveredTo(').replace('bool mineCargo = false','bool mineCargo')+r'''
|
||||
struct F{Entity cache,item,foreign,truck;Def def;Stock stock;Responders responders;Site site;Sites sites;Array<IEntity>original,spent;ERR_FiniteMagazineReservation reservation;Service service;Loading job;Proof proof;Truck vehicle;Mounted mounted;
|
||||
F():reservation(&original,&spent,&item){site.Definition=&def;site.Container=&cache;site.Responders=&responders;sites.m_Sites={&site};sites.m_Entities={&cache};sites.Capture(&def,&stock,&site,&item);original={&item};assert(reservation.Reserve()&&reservation.Commit());job.m_Reservation=&reservation;job.m_Move=&proof;job.m_Item=&item;job.m_Service=&service;vehicle.Entity=&truck;service.m_Truck=&vehicle;service.m_Mounted=&mounted;service.cargo={&item};}
|
||||
};
|
||||
+struct M:F{Entity initial;Batch batch;Supply supply;
|
||||
+ M(){item.magazine=false;item.ready=true;initial.magazine=false;initial.ready=true;batch.items={&initial};supply.MineStock=&batch;service.m_Convoy=&supply;service.m_MineBatch=&batch;service.m_Spent={&initial};job.m_MineCargo=true;proof.mine=true;}
|
||||
+};
|
||||
int main(){
|
||||
+ // Authored inert mines join detached startup provenance, without replacing magazine APIs.
|
||||
+ {F f;f.sites.m_State=1;f.stock.Prefab="{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et";Entity mine;mine.magazine=false;mine.ready=true;f.sites.Capture(&f.def,&f.stock,&f.site,&mine);assert(f.sites.DepotMagazineCount(&f.site)==1&&f.sites.DepotMineCount(&f.site)==1&&f.sites.DepotItemCount(&f.site)==2);assert(f.sites.DepotItem(&f.site,1)==&mine&&f.sites.DepotOriginal(&f.site,&mine));Array<IEntity>out;f.sites.DepotStock(&f.site,out);out.clear();assert(f.sites.DepotItemCount(&f.site)==2);Entity other;other.magazine=false;other.ready=true;assert(!f.sites.DepotOriginal(&f.site,&other));f.sites.Capture(&f.def,&f.stock,&f.site,&other);Entity third;third.magazine=false;third.ready=true;f.sites.Capture(&f.def,&f.stock,&f.site,&third);assert(f.sites.DepotMineCount(&f.site)==2&&!f.sites.DepotOriginal(&f.site,&third));}
|
||||
+ for(int bad=0;bad<4;bad++){F f;f.item.magazine=false;f.item.ready=true;f.stock.Prefab="{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et";f.site.DepotMagazines.clear();if(bad==0)f.def.RevealOnEscape=true;if(bad==1)f.def.Kind=4;if(bad==2)f.stock.TargetId="radio";if(bad==3)f.stock.Prefab="foreign";f.sites.Capture(&f.def,&f.stock,&f.site,&f.item);assert(f.site.DepotMines.empty());}
|
||||
+ {M f;assert(f.service.DepotMineNeeded()&&!f.service.DepotNeeded());assert(f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==2&&f.service.m_DepotMineImports==1&&f.service.m_Stock.empty());assert(!f.service.DepotMineNeeded()&&!f.service.AdmitDepotMine(&f.job,&f.item));assert(f.spent.Count()==1&&f.service.m_Spent.Count()==1);ERR_FiniteMagazineReservation next(&f.service.m_MineStock,&f.service.m_Spent,&f.item);assert(next.Reserve()&&next.Commit());assert(f.service.DepotMineNeeded());}
|
||||
+ // Known mine expenditure only; missing/deleted/magazine identities never become mine demand.
|
||||
+ {M f;f.service.m_Spent.clear();assert(!f.service.DepotMineNeeded());f.service.m_Spent={nullptr,&f.foreign};f.service.m_Stock={&f.foreign};assert(f.service.DepotNeeded()&&!f.service.DepotMineNeeded());f.service.m_MineStock={nullptr};assert(!f.service.DepotMineNeeded());}
|
||||
+ for(int bad=0;bad<21;bad++){M f;assert(f.service.DepotMineNeeded());if(bad==0)f.service.current=false;if(bad==1)f.service.m_State=7;if(bad==2)f.batch.complete=false;if(bad==3)f.supply.MineStock=nullptr;if(bad==4)f.service.m_MineBatch=nullptr;if(bad==5)f.service.m_MineStock.resize(96,&f.initial);if(bad==6)f.service.m_Spent.resize(96,&f.initial);if(bad==7)f.item.ready=false;if(bad==8)f.service.m_Stock.Insert(&f.item);if(bad==9)f.service.m_Spent.Insert(&f.item);if(bad==10)f.service.cargo.clear();if(bad==11)f.item.stored=false;if(bad==12)f.item.inventoryItem=nullptr;if(bad==13)f.item.inventory.slot=nullptr;if(bad==14)f.item.slot.attached=&f.foreign;if(bad==15)f.job.m_MineCargo=false;if(bad==16)f.proof.mine=false;if(bad==17)f.job.m_State=7;if(bad==18)f.job.valid=false;if(bad==19)f.proof.done=false;if(bad==20)f.service.m_Spent.clear();int before=f.service.m_MineStock.Count();assert(!f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==before&&f.service.m_DepotMineImports==0);}
|
||||
+ {M f;f.batch.items.clear();f.service.m_Spent.clear();assert(!f.service.DepotMineNeeded()&&!f.service.AdmitDepotMine(&f.job,&f.item));}
|
||||
+ {M f;assert(f.service.DepotMineNeeded());f.service.m_MineStock.resize(95,&f.initial);assert(f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==96&&f.service.DepotCurrent()&&!f.service.DepotMineAvailable());}
|
||||
+
|
||||
{F f;Array<IEntity>out;f.sites.DepotStock(&f.site,out);assert(out.empty());f.sites.m_State=1;f.sites.DepotStock(&f.site,out);assert(out.Count()==1&&out[0]==&f.item);out[0]=&f.foreign;out.clear();assert(f.sites.DepotOriginal(&f.site,&f.item)&&!f.sites.DepotOriginal(&f.site,&f.foreign));assert(f.sites.DepotMagazine(&f.site,-1)==nullptr&&f.sites.DepotMagazine(&f.site,1)==nullptr);f.sites.m_Stopped=true;assert(!f.sites.DepotOriginal(&f.site,&f.item));}
|
||||
for(int kind=0;kind<6;kind++){F f;f.site.DepotMagazines.clear();if(kind==0)f.def.RevealOnEscape=true;if(kind==1)f.def.Kind=4;if(kind==2)f.stock.TargetId="radio";if(kind==3)f.item.magazine=false;if(kind==4)f.site.DepotMagazines.resize(96,&f.foreign);f.sites.Capture(&f.def,&f.stock,&f.site,&f.item);assert(f.site.DepotMagazines.Contains(&f.item)==(kind==5));}
|
||||
for(int bad=0;bad<7;bad++){F f;f.sites.m_State=1;if(bad==0)server=false;if(bad==1)f.sites.m_Sites.clear();if(bad==2)f.site.Container=nullptr;if(bad==3)f.sites.m_Entities.clear();if(bad==4)f.site.Responders=nullptr;if(bad==5)f.responders.Group=false;if(bad==6)f.site.DepotMagazines.resize(97,&f.item);assert(f.sites.DepotMagazineCount(&f.site)==0);server=true;}
|
||||
@@ -80,4 +128,4 @@
|
||||
{F f;f.job.m_State=7;f.proof.done=true;assert(!f.service.AdmitDepot(&f.job,&f.item));f.job.m_State=5;f.job.valid=false;assert(!f.service.AdmitDepot(&f.job,&f.item));}
|
||||
}
|
||||
''')
|
||||
-print('PASS: actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption')
|
||||
+print('PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption')
|
||||
@@ -0,0 +1,19 @@
|
||||
check: /tmp/err-policy-sgdi7y8u/check.cpp:211: int main(): Assertion `f.service.DepotMineNeeded()&&!f.service.DepotNeeded()' failed.
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-depot-mines-stock-1116/tests/test_ground_depot_provenance.py", line 50, in <module>
|
||||
run(r'''
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<77 lines>...
|
||||
}
|
||||
^
|
||||
''')
|
||||
^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-sgdi7y8u/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup
|
||||
@@ -0,0 +1 @@
|
||||
PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"scope": "SiteService, EveronSites.conf, InfantryResupply and existing ground-depot provenance test only; courier/lifecycle/root patches separate.",
|
||||
"authored": "Five eligible nonopening OUTPOST definitions receive exactly2 PMN4 each at original startup (10 total in authored scenario). No changes to Southern opening cache, other site kinds, guard counts or resupply generation.",
|
||||
"provenance": "Core captures exact spawned identity only for authored PMN4 resource, untargeted eligible outpost stock, max2 per camp and96 combined identities. Core has no AI class dependency. READY-only detached generic ItemCount/Item/Stock/Original APIs; magazine APIs preserved. No late inventory scan or refresh. Native inert readiness is checked by upper mine controller/transfer/final admission and root initial stock witness.",
|
||||
"import_contract": "DepotMineAvailable preserves exact initial convoy batch via CaptureMines and closed initial allowance (max2 startup), then mine lifetime96 and shared outgoing spent96. DepotMineNeeded counts only nonnull committed identities already in retained mine allowance beyond distinct m_DepotMineImports; magazine commitments/null/deletion create no demand. Imported identities can later be spent through existing mine supply; zero original allowance cannot bootstrap demand. Final AdmitDepotMine rechecks needed, ReadyMine, typed DeliveredTo(...,true), actual inventory Contains and reciprocal owner-slot custody, then appends exactitem andincrementsmineimports once. Return maintenance remains DepotCurrent rather than demand/cap, so95to96 does notcancelreturn.",
|
||||
"accounting": "m_Stock magazine allowance/import count unchanged; original batch still bound and never rewritten; m_MineStock represents startup+provedimports, Status now labels allowance rather than initial. Source depot spent and outgoing truck spent stay separate. No engineer grant/placement policy changes.",
|
||||
"tests": {
|
||||
"primary": "tests/test_ground_depot_provenance.py actual Core capture/accessors, CaptureMines, mine/magazine demand/import, DeliveredTo and finite reservation; native ReadyMine/slot graph boundaries doubled explicitly",
|
||||
"green": "provenance-green.log (before final status-label-only change; extracted tested methods unchanged)",
|
||||
"baseline_absence": "baseline-feature-absence.log fails explicit feature-presence assertion before compilation; no fake behavioral red claim",
|
||||
"negative_control": "mutation-magazine-demand.log compiles then runtime-fails when mine demand counts magazine allowance",
|
||||
"existing_planning": "planning-green.log, unchanged actual planning suite against proposed service including final status label",
|
||||
"scope": "No fullsuite/native/target writes. Compiler sessions finished."
|
||||
},
|
||||
"peer_dependency": {
|
||||
"loader": "/tmp/erri-depot-mines-courier-1116/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c",
|
||||
"loader_sha256": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d"
|
||||
},
|
||||
"logs": {
|
||||
"provenance-green.log": "e26ca35beb9bdd2800680a97f46df2693145f8ed2d63e42c745c73e3238d2205",
|
||||
"baseline-feature-absence.log": "ee96c32a45ad254096dd0046f4d4411d7c7d8b7b71a2e17754665abb23d4bcf4",
|
||||
"mutation-magazine-demand.log": "ab0fe2ac580e35331683845aeb0b42f7b0e57bfd3840f5e1cba3be57557da5b1",
|
||||
"planning-green.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21"
|
||||
},
|
||||
"owned_reference": {
|
||||
"path": "/home/jakub/devel/escapists/escapists-ai/Scripts/Game/EscapistsAI/EAI_DepotLoading.c",
|
||||
"read_only": true,
|
||||
"review": "Original uses real porter cargo lines but creates stock/staff and calls Fill at Begin. This successor slice reuses physical responders and finite startup-only stock; does not copy refill/spawn behavior."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": {
|
||||
"before_working_sha256": "210646e679056f4a46ef454a5abe15bd42d48349aa376ccfbb6b3b2ebeac6812",
|
||||
"before_index_sha256": "9bd0824995d3e08cdb2745f1cb539ddd27e422509814188ea6ab2ba56631e7cd",
|
||||
"proposed_sha256": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712"
|
||||
},
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": {
|
||||
"before_working_sha256": "bf50a7a7d5cd182d29a02ea5de8d58b46979019158250c5ab589ed8ffe49b974",
|
||||
"before_index_sha256": "966068555a6724e620a2c377b98d8dc02f141466c5cdd44636f86cb1cfe9ac78",
|
||||
"proposed_sha256": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35"
|
||||
},
|
||||
"addons/core/Configs/ERR/EveronSites.conf": {
|
||||
"before_working_sha256": "b479000b36154a6a3af6b519b086251d981ef63cb86a973d00529499cfd4238c",
|
||||
"before_index_sha256": "b479000b36154a6a3af6b519b086251d981ef63cb86a973d00529499cfd4238c",
|
||||
"proposed_sha256": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1"
|
||||
},
|
||||
"tests/test_ground_depot_provenance.py": {
|
||||
"before_working_sha256": "33880dbf308dd4f338cc4e4bb04449d662cc2fe0941721a819528b7f7a6decd7",
|
||||
"before_index_sha256": "33880dbf308dd4f338cc4e4bb04449d662cc2fe0941721a819528b7f7a6decd7",
|
||||
"proposed_sha256": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85"
|
||||
}
|
||||
},
|
||||
"patch_sha256": "c7273b6800da3600cc49348000b139a5caaf50bc6395640d5ff59c674c0fdb43"
|
||||
}
|
||||
@@ -0,0 +1,988 @@
|
||||
{
|
||||
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"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/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "572cc36f88255a37e8f0e9f284fb96e07c6c4032506b34b8c77d688f02785400",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "077c09491f4444fc58f093975fe9b3c294ea1fc966abef847ee5f13aa795ee29",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "1c4bc25a6ce9b5ee10f82592f955b0019d13ddb4084a783fadb98d267bd0f4fc",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "e306b9d179b97d0478f821be3ca606c71908a21a4f87085b37a5fd18c4e3575d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "c0c3d9d1cf4615f38c793f1250315bbdb9349f33afa0841851da89433a303c3e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "1b466886e9f5fbde1de0be20395e3887046c6b5a9a239dae92cecbfb721714c2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "ec25e5c3a5b97527f9cd70341c10d69d7124048089d26883ac2f8c9b3fd2815d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "4d0e8b6e147486fb65db82a1060f0c5641c1319ba9e418bdec99cb5a422a7fbe",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "b59016d83cb9d40136b98b4e0067ea490bc553574fc53603593efd5522dbed20",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "defb12924ea5dfe68f86c2bbb4b07362f016ffee810f720d13f01d81881b3cfc",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c": "bcddb72845189b52e5ed71c687d7dd4b0b40b91b7306c3f6edf84a631002fc5b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "d873b5b689e918f8c907918d673304a184ac2e4a4cb6face527b37a67821ee9f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "88ea0fc0e13d7e3c22c7ce8b652816d1d137e4e6e37a72f48f0bdf515b936ae7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "cee3ae301ac2f211c290450b644a7942c9786a2a40d06f16e2a47efa96fd15b6",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "a37edcf66e43945f331db47fe81cb2e0e767a7aaf8115244dcf9e6295932be98",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"addons/core/UI/layouts/ERR/AdminMenu.layout": "e8d570f7bf3b8c4067ad81d47bca7f35514b2f8c8748f5fa5f775fbe27debeac",
|
||||
"addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"addons/core/UI/layouts/ERR/ContentRow.layout": "62d2c95814c99d906266fa96c6112e04a7fab1667e1a05e558d1d3974adc2d76",
|
||||
"addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"addons/core/UI/layouts/ERR/ItemRow.layout": "8ac6fbc7fe0ce0ffc3185516197303bb892a4415948f75ae06f3bc289fefcac6",
|
||||
"addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"tests/helicopter_availability_regression.py": "3f256b7f5db246723b75caa2cc247249881cba95bde71ea1c90733404fe19f35",
|
||||
"tests/mortar_salvo_regression.py": "0f5d5f5d33f64ff43f5a2b954fe4eec032a00697f51f09efa10284537a3682db",
|
||||
"tests/test_mission_rules.py": "f534ae447fe1db6ae939430c3b14568d2bf1b84956dca295cce04211411d9ee7",
|
||||
"tests/policy_harness.py": "e861c30037b3e456f0c8ef1c02e9fe1417b601ffb15d2037974715008865e4be",
|
||||
"tests/test_time_policy.py": "45ae5768f6e87009b4074937cbc2e384c59341e905a3f250672bd2a110b2e6c5",
|
||||
"tests/test_radio_defence_policy.py": "48c9c01dc6135a3f6d2187b0974645758040f041c3c2c2c26b14222fc572dfe1",
|
||||
"tests/test_performance_comparison.py": "5f932de9e9898acdd379f26c777a35c884269522dbf8c41991a7a25bf61c369a",
|
||||
"tests/test_release_check.py": "8b6e755ed922ad129ba01c228989610a31f3a79841dc7cdddd4ddbd0e510971b",
|
||||
"tests/test_player_admission_policy.py": "745ec0a9e491ffcf5bec53ebf67ecee8333f4dcfa5d19bafbde31cbd1cad7f8b",
|
||||
"tests/test_recovery_policy.py": "adc4966ab92f0849d08636d93da5bd02b9162d1ad7369b325a1a357903abaa55",
|
||||
"tests/test_admin_setting_policy.py": "69af6f74e262ee4981ac428ac1ab85561f8b365aed5879e20d315ededca9ee22",
|
||||
"tests/test_prison_placement_policy.py": "34539744426f0b30e41883203484ed60606df8ca319324014f07e833bcbf854b",
|
||||
"tests/test_environment_policy.py": "66b86e66f47c4ce397c6093a50a724bbe8dedbf3db53e0dd7d53ff33243a0b52",
|
||||
"tests/test_faction_catalog_scope.py": "c8fab92575f2621f47ed8685243338aa9ea717bb809c2ef9e8e0884af9df263b",
|
||||
"tests/test_environment_restart_runner.py": "05bc09bc45db70ba4a635b65b0a96aa38437ba50c98640b47ed8d0683c3a5f71",
|
||||
"tests/test_inventory_enumeration_policy.py": "95cbfd7c4351cb9a8e1cd6783524be79f77255e5996299919a61dcfce8b0f21a",
|
||||
"tests/test_site_discovery_policy.py": "40fda37b86d469a1cf8fcb7a1fb18abcaab0df44ad09f50018744d42f8f4f649",
|
||||
"tests/test_headless_game_runner.py": "0d84160076ec9961e7315ccd50d6ce45ff971328c298649505fbba6305c22f31",
|
||||
"tests/test_initial_guard_policy.py": "0c80e744db1ce0a0d0746c43d867f5d2f47d9b92bc48d6561ceeb28a204d8743",
|
||||
"tests/test_casualty_loading_policy.py": "cdf2c0abe4b794502f18228b173db47c4093ea062378ec9e3971e0c4f9e3bf1f",
|
||||
"tests/test_casualty_reservation_death.py": "fd68dce04ea48ee2a22fac499c32a5c53847a25e3f14eaba3f50437d2c040f25",
|
||||
"tests/test_casualty_ground_policy.py": "6543c594293d7122242ec68d506a92dc81464d110cdb7496a225555cee338c83",
|
||||
"tests/test_guard_cancellation_policy.py": "f8f134b6d525a3c775677b2a95c562b12aa84ba287318c08c833d684ad0bd9d8",
|
||||
"tests/test_radio_feedback_policy.py": "6b576472f81a35bd4df4dae3f19925b046eedbba262ad67f9bfe1ce9d220a487",
|
||||
"tests/test_extraction_placement_policy.py": "d924f163d98c78989938ca01eca5935891fb454266810f4817cbe49651b84ae2",
|
||||
"tests/test_casualty_remove_probe.py": "e3b8ac386bb8e4a9832215cbbe1cacf7a5bd1314467bd4b07ed4a57b2db75458",
|
||||
"tests/test_casualty_incapacitation.py": "55b5cfb7b3eae496a8cc18888872d11331ecc01afb7326fbee3b8d65047dbe93",
|
||||
"tests/test_diagnostic_no_splash.py": "d99539a8b3277c2f1ac3e3bfa4c897876fe21e704c9ae33c542eed79fc2e9e65",
|
||||
"tests/test_native_mortar_probe.py": "217801a6eddd48f76e99363a72a9812c0f48766ebd2faf8e188f4466ed1e4088",
|
||||
"tests/test_local_admission.py": "0bde82f6d5c31c4187ed0aa1935940b8b9e634868b3a4820eca073580ad136b4",
|
||||
"tests/test_dedicated_preflight.py": "0d654375db6b8eb91d0b92663b50e32776aaa7ecafbfdb83c00f04826df5236e",
|
||||
"tests/test_mortar_aim_renewal.py": "cf228b7f83d247d93277ec4c8644eb1090a20336a7e9ee2b90086c78199a70ca",
|
||||
"tests/test_native_mortar_transfer.py": "3b2a201a73c9ff2509276428988e4a98023c6aa94f8eeb42bc06c6cc604473d2",
|
||||
"tests/test_dedicated_native.py": "f0323b20743221bd1ad46d6462246c2a0e2be84b395e40faa39007ef330aaa3c",
|
||||
"tests/test_mortar_report_ledger.py": "fd2346e06c37a9e7621e1861e0f472b72ac14786fd2bcfbd785b62700d55ffde",
|
||||
"tests/test_native_local_admission_probe.py": "16864bc359ab607dae3919442bd18f191320721411a8156e23be999f24e4454f",
|
||||
"tests/test_powered_flight_policy.py": "86bfd5851be6fe3a187e1fe7fd2b7b0965c891cf29b2260b0df292255c5c547a",
|
||||
"tests/test_prison_escape_policy.py": "d5d54588116eb730a8fda046f25fc4edc89a5345f85774cbc0f0a9b3adb85b98",
|
||||
"tests/test_powered_flight_pad.py": "690c1c6e05f3520a6d4d6c45a0fc5d9184e30a12b24356b3126bdb35c4171b82",
|
||||
"tests/test_item_station_teardown.py": "4e0f508dea6172862be82d6c7f295ede2bfb2412c390a0937a75ab176655f4b6",
|
||||
"tests/test_source_bundle.py": "074ad87ee7ab0b41ab94a7cb28efca66a975c24b8e2574122a13a52a4d491d0a",
|
||||
"tests/test_native_flight_footprint.py": "96923c018608f0c4d24294a9f8e769e2037be1fac8f1d51f4d73463706e134ad",
|
||||
"tests/test_native_flight_input_diagnostics.py": "355e2e45b86b9a46c68efb0563d16bef7a032cd7758169704b4b26ea92bee2bc",
|
||||
"tests/test_mortar_logistics.py": "98cdf38e43eb564163d8b409dfc95c4ae23e775c423651f05698acd52a7ef5a2",
|
||||
"tests/test_mortar_courier_storage.py": "0eb75fbcdcd712ff1c2220dcdd87cff6f3ed1e6e8f1c889916daa6b84a4359f5",
|
||||
"tests/test_progression_identity.py": "2fb3725aa735e00b20ba7a4ac45f8e087d4346c58a176bee091bab0a9755c1df",
|
||||
"tests/test_discovery_map_position.py": "0644aea60d4c546e819ef417771563ab7598e84d5e13db2fa63416ae1fe6ddb0",
|
||||
"tests/test_vanilla_game_control.py": "8ab3777a5bd0f8213efae08bd6db70a05790af992c2abfda8e5e5aa079beebbb",
|
||||
"tests/test_archive_game_control.py": "8126e2be91f9ee8c09fceb82d03bb0d9c51247909189a424c3e24dd2b1ed22ce",
|
||||
"tests/test_flight_action_runner.py": "aa14ebe85fce7c0435f48aceec1d4463b33fe8a5792b4e935b543dff94f4ad02",
|
||||
"tests/test_native_package.py": "0776a1eedede7185aa36c7fe816ea6231e6f475c0f6d210a2c732b23dc6d765e",
|
||||
"tests/test_spectator_guidance.py": "26c02deb1a707f51dcf577a9ccb789bf33f432b41d9404d36a7b1b3c8802298f",
|
||||
"tests/test_native_mortar_salvo.py": "f45625eb92d16adc8b3eb57bc72b77c8829d46c2c7e5bef40d302fc90252ba72",
|
||||
"tests/test_pak_inventory.py": "8f0b55bb295117c226900bd641d25175db1021a365866a5ce6482a78d08c7f41",
|
||||
"tests/test_packed_core_game.py": "ddac4281f74999b1e60c2052bbdee36c97699192cfd5174a88b6f01ee740111e",
|
||||
"tests/test_mortar_refresh.py": "0ac74cff8aa10fb06ecb75d17eb7ca3a6b80bf5194522bffec583a44fc01a419",
|
||||
"tests/test_archive_packed.py": "37712810b7c6fd11a2df35665df81546f8b98682dc74b317ad1f9ad6ad274d86",
|
||||
"tests/test_native_mortar_refresh.py": "60f3c4fcb063506e9bd85e4abd3cd2fc802304bc71933f3e31d88f5b896aaa7b",
|
||||
"tests/test_mortar_activity_completion.py": "a0db3b63962bc95de42ec12ef17c53730464ac7421a4475020957121513586ec",
|
||||
"tests/test_packed_chat_game.py": "d23c099d17a0dda09e5ee28931a4850f9bf6df5a7874581342eacbd16860565e",
|
||||
"tests/test_shared_map_ownership.py": "486eb3a8a04a47878b87ec3952c613542871077af1de27ea7299fa3d72caff1d",
|
||||
"tests/test_native_shared_map_ownership.py": "672d248550339dc6350e548034c50b3440d44b91668457f3efb2d91c8445c3dc",
|
||||
"tests/test_participant_selection.py": "e153f69ffa60d186dc3b1a238df1d48f2a0623b2dd8331d2cbbbdd57cce5529e",
|
||||
"tests/test_ordinary_screenshot.py": "eadd4f8ae2a8057d0ac7bca5e8f4abc260faa10cddfca31b8552d7b49669ab33",
|
||||
"tests/test_aircraft_flight_policy.py": "147a27fb57c0b01cded35eae26af4394d7f41eeeb68856f564972e1c89c629c9",
|
||||
"tests/test_aircraft_flight_envelope.py": "6499ec174ed68dbfc07bd49275eaff8a7e60865615bbaefee354de7233a6ff13",
|
||||
"tests/test_native_aircraft_control.py": "3ffed5429896254d96b67ff3fdd01f65689f526e6a1766cc6874e2e63f2e26f3",
|
||||
"tests/test_aircraft_translation.py": "983fcff4800e777cd1c42126431ca94e7c03bc06b5fb34a243704b8ca55dc36d",
|
||||
"tests/test_action_feedback.py": "1fec11a218b6da69c8c40ce232523582f0ad390f8357e74f24daccf5d46d3814",
|
||||
"tests/test_spawn_retry_budget.py": "c182acfcfd52cd74a94dc3336d7603d14668850a684b758cc7545a98a5d14beb",
|
||||
"tests/test_native_stats.py": "a9ce90c74f0ae7e5c40e451f6b1d60dadde831c3d858710a70929390d5c70f7c",
|
||||
"tests/test_native_end_lifecycle.py": "8b187723c9039e68e3e590c812c91dcffe1e5917d4e450ed798dc177888fda7a",
|
||||
"tests/test_native_end_runner.py": "aed94be9b370a412937303cc5b66f0151c2cd64c3e1358f983f9ea53eb0d1057",
|
||||
"tests/test_escape_result_wording.py": "7b3613cccd4f24d3ef4665dfc1854cfc958a69018a59f9b8090617f0185a82a8",
|
||||
"tests/test_preparation_status.py": "e43cb7ce81232a31d00219004574dc2d1806760e0b6f0c49693725ffcb1b4e9e",
|
||||
"tests/test_headless_display_probe.py": "d4d6c9907d7419ca888d5d9ba7448cbe6f5d2e53810f74c85660dfbdfc9f7e2d",
|
||||
"tests/test_headless_display_runner.py": "f03a908e813c9ca4dc2ff13b3ade08549931e39490b8636742390a304c73974f",
|
||||
"tests/test_rough_intel_feedback.py": "d7395ecc498dda46e1c9a4c8fbf98a64f2bbd013de7806517fb8008756e7b40d",
|
||||
"tests/test_aircraft_route_envelope.py": "08b16d4e7f97db96e3f88af0cfccd9b6bc083f6f25ec33cffd7ec36b18798729",
|
||||
"tests/test_aircraft_route_policy.py": "b717734a07a59ada837f05c36172110bd7d0b5a5a277e8fae55a11dcab3e2aa2",
|
||||
"tests/test_aircraft_route_probe.py": "bd8cb998fef33db8f26342eec0198c54b7715662d333530e2bede572c81f162f",
|
||||
"tests/test_ordinary_input_observer.py": "09cf661ae47f53cb429a7ab17c2b752ae30a04368a260468227b0678148b2434",
|
||||
"tests/test_ordinary_input_runner.py": "1ed373818673a438647fc7074c4c689f5bac0a91e8d55edf29d466b96f6703f8",
|
||||
"tests/test_private_prefix_cleanup.py": "bc6d3fcf6a5ee5b5266bfc4516642d2f73e71dfc870c527d67cb5a47964dede0",
|
||||
"tests/test_runner_private_cleanup.py": "4380874af7553391ea7e1e234c8a3f8e61922e0f16b1bf9bd4821cc479e5edf4",
|
||||
"tests/test_headless_input_proof.py": "55c84de6dac3a9c44bd1ab4113d306544025a405c613f6e7d26550328e84f6c1",
|
||||
"tests/test_headless_input_exercise_runner.py": "0b812647718a3d7145905a3ed17fef97b025d57b1372773d2c1069a3473a9b1f",
|
||||
"tests/test_inventory_control_runner.py": "f325fe1975f7a56fbbb1a6357206d2ac0c9e7c32c396473fdfaf1cb80ad39b11",
|
||||
"tests/test_inventory_layout.py": "8e176f8a87c300b8062a37ee34b22a105978c7d9c6147b506757135f4f48a1ff",
|
||||
"tests/test_radio_waiting_text.py": "2aa54d8126b3fddae2b77d496f56d2d6e6d393c6d5124bdb5598713d9c29d629",
|
||||
"tests/test_relative_look_runner.py": "131d829c60a7bbfe3e047af8e38d255e5ecb9d84b7d2188d14422dde724fa05e",
|
||||
"tests/test_ordinary_look_observer.py": "cd5842e54c9ccab16766637bf2ab4e4e0b98f4d597b5927b0c2ec3f720fa3668",
|
||||
"tests/test_ordinary_look_evidence.py": "1b98be4b69a5e5bacf46791f1e009fa3c73cdaff875c012837c9888443a61633",
|
||||
"tests/test_ordinary_gate_observer.py": "78ff734604724a525809567ecda88f4d5fcd67816a6ba4960b72d0685f1a8b00",
|
||||
"tests/test_ordinary_gate_evidence.py": "2bb3cff082b3fe45f668933a5039fd06a8d31562049cdd41c4f32181136ea5df",
|
||||
"tests/test_prison_approach_proof.py": "ca71ba6c8cc20dad52d2966984676a111004333c24bc408f1ec84312e4208039",
|
||||
"tests/test_prison_approach_evidence.py": "660e03b6f9932947c1aafc4c043c2a2c5bca776433c2146df18e8bb90c606a9a",
|
||||
"tests/test_aircraft_route_demand.py": "96d9a21c49605cb671525f977928a21c57f1d0b441460a2624892006e7057efb",
|
||||
"tests/test_prison_alignment_proof.py": "04c96825ea03b95c3966e3a53ce2c15990d63388386d84f2bff3e6b6838b18c0",
|
||||
"tests/test_prison_alignment_evidence.py": "214af04ff9b0e8ebf0bc97f528233f5d55fccc7623392a65c6dd286ed415e724",
|
||||
"tests/test_aircraft_control_bridge.py": "bae6f1711dcc5f55f7a813af251fc210ed017c58a8067c03d91e936824542ef0",
|
||||
"tests/test_ordinary_gate_choices.py": "0e21f2933a4862eb5fd2f04b3b32dc7de6b2ca72d920aaa332d179edadb932cf",
|
||||
"tests/test_prison_action_selection_proof.py": "1f09fb84b73ea916bb39ef985c58aa6886223e60cd425f929b3a020eef74ebae",
|
||||
"tests/test_prison_action_selection_evidence.py": "1fee0421669721618dc2f9a3039f945d470b83b186661d3b1f00291ff8b78e9f",
|
||||
"tests/test_aircraft_service.py": "9c19a09354ccfe8b41961204d80c3621d11e6704909b7266fa00e6c197bfd20b",
|
||||
"tests/test_aircraft_service_cancel_runner.py": "1220e7c45c50590d12c9a5192eb4482e7e6942d7c00f36d9a79b5ca70bd1429d",
|
||||
"tests/test_command_maintenance.py": "be2c942aa11a5f874448e94f06925f2f1de2210a14881fb7e486842119cb673c",
|
||||
"tests/test_aircraft_field_rules.py": "dbed3a499eeddf2513e3582667ea2bd90fff6ed26057891c7df6e196c3d00e84",
|
||||
"tests/test_aircraft_field_envelope.py": "67e60717a92580e3c4caa4974994cd92a96c98562be805b31319b3585f296639",
|
||||
"tests/test_aircraft_field_runner.py": "822717f77702c335667b226f025aa6525415689b492f9ed42dd256d4c893429d",
|
||||
"tests/test_prison_coarse_facing.py": "fe0ceebb74dba77005d6a7e31baa1a50156cc66f79a1d90eba4db9b27b099acb",
|
||||
"tests/test_prison_held_action_proof.py": "349ee99d36f18fb7c70382ce95f1e9d84d819575a45b6f5429394d1702f1f227",
|
||||
"tests/test_prison_held_action_evidence.py": "bbb032736774bc5db5fab7758faeaf038eeaae9eb49ba706a52f1e9bfe09fd01",
|
||||
"tests/test_prison_held_input_adapter.py": "56fa60ae69bf280e1c2e90e7882fa213914623980b6800a4312c6f1017b8f632",
|
||||
"tests/test_prison_held_runner.py": "d50905e899c2d0d92ca2f4c51dccbf2166ee21b8c6d2d4b218da459b724c5a4c",
|
||||
"tests/test_aircraft_field_flight.py": "ae5e18f0e2efe5ad01523cb1cf9bc64139094aeaac7477a900a9abd8e6ae8f18",
|
||||
"tests/test_aircraft_field_probe.py": "fe4e5b58bbdca0f366fe4c614f7506f2a05fa29fabcde345e322cdb3d62db897",
|
||||
"tests/test_initial_admission_exhaustion.py": "14d6959a1185f154389be1405c49e2f7c1c9a3f27295e26074ac4ec74380057d",
|
||||
"tests/test_casualty_feedback.py": "2d8bada9a3fd7583af4fd4f07033dd9eac28ca3bdf34a4557c8985b7a1714dbc",
|
||||
"tests/test_intel_admin.py": "f2704740a380de8e93c7ceace414744f938442cffc6bca77a3439b4ae36aade6",
|
||||
"tests/test_intel_reroll.py": "d102cff7467323440273eb457b5dfed6610d27f32c52c6fb7801ce93348ef5ae",
|
||||
"tests/test_admin_player_tools.py": "7520c768b760ef3a03dd2f17376077fc17695360a89f91df88af924899a74517",
|
||||
"tests/test_admin_session.py": "6e1850c625e18460a5d64ccbadac992b663a46bd612fcc16b6006f19b3014896",
|
||||
"tests/test_project_schema.py": "0e25ade3ee0083618c1b2837aaaef36ce33663d78f35d862e1dbec256f4d6e40",
|
||||
"tests/test_admin_tick_delivery.py": "8f61a6aaf07b0c41df2f415a1956d8f09fe61a7d4f256775ca62511030937a5d",
|
||||
"tests/test_hq_doctrine.py": "5c18ee72454cf92132dedfb4bf581d174d67fc2e423158347ebe52ca74e8a416",
|
||||
"tests/test_force_ledger.py": "3dc268db304b9465d53056edfcd8cedcc15591b411c55ae8f9bd43e163ff9c49",
|
||||
"tests/test_hq_body_observer.py": "6cae50ef0a2b2fe35845f42e90998c517c061fc417cadfac375bacc89bbe603a",
|
||||
"tests/test_convoy_budget.py": "481364c432715336825466a9ff199edeedaa2d3621daba90c0503addfa6010f7",
|
||||
"tests/test_convoy_dispatch.py": "47e77f544ec6f3f34346dc6b5082f9df0a2d869897e094ca993a92c7315468c0",
|
||||
"tests/test_convoy_admission.py": "0ace42a7e1afee7413e45a3909e7ea5c29dbb8c0e692acc3dc9a35ea7ffd4adf",
|
||||
"tests/test_native_package_external.py": "8eb3eaee401640521c67a51607104a28de89ea9c32b3b6dffd05d9d3026fca3d",
|
||||
"tests/test_convoy_road_plan.py": "62bb655a84f90e934bb894f8e472a8a06905d72e1c0b05bd641e46eb8f4873b4",
|
||||
"tests/test_convoy_placement.py": "dcbf572747a85edbfac341e7e358b1987150a2eb721708a3a025639be228a7c3",
|
||||
"tests/test_actor_group.py": "0d808be40d13866bf8bd983d62ea3a8e7772e9c49a41109fffb02c5352153a4d",
|
||||
"tests/test_external_addons.py": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"tests/test_external_profile_review.py": "a35e9670a8f5eb47d28b4d6afe498e5a58b2ab2dbdc59912a206010ac8dc5240",
|
||||
"tests/test_hq_delivered_casualties.py": "c22ad9e395b36b41e8292b034f170e14b5d13a6a02b2a81dc619dd37110ad905",
|
||||
"tests/test_hq_ammo_dispatch.py": "6c7a4cbaa41ca3bee01082ffab376fc2db5b08757aac88c5e8caf99b39677d0a",
|
||||
"tests/test_convoy_combat.py": "140d5e8c8c978f97f7f15238bf2aa4efc6ca4d9b6370ef5a0c68bf469cec0b9a",
|
||||
"tests/test_native_hq_body_probe.py": "f2b761fadf013d55d4e9c2ae11c5349fc054e767cf950aa632a43b8f4fe1d758",
|
||||
"tests/test_enemy_optics.py": "06361eccef16d60a6f5072f9b126814a8f686c478049760047bb2ae8d19b5c52",
|
||||
"tests/test_native_convoy_cover_probe.py": "68681753a1ab89a8e8e07ba7f701190bf860d07762e5a06e87da7ba606fc0de6",
|
||||
"tests/test_vehicle_security.py": "f08a1cffb0860ac7ad93e94f4cb8b7cc37b8c49b3dee72b1d310fc72d9f95422",
|
||||
"tests/test_vehicle_security_native_probe.py": "977384c5ec07588bc77aa9aeae45b008c02d55d31169e46984a1947e987545c3",
|
||||
"tests/test_vehicle_entry_diagnostics.py": "49e8b4cd8274e08de628e89f4471ddb47823af38d98b464336e8c98a4308dbda",
|
||||
"tests/test_hq_radio_node.py": "2297ae23b7a5fece845c13f16432dece6e2dde55ecc097a5be6311f470dd5242",
|
||||
"tests/test_native_maintenance_stock.py": "7acbb488f7075428c08a10cf0e975ca0d508f3bb6416eddcc2991da93a5fad91",
|
||||
"tests/test_packed_external_game.py": "c5581fa3225bbc5b160fafc26c65783eb7d551489ab101b17f7a6acc1d8d9e63",
|
||||
"tests/test_intel_registration.py": "41cd929a29ea5e6b37d856cfc873c33fa2a8130e3aad30146f522ce217875488",
|
||||
"tests/test_convoy_startup.py": "2c9106023ecb6dcfb5c96c2edc98b51695c325c685b2ced37b999b6cd4504c65",
|
||||
"tests/test_failure_result_refresh.py": "076444d2c740609ea4290de1525cd5d7fbd99beef3c48c134afb581422a3dcfe",
|
||||
"tests/test_convoy_auto_settings.py": "fe4a1e237e31bfac11f07b1986bff859f6b4712aa7759ce9e359e28e5ec2aec1",
|
||||
"tests/test_settings_migration.py": "5a82ba8672b72fb388a95e297d53452e45679ed3b94f5c7d4598455179038aef",
|
||||
"tests/test_native_memory_deadlines.py": "f2d3f0feda862318ab936031487743218a8c8241d192b34e2b1ab63a5aa2cc48",
|
||||
"tests/test_enemy_gunner_skill.py": "67172901ed950517977e535c1237e8eaab10d22d52452bbe05fe16bfbb4089fe",
|
||||
"tests/test_native_infantry_fixture_lifecycle.py": "c20ed9dd152489a8242ec0b97135b0691c9c104783bb843b0715cdd8d7c2e156",
|
||||
"tests/test_infantry_ammo_access.py": "bd80e4405c3f2029553b5e932ec49c6370b8366cd4e9ed03be89393f86c07dbf",
|
||||
"tests/test_infantry_placement_settle.py": "1490a797e016b99a222280f57875cc83096980022d1784495a80b8a406d400f7",
|
||||
"tests/test_infantry_resupply_waypoints.py": "df3596515e0bb6a4cbf1e6f07d56755344415ad1deeffb8a70f71e8ed73a139e",
|
||||
"tests/hq_network_regression.py": "63c7525b26ae6b6e2369307250e89223a77e7e28321daf4309ab76f21ca1bc50",
|
||||
"tests/test_hq_report_selection.py": "4bd4c4800c217584ad9e1b4a37968350eb9a160e0151fc8b0375781736726cc0",
|
||||
"tests/test_hq_local_handoff.py": "0fdbcac1958b0d12296753e7c9d92700079ea6c5c8e33d0e21e8318f997b79e7",
|
||||
"tests/test_hq_local_handoff_intake.py": "c51f0ca082456331eb5856bf6dad864c3852adc20beba9b6829bdef978b11d88",
|
||||
"tests/test_native_local_handoff_probe.py": "5a0904863ea00fd7ad262fcf91d8c1e55036b2041f16b043104f333c37d8c7ba",
|
||||
"tests/test_hq_road_intercept.py": "ba4ce9af49acdbf5c0c04b849761ea36abe2ec7d68ccde1f0cd731fb9e3ed451",
|
||||
"tests/test_prefab_identity.py": "2a1c6e4cb1ead0c7b36b8fffb2ba0c59dc7e025dafaf8344a8158d38fe17582d",
|
||||
"tests/test_prison_ai.py": "557015a4a3191aede258dcd7dee4ec4f555c3efde02331687185ed124cebb4fc",
|
||||
"tests/test_spawn_scene_inventory.py": "f29bee9c629072f51caf66b680013b18f608bbfc5135a1f020e1a2904e89cdd5",
|
||||
"tests/test_spawn_scene_lease.py": "adaf38b259cc36af526884d3d2312ccec0cbe6eca18d7aed2c1a066be8ea0da6",
|
||||
"tests/test_content_policy.py": "260eedd838802647af59f33a15510d2c721aa80a7540d54e47f22734041cb49e",
|
||||
"tests/test_random_settings.py": "75fbcba53ff2331811fb91051bbae1b2c28108fa9477d98372e0eb057655f225",
|
||||
"tests/test_hq_convoy_combat.py": "07a4cd8e3bcf50ced71de05d0713a7944849a38b3f33cdea27f145bd53b9708e",
|
||||
"tests/test_faction_selection.py": "77e4789499b3560e729a115197c5b02d032c291ae1bd44b1cac5a2c2c476e450",
|
||||
"tests/test_generated_sites.py": "111095f40133b025ab67380b6cdcbc25ce0ecbc03379d1a015db6fdb0e5f2b25",
|
||||
"tests/test_debug_ai.py": "7f4b847ba11e8da937eba7be3c4c0ab898b44567f6f553ff842da54c1e7a85c2",
|
||||
"tests/test_mortar_station.py": "6570f18f787b7366ec5341da68dd99acf541cbbc31c6db7a9a3ae967506456ec",
|
||||
"tests/test_scouts.py": "25c6bb1bcc9cb171d12cb1e59b5b278e256a7a4b257b5ce3a1d76d60d459bb59",
|
||||
"tests/test_air_recon.py": "ed8938ac85c2e539bc5cddff339809624bdaecfff63ff4b2ab728d006548dc46",
|
||||
"tests/test_air_support_policy.py": "bedd5437ba0667c371c390cb8c4fb5a3096e8ef6a71c8bac2091264b8d2eebf7",
|
||||
"tests/test_intel_body_inspection.py": "04dd19efafc796f349976d29df77cb71b95615e527ad9add4fceda1f6105fc94",
|
||||
"tests/test_air_logistics_orders.py": "adf7181998f522f8825b71ef10955c9311aba9086e5bb601cfd47599baa46d8a",
|
||||
"tests/test_enemy_awareness.py": "881289417a1e4af219546b113d018e9bc6a402a16cf4bfa7e983ab240f41c2aa",
|
||||
"tests/test_faction_menu.py": "9e6381a4786487962358362b75a2287532a688ab27df756e84801e2bb6dc2e55",
|
||||
"tests/test_hunter_opening.py": "8d791372f465b6242a386d81b8e2136865390cbea5dfdcbfc6bb8b4f717c041d",
|
||||
"tests/test_journal_readability.py": "47764126522e7d7a90100cd9beff741bf49e4d8390111f977919d3e323a5c7df",
|
||||
"tests/test_player_medical.py": "e4b3140a3afc0161db53f261e5480e51f1ca09f85657e25b0efb7dbba3336e3f",
|
||||
"tests/test_gameplay_session_regressions.py": "d9968b06627ce10412e5b1165987de662385d5dcb29090c5626b90fb59df52f2",
|
||||
"tests/test_field_sites.py": "fddb0e44e72fdfe32bb94347a14da64efbd2208e4f252754e80c620fbecda56c",
|
||||
"tests/test_town_garrisons.py": "3674f713d7adc62ec9098f7923991c9f6b1d0edfc1431ccfd82fc8031ddae17f",
|
||||
"tests/test_unconscious_controls.py": "74d4008a5c02ad0087b55030c177c8320b7099c11b97a14d93acf0ad14941356",
|
||||
"tests/test_hq_local_awareness.py": "00c8023f85e88ffc1113353836962c31e8e541a32c9b2f1f66b91eaff5b923af",
|
||||
"tests/test_hunter_combat.py": "240472940515795b205d5caf530392ce416e3e0d2b97e473bb935930f29287d6",
|
||||
"tests/test_enemy_medicine.py": "d13ab1d4ebe81614e00a9a579c6bcc6bd5b2c608187458f414e47f47686d7ad0",
|
||||
"tests/test_infantry_combat.py": "03bc85811c52bd894ab8545794135227fc33b911a51f4e70d89fbeb2673de8ee",
|
||||
"tests/test_hunter_profiles.py": "bdc7898666a7e1078ece35b5dc9bf903d2218843abb24addcea9353fe6b3f7f3",
|
||||
"tests/test_gameplay_review_fixes.py": "5f988d63ea4b2a8a364b181982ddd462baa628ab66e3a35d0fb5ea6f20c50b0b",
|
||||
"tests/test_convoy_column.py": "8c5de7616d4f8c3ed15bcc29bbb57f04dcaaca0626683b81547e2170fc5f9a62",
|
||||
"tests/test_spectator_recovery.py": "8bb59c51df003e24532ad9476af4c8ff3b7f4276dca25e8162b91eb77c7b67c2",
|
||||
"tests/test_server_log_regressions.py": "733084d7d2e33eb96740768c48d9e25bd7f3ffa9081949e38d0776c6822f5748",
|
||||
"tests/test_mortar_load_ack.py": "6eceee33969ec268d904f062bd1ac12ec4269cf87acd235469052b193b048774",
|
||||
"tests/test_body_recovery_lifecycle.py": "b4cc6df60863e12a16ac555ecb9818e318f6325cd989bc97d5bb6ed737857a73",
|
||||
"tests/test_native_infantry_cargo.py": "0d27423c6834503840813327d0d3ba0d675206ca759260ff79cb775adf83e314",
|
||||
"tests/test_native_infantry_setup.py": "8d935cd24ae49ca8a11f9a52fbd73146e567b8f36e0a7acc6565eb3e7d55f1fd",
|
||||
"tests/test_view_distance.py": "ddc6cbeb41485f14a4f2ce23a7a86f1708e7e335bbeecee6309be49fd72e00e7",
|
||||
"tests/test_optional_transport.py": "16c72845dd07f4ade7de361136c04bd264ff75634152e83a19d19a2fdf59bd0e",
|
||||
"tests/test_terrain_adapter.py": "bcc6f469a12399f833651c591b3e1ca9a8e7f49d8b98e223a271fddc245bc4c4",
|
||||
"tests/test_terrain_sites.py": "03ffa5812ae4fa282174f29b5fb3738fdeb261ea26ddbc44b9cd3b3d61c008c1",
|
||||
"tests/test_terrain_airfields.py": "3a6e7151902657a38d8bf0510fb5c1a8049408d4f84d51ca260a0b5d651431e4",
|
||||
"tests/test_vehicle_alarm.py": "1b58d6b35f080003ecab03b23c8da68e0ba2a6a82db4edce89e6031d83f26c82",
|
||||
"tests/test_hq_mounted_binding.py": "40b6af209178cab30b2d6b4420acabf2086532fe0d3f836caaba60e369bdb905",
|
||||
"tests/test_vehicle_alarm_perception.py": "6c8854088c28e2a7b4ee8d38a1f10f66eddfcf9d67afdd460b395d19877b7191",
|
||||
"tests/test_hq_vehicle_seats.py": "8f35fcbd30e51b5576349245a102105926c7df738f3f77abb6ffcd780c6cb62e",
|
||||
"tests/test_native_alarm_hearing.py": "7842886a177aa9fbb6b943b72703c4dafd18d162f26581ce30ce04289e7e9ab5",
|
||||
"tests/test_finite_magazine_reservation.py": "dce435b1dd2d9b1e0ae1f54b5f911ca4207227c4c23586b4f4701c6a6995fc8b",
|
||||
"tests/test_hq_memory.py": "839c7adc63dfab023fafe1547e29caf0ccef52882c5d2fad7b342691b562a41d",
|
||||
"tests/test_supply_budget_admission.py": "3d0e1372f89873470c336038c667df38d2e2e71b3dc2abfddd1215939c448fc5",
|
||||
"tests/test_native_mounted_swap_probe.py": "08674b3c0121756fe94762bd0acd5b6880ba5b234691557851eca5558718e2ea",
|
||||
"tests/test_mounted_initial_stock.py": "cf7d101d8bd31cbdaaa0e7d66f0d8b39aff9b3b70acf51641902c6d0de5be096",
|
||||
"tests/test_spawn_scene.py": "d89ef752906c1cf27c4cc7292997a4d793ddb3b56a6dfbdeff837978350167be",
|
||||
"tests/test_spawn_preload_timeout.py": "db3a3aa42c20f047da90cac6755cb283d15cb3de6a22a57a6e1f352e9b4511dc",
|
||||
"tests/test_hq_uplink_fairness.py": "fc4808a2045522ac6038eef9c37c75ef133bd8af7ffa02c6c1d105b3bfd6c555",
|
||||
"tests/test_hq_pursuit.py": "7ccbf51c7317097d9db6a66cc5be4bec67e542187f0fce5b4f3750bdc4311733",
|
||||
"tests/test_supply_convoys.py": "be4fc6376a77296c6721ce966ea33fd256fe9d76af8705a056a88b32c4f16710",
|
||||
"tests/test_native_mounted_courier_probe.py": "4dadd3157f7da193ce8996b5b08e802f891295ad82a4236366f3018c778c07e7",
|
||||
"tests/test_vehicle_maintenance_stock.py": "e09a6e98f314eef1cf487cbaf8b2185bda950c12329939214ed1ba95713a097a",
|
||||
"tests/test_hq_coverage.py": "d790ae0e5b533f702284e6deeb2c84f7ede5c89bb2b6a68847400e915d50c146",
|
||||
"tests/test_engineer_mine_hq.py": "991666e1218282ce5ffca4ad3f47cf25ec436c6dc091951cc4db395e0cde01a6",
|
||||
"tests/test_intel_discovery_feedback.py": "49b2fedd8704ec67af60a6bb3dd156ddca28eb334d18b20692ab1e4659f439c5",
|
||||
"tests/test_mine_intel_discovery_integration.py": "bac2c8ec269d6e51a46fc17893de4114a5613f37899a1e044a9132d97d44cc5a",
|
||||
"tests/test_hq_delivered_task.py": "076aecdb0ff0d614cadbffedf9d9f8cbb1383fb94a468bd92050b31251bcbce2",
|
||||
"tests/test_hq_assignment_lifecycle.py": "4cfd15d1655b7cfadcbc08104bd01cdfc9960dc88a95ebc5a9958f6f71ce4aea",
|
||||
"tests/test_hq_task_reservations.py": "aa6c5a38618d4bb469c84f18fb7d1748501b4608bd1929cf7e0a6600d248c0f8",
|
||||
"tests/test_terrain_takeover.py": "12365036f81e0874910f100626d2e26b4b2a83042327a927727fda87f05e80db",
|
||||
"tests/test_ai_stinger_admin.py": "d645813857f85854aeca60c9010689662d7cc43f298256d73ae37b05d74e94c1",
|
||||
"tests/test_hq_convoy_dispatch.py": "945a3cba06694608b4880408a13447ebbbf812d400fba3af5b7a57cb006a1f6d",
|
||||
"tests/test_native_maintenance_refuel.py": "15eb8c0ee75778fce2a1caace045940b63cd253f81d16a081f669643b9fefcae",
|
||||
"tests/test_mounted_ammo_pickup.py": "cc4f70870b10beb2595ac4fb030952cc25be1fe1d9506f54dc3901fd1baecda4",
|
||||
"tests/test_mounted_ammo_transfer.py": "cb354bfc71560f430101aae9421f04d601bc2cb0788500771d66ac750df8ae72",
|
||||
"tests/test_mounted_resupply.py": "c17525ffeca6791b4542ea0c7641e4b220b03bce506fc2fda924aac09e8b24ce",
|
||||
"tests/test_hq_mine_sampler.py": "67186d8f6609c3544a9c60f57af876b046618f9b586b2a56520d3a5c8a0e6e22",
|
||||
"tests/test_hq_status_sampler.py": "b8582fb71b7ac77a23158ccd6230e8124ef0432831204e4b8992dee3a9c10062",
|
||||
"tests/test_convoy_mine_stock.py": "e0073271428f00edf86251c9af5530f39094261b05474058df6b794bd958091f",
|
||||
"tests/test_infantry_supply_pool.py": "6fc0053337bbb889021c6eba608796ef946ff4d30a1b01cf678927293218d9d2",
|
||||
"tests/test_automatic_equipment.py": "f8cb478df7979ab9e35c2bcb084e75b2571d41e21e68c8ab28249e01f5708c92",
|
||||
"tests/test_admin_menu.py": "53286ed86862e4b71614cb3ed687aa68893fc024cce203368bf54589ab92703b",
|
||||
"tests/test_admin_providers.py": "4869c86d2cb8c17a383680d594131f4053a051eb4af369657523e20f68311de6",
|
||||
"tests/test_native_mine_stock_runner.py": "51b30d4d7d7543b1674285448d382dcbca55272a0403ea977d2cf08db6a5290c",
|
||||
"tests/test_native_convoy_mine_stock.py": "f069900030cb644ba9e04adb01a6d847a1afa6248a6c458f547aa4fcbd4b5a40",
|
||||
"tests/test_native_mounted_ammo_probe.py": "dd7169d8127fef52a4815fb4ad8227307df557170da6a22723c765bcd74ba340",
|
||||
"tests/test_hq_mounted_ammo_sampler.py": "b1c630909e5227d0f7bd0d69d7927403fcb0f33e7297d5fa52f96001720f8442",
|
||||
"tests/test_native_player_death_fixture.py": "0d0825ebb948a68ff8b8f5cbdcc7e27bdf940e5af1e277ba1780d03e12f2ba33",
|
||||
"tests/test_enemy_loadout.py": "0cdfd28ce4d9c89223a7f439eaec1cad762cfc6c9e1cc4c3213d4600a3501b37",
|
||||
"tests/test_enemy_equipment.py": "bbc753525bdfe05ea9ee7fcf45f3158307ed56428518b08845e097fbcdf299c0",
|
||||
"tests/test_infantry_mine_transfer.py": "55caf2735f2d86aa4cc474ef2d3998f847935e0a0b0d881d5390b2039a055704",
|
||||
"tests/test_infantry_mine_coordinator.py": "2fdb2138685a329cef11557973450bd5189d3d7d657dac5cc51b3df2530fab6b",
|
||||
"tests/test_enemy_radio.py": "698c3ea5e1a3680d5b0438c50a341e53dd09f08d2f1f935e59667bc72ae83765",
|
||||
"tests/test_hq_planner_budget.py": "c9e6b85a3d25267c187f503f903136a16aee382e9d842f61ff88c550b5bb4e51",
|
||||
"tests/test_ground_depot_lifecycle.py": "927a6f15560e177c838322e18ef555ce7db3acde0651d1a43353a2c6e805f3a8",
|
||||
"tests/test_ground_depot_loading.py": "1e44647933a248dc80636de63a6d690efce2bc4c38316c31bb27264682861755",
|
||||
"tests/test_ground_depot_transfer.py": "d468f015f24d4bafbfdac4dabd27acd4282fa84e154f83f46aec96319d54ef36",
|
||||
"tests/test_ground_depot_provenance.py": "a56a0402ee255e2824fc65ec5cc613088013e2795413e484161bab7e28f45c85",
|
||||
"tests/test_native_observer_selector.py": "bafdca52e25cc45d94f2fc306c078e5e59d48f2e2540248acc3822b42668e937",
|
||||
"tests/test_chat_client_ownership.py": "c559dbda1af996455038da9eeb5ffcfc6332da9b93082da8ad3071f5d72b8bdf",
|
||||
"tests/test_mine_intel.py": "db64129001c0010ad11389ff764356893ac7c4fbf45e7c82aa56bbe4c75f4929",
|
||||
"tests/test_objective_map_element.py": "b02e59f977aa81462649282f99e70b0b6320b31ba0ea46f586e9ac0c5d15b884",
|
||||
"tests/test_objective_map_presentation.py": "2418f4c0f370bd436b316e56d5ead97ff4b6aa7cdfb3777c9d2af22486148268",
|
||||
"tests/test_native_objective_map_probe.py": "ef0663aa7d620e06fda63fef578abb397a9dcd8fe5336af5445056e32e19aa28",
|
||||
"tests/test_hint_delivery.py": "6066e2b00e54553ac298a3f9b37060a23851f5ca5d4f98eb25e502b2c44240a6",
|
||||
"tests/test_observer_ownership.py": "8e485c3d2e6ae90df82cbc7829996138db8e9a5a4a42a5e2bcaa3bffa61368de",
|
||||
"tests/test_hq_ammo_reporting.py": "bdd4a30440501a2861aca80c951098c48cf999023eaaabd9a2eef82174f8173d",
|
||||
"tests/test_hq_ammo_sampler.py": "e9c2d147eb1547be471df7459f1be815cdc9ef0a64c9a4ae4ef58936424dbc55",
|
||||
"tests/test_hq_multiconvoy_supply.py": "e58d1d6eba48b2c5c6073d54c76302b2a7250ad22176fa94c386e1bc2ce65588",
|
||||
"tests/test_hq_watch.py": "51d5a728b0be83ff957c0df61289d14f90aba109b49365e457c9b200d5ede36a",
|
||||
"tests/test_infantry_ammo_transfer.py": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"tests/test_infantry_resupply_coordinator.py": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"tests/test_infantry_resupply_planning.py": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"tests/test_mounted_supply_integration.py": "f52acf7a16c9d5273894eb5a4afe7657a7c97de2ed72ba06671d25e163eea5d7",
|
||||
"tests/test_hq_mounted_intercept.py": "444411a6a97ebaff69a056302f444f986daa5f6f7f792e622fdbcca731f939c8",
|
||||
"tests/test_hq_mounted_dispatch.py": "3eb793719b21d508ffc294f5a1bf5c5153f5717a1408a8f779f0a4c1ddefe2a6",
|
||||
"tests/test_terrain_presentation.py": "05f070c5730a9f7f0aae9487a313342785a42682c9beebc3b10cac270b514f18",
|
||||
"tests/test_terrain_selection.py": "80bd8eec34f58ca139efa298509f0fa9dc01b7d35e02d2d62cb593b131c19211",
|
||||
"tests/test_native_mounted_intercept.py": "24810c0a22b221604e1fd8e6596f2d409e558699c5070fef7aae1f74a4fc2f5d",
|
||||
"tests/test_server_item_catalog.py": "c5aae32a55552095e49d9e7884ef88e1cdb4bdb257f850af67d387793c327e74",
|
||||
"tests/test_item_preferences.py": "1c52bec3aeb47b224adb3ee4385b68d4ec00214bc9f5e08fffb932af07f785b0",
|
||||
"tests/test_mortar_transactions.py": "5db4ec737355a7ae995240dc93f1dce146e07c0110c2da2c23451f180b134d26",
|
||||
"tests/test_native_convoy_probe.py": "c81046b5b3f7734f2f53dead61b01a3d81c96e841b7f9a4478c05702b29bde07",
|
||||
"tests/test_convoy_lifecycle.py": "fc18679882f1666a38587d151aa368241c5af115f3a8269dca81eb2617eb8afc",
|
||||
"tests/test_hunter_lifecycle.py": "4d228ec10c3d5f02ecf0eb755ca2773e3496a2c25a1e1c355e6ec79ee2ef53b6",
|
||||
"tests/test_convoy_survivors.py": "415cf9f5d23cce363e483d4bfd0292b58ab1fb3d9e727f9581271aa65c1c3109",
|
||||
"tests/test_hunter_capture.py": "d88b3a830c350e27a08fe5977cf85247dff140b3dc9135062eb5e7774b400790",
|
||||
"tests/test_hq_mounted_intercept_pair.py": "a8d758b1ff20bb6d1a95a9ff1d38f687e43c819c279f5ea9692e84f766dc4fb9",
|
||||
"tests/test_convoy_intercept_pair.py": "52b55727b7c2441d43530efa701045b9439b9175c71fbd2ae7577f851d2c98ec",
|
||||
"tests/test_native_supply_travel.py": "045c055e96ba5a19bb79406fa1ae29ca2afac6ed0770801b5623d692087e01de",
|
||||
"tests/test_native_supply_travel_runner.py": "4c7e1eb4de6bec932f7462a68f4597908c4c53a279521499ff28e64ed8053e3a",
|
||||
"tests/test_native_supply_travel_hook.py": "d92f80c44d5a3095ac16d539569d99d951e5bd865e904c65e91d5d6682bc0af9",
|
||||
"tests/test_engineer_mine_site.py": "b174162dc0621c46835b050d7df1ab9540e2f8f3b1ee805aeba8bb6d4f956a90",
|
||||
"tests/test_native_random_radius_trace.py": "a87f553de26a32b5f242c2cc8ea31564eb54d29f1d0cab7018c1c408888b8101",
|
||||
"tests/test_native_random_radius_runner.py": "aa75c700906d55b098731715503ce52725a944d47b7195fcd47d222756345c75",
|
||||
"tests/test_engineer_mine.py": "300023f165be86f681d3980e844823c73e37b98c5855a2142d9d373fdce3e9ab",
|
||||
"tests/test_engineer_mine_posts.py": "6185b5ab6576948fd8b47bb945fbe40107ec6944eafde2d04dd60ff49d5ec89c",
|
||||
"tests/test_ground_depot_mine_claim.py": "dfe117f58cdf420974fc0d821b1a4153c9fd4da7585fb3e6b872a418d22d2083",
|
||||
"tests/native/inventory_control/README.md": "29f7086ee223b1cfe657932c7f236a1640876503f69f6f401451c72a5452695d",
|
||||
"tests/native/inventory_control/addon.gproj": "18dd7db85574119fac5057091c4d9991b247855f67f06bb86cf440f429b5911f",
|
||||
"tests/native/inventory_control/Prefabs/ERRIC_InventoryMode.et.meta": "6b4f66f296d15e7e5f82928cf1bdfa58f085421ae9b6f24afc5ac922d2a8781e",
|
||||
"tests/native/inventory_control/Prefabs/ERRIC_InventoryMode.et": "98408ab80347058f5b79b1103b849b19beaeb97a9ff81662b59fe6100ddd6bf8",
|
||||
"tests/native/inventory_control/Worlds/ERRIC_Inventory.ent.meta": "ca0420504016fa2aa7220712d13b7bf7748832d8d58b085afc4373f4abeb1339",
|
||||
"tests/native/inventory_control/Worlds/ERRIC_Inventory.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"tests/native/inventory_control/Scripts/Game/ERRIC/ERRIC_InventoryControl.c": "8707f35ecf48813bc4e72c599fe2527c44807493496218d18e89aa8739eb59f9",
|
||||
"tests/native/inventory_control/Scripts/WorkbenchGame/ERRIC/ERRIC_InventoryControlPlugin.c": "000d8fa3aa6412a5adb1561333f840f27185dc42fa61569c311b0607df0f2420",
|
||||
"tests/native/inventory_control/Worlds/ERRIC_Inventory_Layers/default.layer": "80a5f0b6c1bc8761469ea69978967dffc070ba9f98c5125430a78a506684c39e",
|
||||
"tools/native_command.py": "883c5955018e43c9451e3e6cb56e9cc8491c77920be3264478612a82c248cbbe",
|
||||
"tools/release_check.py": "65df1bff33638a583905ba5f6c583a095b9f7e38186b6f29d70b72a61525589e",
|
||||
"tools/reference_guard.py": "545b67111927d73bf2020f291528ea6f2f687a994b3e37bf567f239c32c8cd78",
|
||||
"tools/native_report.py": "bb75ef5fe551f45776d441f15a49ccad4daf19abca505187f9b2d30102538658",
|
||||
"tools/archive_native.py": "445736e18e645f1d6fac0aaf837627e94179d295c21a6a67a8e84b5b468758f9",
|
||||
"tools/compare_performance.py": "568acfee2525b8924f3e7a39784e8641f76d63bb3703dcce8251ab9ac9bb1854",
|
||||
"tools/source_manifest.py": "c1a985348bad16f3b5b69ef7e545b6341eca298d8ae08111b8340b31535cc199",
|
||||
"tools/native_provenance.py": "d4777f1f6ffed6993f7009ee2af41b100e8e0138d60ebfdcc5404ff2128f8e2a",
|
||||
"tools/dedicated_preflight.py": "ee56e05a15ada3bda80fecd74a024d141dcc3df00416821ac2c1a29ff308123f",
|
||||
"tools/dedicated_native.py": "35e0c1402be1d54f1b4345de8ac4fa7fc73f8cdfd09c7cc6f832a39dfb33e621",
|
||||
"tools/source_bundle.py": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"tools/native_package.py": "32195bf9b43024028e9931a99885d0a131b28ba1b77b32e9d6ed70b914625559",
|
||||
"tools/pak_inventory.py": "95b0b64ab1f89a2142385ca596016fa131b49d933e31aef42d9bf18e2ec01383",
|
||||
"tools/archive_packed.py": "99cec180db72dc93c1ea8256bc316d42c23ab02843d5331a9d228b1a06a71d57",
|
||||
"tools/parse_native_stats.py": "32aa0935d63e59ace29fcdb1a02eaa850898b21ee4cce011a21d364e3dd69c75",
|
||||
"tools/headless_display_probe.py": "4ec3851835474eb4d8b84fc74c20d08567d92906ce832643d911f1d062abf0bd",
|
||||
"tools/private_prefix_cleanup.py": "336889ddfbfe8032eef584d8e9e222d85e33a039441f8fe9c4904e1db8ee10e9",
|
||||
"tools/headless_input_proof.py": "1952fb2ba577b80420133b9698b6d718d25211c86f853de8d22e0acb15f9f9c3",
|
||||
"tools/headless_inventory_control.py": "194121b64ee39c31cc25935afea8ee9dddbce04cbf26aaf058e25d02ee9828fe",
|
||||
"tools/ordinary_look_evidence.py": "3b6a0415352295e15e988ff78659e81981001e1ee03430a5b4c2df1518dd9a31",
|
||||
"tools/ordinary_gate_evidence.py": "5f02596c92b945b28081d861e466f01897875489e673bf0feafa6e4ebdae1708",
|
||||
"tools/prison_approach_proof.py": "fcd2936fa5a67ba6a970c56e8e4d04cc76bff6ffc6087ac95085716fb5fa673f",
|
||||
"tools/prison_approach_evidence.py": "12f1618b16f845d987ba928c8d95f2d448bc6a600fb76f8870b2ae8fd4a660cb",
|
||||
"tools/prison_alignment_proof.py": "37bd011642ca96dd0279e90cce785fc689002011b3977055f15c0dfad4161bed",
|
||||
"tools/prison_alignment_evidence.py": "67d5675c13b2de75110c53b99d1bd88e0eb0c36673488312711b03fec32e4235",
|
||||
"tools/ordinary_gate_choices.py": "59a0055d44f2f5b27c530406e5cbd46847357285d2d260d08e5c34cc53b7a795",
|
||||
"tools/prison_action_selection_proof.py": "00d397bf9b13405a2612678ec866f09d452acb4079f2072eb97c79a7fdf650da",
|
||||
"tools/prison_action_selection_evidence.py": "668b1d6ff86903ddeb702fd0c49d8d8110cd58559062d6d650f2962e4e321ab6",
|
||||
"tools/prison_held_action_proof.py": "450f03c6dbb4960d9f15a0f9c43ae5a18ab00594181e23321a2eea9b59ed47fd",
|
||||
"tools/prison_held_action_evidence.py": "971a630d663291d50c407dbadf6005e17ea035db88b5358e5ec1f6b24e6824fb",
|
||||
"tools/project_schema.py": "cc1527c5f68fb75711208f293f4751c206fedc725934d9db7d4b7fe539f60cec",
|
||||
"tools/external_addons.py": "c389b76c4d5f0f763420cd7d564d3ff5ebb7350cac10d2a26164c17f59b72dde",
|
||||
"tools/headless_game.py": "e7cab472ee51497343174cb460022b3e4591f148d4acbc6e6f881fc68c0fda1b",
|
||||
"tools/packed_external.py": "46203c078a82e825ec2e82c2495e6e165aa7ddc92368d2fe7786d87b957d3096",
|
||||
"tools/import_settings.py": "8b41ea8fb45e5c3840dad67f9d2494cba5dfa1e0e67d41e334fdd04e515a68a1",
|
||||
"tools/prefab_identity.py": "26088826275e84dcac2dbac771faf0552545791d30e9110df1ce88ee0d5a81ad",
|
||||
"tools/terrain_adapter.py": "d5ca50a5dc3ab4ba8b7d8cf2c72a9c3579b6567efbad5572acab991267116417",
|
||||
"tools/check.py": "6c1b5b24e759f7855058c9d82956f9ca0107a5311fdf9f7217129a86ecb62f5e",
|
||||
"tools/headless_workbench.py": "aa971eb48206042315aa7632625d04d44ec9db82ea568a071b977118cb63361f",
|
||||
"tools/desktop/kwin-right-monitor.js": "ff2b6f7b9d1b1eb9f92b61b39df18f1ddc44be5540e18b1fc1829eb2fc1fb1a2",
|
||||
"terrain-profiles/nogova.json": "4456c27cd7a4b2fef329051beedf3ccd683c94a684580bb07a35f16a9c59e743",
|
||||
"terrain-adapters/nogova/addon.gproj": "08442b784c8ead8362c19f084a9812e70783069da7740cbff7eef21f9a07e084",
|
||||
"terrain-adapters/nogova/terrain-adapter.json": "f2bdbb3ee3e03300f03d8ab184dd59f1b016c2eacb70b8873ab6fe5dbf1137d3",
|
||||
"terrain-adapters/nogova/resourceDatabase.rdb": "b12cdbacbd4fed63f460a19697b2ae8d1cbde7f9e725b73264ba3acd3584b2dc",
|
||||
"terrain-adapters/nogova/Worlds/ERR_nogova.ent": "6a2d45449ceedd13632a53c2ad612d155d3fc76b029febff7e3a5350d66952a2",
|
||||
"terrain-adapters/nogova/Worlds/ERR_nogova.ent.meta": "d6c41b4e1251829bbbb079a699a94a318b1a94e9eeade6e3fd4a019e0967c118",
|
||||
"terrain-adapters/nogova/Missions/ERR_nogova.conf": "60d542d81e48c15c838fe267e43e75273c7ec805d3a6031162dbb26fdab62889",
|
||||
"terrain-adapters/nogova/Missions/ERR_nogova.conf.meta": "cb6b7feabed57784ff41ac6d82f37df05f0e831b3f87bd18b1612332c61e21c5",
|
||||
"terrain-adapters/nogova/Worlds/ERR_nogova_Layers/default.layer": "2e9f780b1c2cacf5e34de4eaa7aa5010c0b4c81232e54246f8f466b32f909f5e",
|
||||
"terrain-integrations/nogova/terrain-adapter.json": "c6cb3d243ba68946add810256501322026e757027ff7e83cda40a02471dfb1a1",
|
||||
"terrain-integrations/nogova/Worlds/ERR_nogova.ent": "6a2d45449ceedd13632a53c2ad612d155d3fc76b029febff7e3a5350d66952a2",
|
||||
"terrain-integrations/nogova/Worlds/ERR_nogova.ent.meta": "d6c41b4e1251829bbbb079a699a94a318b1a94e9eeade6e3fd4a019e0967c118",
|
||||
"terrain-integrations/nogova/Missions/ERR_nogova.conf": "60d542d81e48c15c838fe267e43e75273c7ec805d3a6031162dbb26fdab62889",
|
||||
"terrain-integrations/nogova/Missions/ERR_nogova.conf.meta": "cb6b7feabed57784ff41ac6d82f37df05f0e831b3f87bd18b1612332c61e21c5",
|
||||
"terrain-integrations/nogova/Worlds/ERR_nogova_Layers/default.layer": "2e9f780b1c2cacf5e34de4eaa7aa5010c0b4c81232e54246f8f466b32f909f5e",
|
||||
"docs/addons.json": "ccda7c1aa6bf60524cd983ff863e178270445ef193e7418967b11cc49eb366d4",
|
||||
"docs/migration-provenance.json": "e671a9ec4dd69097a7a7f974c8a1ab0985b8070724847cfafe2ede0af88e7bee",
|
||||
"docs/dependency-audit.json": "d5e6cbcdc59c0a25e5748c590d6a195da9c97e8296119e07185f4c360bdfc4ae",
|
||||
"docs/architecture.md": "4dc8f223a793b36c92c5a70de9d2114d0e70fe36ddef873dbaef96ffa0bfc8eb",
|
||||
"docs/migration.md": "04387d3dad83ebdba4e4076fcc8ddc903a16836a3d0bf79d504d9006e6e7a17d",
|
||||
"docs/runtime-testing.md": "82a255aeb0c4cafa34b9fce9839147739c72e2e163dad18658c01cc0ee199faa",
|
||||
"docs/validation.md": "2810c18d2445c27c50f94ef92a781f9281cb3bd88ab9235834194abce3266262",
|
||||
"docs/acceptance.json": "b58e56be792c7ac2cb792a70e0b560989e59b1607fe9533f6f852e2171df9408",
|
||||
"docs/native-initial-snapshot.json": "94ca2c1fcb003823b7edc719d923df1d2387543f975fbca7ad1fb5ad3628889e",
|
||||
"docs/native-followup-snapshot.json": "156e5de03b28b0cb717e2d832afbc6dd9bfa966c28d2f9b9416415e7643ecfc3",
|
||||
"docs/original-resource-inventory.json": "bc52a981c42f933134e637a027d08a0924abb19784782731590b7ef0b0e2e73f",
|
||||
"docs/base-replacement.md": "b8af82e651366198a93824b7569430faed4f0e04018a5438a92942b98bfece25",
|
||||
"docs/site-authoring.md": "7a2e66e75ca3fdab43bd730f16e864c31909ab42fe060b00715caa13b8352ce7",
|
||||
"docs/original-feature-coverage.json": "fec7f3fa341b40db09b1d7c9d96907929210b2474048127c4415de0de27f4383",
|
||||
"docs/original-feature-coverage.md": "fa4a79d7dc98a92433fb9157ca9f054b5cedaec333069296deca7a70c4a8047b",
|
||||
"docs/configuration.md": "c89d23793e2cf8d8a9611efcc7dd584a80b568b30d9919ae8f9c6a96a6077069",
|
||||
"docs/extraction.md": "215c96cbc004b3817a70ee40f30b181a72e78123e69e16a3585ed4d8d566837d",
|
||||
"docs/mission-time.md": "29d9a18c7acef0587764becbd04c2c63684644a05c7b3b2fe77defe1881ae7a0",
|
||||
"docs/native-errors.md": "f0cbc674803f5254db0c823bce2df437cad121756e19f6c658087d5d2fddb349",
|
||||
"docs/ground-transport.md": "febce039866e290f1cdadf53ae2f6422387b1a4778264649c04727ee954c2ab6",
|
||||
"docs/radio-defence.md": "82c9c30ac75688b17fd7a5bc52e3e0b9843f2711442d4b8e5274687382c8bf06",
|
||||
"docs/performance-comparison.md": "063d46961611efb49478e462f44443b45eafa28b8ff3ca08f799b1652ba1a91f",
|
||||
"docs/release-qualification.md": "7bdf42f51fe3a4c1d6187d0e6f5248ac9a68ce16873281909bd96e1cea6c406b",
|
||||
"docs/player-lifecycle.md": "35fd066a50ddb2bcc78d4a448811e0763263cb0605161ccf43713b5e4a5f9cf0",
|
||||
"docs/base-gameplay-gaps.md": "8fb9ce4bf3d36507fdcd03af9681657c473bdf1f1d188380e7e4a83d47b10625",
|
||||
"docs/objective-widget-lifecycle.md": "3ec0ee8c74b2a3117356477a16125a077dfbf010050e53280a00769b710958a0",
|
||||
"docs/prisoner-loadout.md": "0b27f5fce4af457bea7133e461dbc37d8fa73fe126c8c3de90d723b358af389a",
|
||||
"docs/native-medical-fixture.md": "3c915a74afbcac1dfa45f0c1e9d8d4801f33704cac9ce1b66355121805ecfbb1",
|
||||
"docs/recovery.md": "026b513982530b8d65a6a1459e8707cd4abaf56450abc00f8449cf01fc660d0d",
|
||||
"docs/admin-discovery-setting.md": "a140f09cd1f27635824a9fa27e88e99259fc0030ff3228dd1376e2e949edbc1c",
|
||||
"docs/environment.md": "2a58f8a969348e42e09e45b906a3d61fb65d887ae2814547605a01987747ab6c",
|
||||
"docs/faction-catalog-source-hashes.json": "46060bf2bfe6c39517e3140acb004f9b129c26695a7ee890b4aae571b3f0da76",
|
||||
"docs/mission-faction-catalogs.md": "2ce3e49404d103a4c372ab0386de3bcf831bee87d95b1092372345a3d32ef8d2",
|
||||
"docs/medical-kit-teardown-ownership.md": "9f5c6636bfef46802800a4cfce27833fd1251067be892d95f4ce4f07469fef1a",
|
||||
"docs/site-patrols.md": "5956f70a5ebea4167819a43c2a15f8b6d6460bc724b000f989d5ad5265d48d56",
|
||||
"docs/environment-restart-fixture.md": "1c1bd3872a67c5a59c12c1293d075d52fe0b563fcd5e9e10a1ce1850c7efcea9",
|
||||
"docs/inventory-identity.md": "02092960cf937b175c5a190b426b84e0383104fa71f324c8b3a0ceb4fbe01164",
|
||||
"docs/radio-document-loss.md": "64e6dbc3a62ffd164321f7b3c1a80de05a74c26b1541bb67f6fd3513983d5fdb",
|
||||
"docs/ordinary-game-startup.md": "e979300482ad716c7a8cee532dbe3ca73b7d265b9e94fe02bd3729359551c7b2",
|
||||
"docs/guard-source-hashes.json": "874845def1458901d61adeb090a464bbee7c7b18816406ae3780ff48fe855266",
|
||||
"docs/initial-guard-readiness.md": "5f2b45f3744f1f0316f198225a34e25d93eb4795bb05d6cfded8de1f1a116c18",
|
||||
"docs/casualty-loading.md": "cddb8b1aece65dd0e3366a493e22ece02f49b1ae5d626cb9931a188551f007a4",
|
||||
"docs/native-guard-cancellation.md": "880b545b8451a86f16ef47e0a378d081c8fecb1175bf9a8a122bf853ff9b816c",
|
||||
"docs/casualty-ground-support.md": "9ffa8df2c88e51d77c29d12a23df8032d8858b0c82ff079d476f773cb6b5825e",
|
||||
"docs/casualty-ground-source-sha256.json": "90ffa7d0c61e3823922ca9d4773e3d12fd5e9a1760a35c3b29fd12a53642f83a",
|
||||
"docs/guard-cancellation-fix.md": "41f8bd169de714df4df4a61189d47a37f9be2f1b1554edc99c29d8a1fa4aaf19",
|
||||
"docs/guard-cancellation-source-hashes.json": "a1bf169c021931cdcba835d52e420df44e5dd2ef351257f0be10f63c8727afd4",
|
||||
"docs/radio-feedback.md": "3aaaecb318e2f737321bd08f9deb9323af153f2ae9ed196b55104c0616dd2be8",
|
||||
"docs/current-status.md": "93f4327f10c9a5ed688782b009e345ed8afa31a532852ee9a0c0944d5df94344",
|
||||
"docs/initial-extraction-placement.md": "643b50d231dd9ceb49b81fd8f061cd114a9618fd1ad5a6f88724c0199a5a304c",
|
||||
"docs/initial-extraction-placement-source-sha256.json": "a44a32cedc54a70f635bf5840e7b29d35850a2212fcf64b1fd36ca096f10fffa",
|
||||
"docs/native-casualty-remove.md": "a91a9a638b19d4e8759a7168e196bf1a50bbfb328e7812d88e329166c06e69db",
|
||||
"docs/casualty-remove-source-sha256.json": "4799a5843315fe5b5b2e933e8068a8b4bae6d924a49438eccb7f68ffc8e12be9",
|
||||
"docs/ordinary-launch-callback-fix.md": "b74b8d0d011f25c367ea07b37e1a5ef488a2b378542ddca63ff9e981e649b874",
|
||||
"docs/casualty-incapacitation.md": "2811fa294de0348fbdf8e78b0c66bc31a59dd8f1e43fe16af8da87cb7e789820",
|
||||
"docs/ordinary-diagnostic-splash.md": "6e07a87a03df81dd5c9d6c0f9602b26e08ec7fd7cf941b91f2b8007bd9d33e6a",
|
||||
"docs/ordinary-splash-source-hashes.json": "b2e277e3487c2b790bce741527555bb74f6b9820b9e5626950ab709533d9fa97",
|
||||
"docs/ordinary-identity-diagnostics.md": "62c34ac6c10331025792d1785272a1605e655ca3bcbcec9ffb4852968925251e",
|
||||
"docs/native-mortar-firing.md": "0a340bb6f074531633e8b1b1189082346f4149db7f8484c08f16207767994be9",
|
||||
"docs/finite-mortar-operations.md": "d277ae850de9c33b410343b1dd498fecbe9f5c87f7c4b74829f07ca894603224",
|
||||
"docs/mortar-transactions-source-sha256.json": "dabad1cbc6eb3dd6f66b3e9ece574edcabff94adceeb2494b1adb2147608dbc0",
|
||||
"docs/local-singleplayer-admission.md": "f7fec9a8ab119d006818b518684315e28c96c7f63a1d075922a5c8af2864a5ae",
|
||||
"docs/dedicated-preparation.md": "7462af696bdb65d32e764cd98a354c9059772252bfa22d3c8aff23bd2e636c67",
|
||||
"docs/mortar-aim-renewal.md": "c26041505ea6af56146dfc9f52aa2b0cc3955ded565fdcb76892a83d1fe2e56d",
|
||||
"docs/mortar-aim-renewal-sources.json": "ceb9162fc1a4fdabf44ce7aeeda5f6d91bfbab6c6d1eb1666ce4661f1a540513",
|
||||
"docs/native-mortar-transfer.md": "7d5086b8268c213375d56ed2dc3994daf7065b2076742d0af588c8ffce5f753c",
|
||||
"docs/dedicated-native-diagnostic.md": "37d3ccf17776f5c2c2f2c8bdb87165451cc4c14eef4173162b89378f67693cd6",
|
||||
"docs/native-local-admission-probe.md": "c2794b2475d94f2756921d98f676aa8224f6fa3bc95bb14ce45c2bb7648e1566",
|
||||
"docs/dedicated-resource-audit.md": "92dbd16d7cd1b018abc5e5bd0c12bf0859f5c7af8194477eaab835e2f3fe4256",
|
||||
"docs/mortar-report-deduplication.md": "cdeeee20885c947e10507b30a2dd19b086f7aa863730c266b574cc756d466bcb",
|
||||
"docs/native-powered-flight.md": "049186db16d1b18f5d51e6eaee3e5e4c9efad9e578774501f14288781b82b972",
|
||||
"docs/mortar-expiry-evidence.md": "fb980772ef0a04568ab98457b889d6af4f3ec216382b1452e6d66eb1165345ef",
|
||||
"docs/discovery-map-usability.md": "b70b210884b642db9e28c4eefb4bde4449858089c2d8b47c3dd3209d9ba2296a",
|
||||
"docs/native-hq-response-proof.md": "9d3e43088e4874a1f6d2edc853bc2f9dfdddbfd9df3c54802dbf499a74f9910c",
|
||||
"docs/prison-breach-progression.md": "31797bfa36556cb744390ec0c7c8d7a404fe91f18a2c20ec1c0e4f122648e184",
|
||||
"docs/powered-flight-pad-survey.md": "0347bf1cfa94855ee26f22c4fa10339baa566ea10d0dee86f9190ac8a33383d2",
|
||||
"docs/item-station-teardown.md": "7a2eb028f767ec52214f375f79ed162f9ee7432a08f4229afdebe90ed338e37e",
|
||||
"docs/development-source-bundle.md": "7cd8dbc04a9cfe87ff7479283477e788552484ea1b83ffdee4893620f1df31ec",
|
||||
"docs/native-flight-footprint.md": "ef178fb48a0fce61d4eb6fa1f5533e0107f9ee6b24a26655fe17ba7449f4c776",
|
||||
"docs/native-flight-input-diagnostics.md": "4dffc58b20b2e05f3fc3d700f3feec79cad2ceacbd5fcaf9bdaabf6574de23d3",
|
||||
"docs/finite-mortar-courier.md": "96306ab4f0313b9b403f7a37b9007bf83b237de433e0cbdf1b1de361d0b2e738",
|
||||
"docs/finite-mortar-courier-source-evidence.json": "970ed87a005fe31382ffda5da77b3f18c944a57d6d1477bf9289403b39d75054",
|
||||
"docs/progression-identity.md": "be443ecba1d0c7f104dae20886c1622286f768d182d69907d4859429fd07fc84",
|
||||
"docs/vanilla-game-startup-control.md": "ff0f24a4921dd3d7c52e2895c1905e107e28824d628924125ba7e6b6b97a3ab6",
|
||||
"docs/normal-splash-audit.md": "f377cfa81ccd49c49f5f63a9d15194b063aea3554afddb934ad3679707ff6874",
|
||||
"docs/native-packaging.md": "6f83aa58d8692f0d84bb8384d3fcf812f8f1f3ef899b20aff839db0a4e2e91e8",
|
||||
"docs/spectator-guidance.md": "ad805edd230933a80950f8702b1a65a177a4f80d525f8c38d96bb74a89f38dad",
|
||||
"docs/native-mortar-salvo.md": "4358b187a9e2f518259535ce23a2f601b2242982ef0d2ad6cbe4528d1edd9819",
|
||||
"docs/pak-inventory.md": "b50157dc0dc5e4630a1626c94abc0037e8fa5db6a0973a06f3f815100b141a18",
|
||||
"docs/packed-core-startup.md": "4c9e8c6d47bb1a0ce6146070ddf4a40e1e7ad0dc710ea60f03a45b2641a85040",
|
||||
"docs/mortar-report-refresh.md": "80d7709a20930e78d138cdf792de9ead5368040ef03a94975c0222d182a6dfac",
|
||||
"docs/native-packaging-control.md": "5e1df445af29ff9d161e2a385ca90cecf283f668ee3806fc0207b55c8774cb1f",
|
||||
"docs/packed-evidence.md": "cf67a65201cc34c7316e3b677c29f301f757a81ebdb0eff83e4f705739c8a691",
|
||||
"docs/native-companion-packaging.md": "e9fc608d900c3849958eb6224f46f5619a5cd5c2e78d47536a5e3bb8d3edc31f",
|
||||
"docs/mortar-activity-completion.md": "388756d09696d1b2bf5277a945a57edd07b792b40be8ebadb709fa8d2f62ea86",
|
||||
"docs/shared-map-ownership.md": "43d8134ce6d1e6f6561634a5b18053f6295f7d7d5a575b4831995ca254f283db",
|
||||
"docs/intel-registration.md": "0568ca6f283532d2ebfc28bbcb11202b72a7ed5ac011ea66ed772272e5e87e70",
|
||||
"docs/native-shared-map-ownership.md": "c3119a4742ec35f914de6f25751316fcbfdd794dd8b395285b8b22a5fb1ecb9c",
|
||||
"docs/native-powered-translation.md": "b1efa32020ca713fe95f20a714853a67bb5b64a09781ba5d1d7cadefd06b7a93",
|
||||
"docs/aircraft-flight-controller.md": "3df786d7ce4ec6d6b52804b2a2ca86a9980fdfd203aac7eadb204458b54d88b3",
|
||||
"docs/prison-yard-surface.md": "4e881eb8eababe03c4bcb86e46fab7bca47ddd1d3ed4cd570e2bdb2e0ceadd41",
|
||||
"docs/native-aircraft-control.md": "eed101ab213e180822fc6967264efefaa75c99ee97f433fc019da45d47e33cba",
|
||||
"docs/native-server-statistics.md": "c5256d62bc6632788057df57fe5daa1fe738904bf1042e0e1bb7785aae66f4b6",
|
||||
"docs/native-end-lifecycle.md": "84bacfc43eb6011b565ca1da1db325d96098be1d4434d24b3c8a3736a0098924",
|
||||
"docs/hint-delivery.md": "35c5d8a2d1e9eda99c2f82315171fd95ca0faabdf7c1b342a45fca7db6e22755",
|
||||
"docs/preparation-status.md": "bca0997a65e5f85076d6c516be22130e5207371f8b06e74a88a140e2f1bfc837",
|
||||
"docs/headless-display-probe.md": "08a5627abe39206610d0641323947367e6631e1f87e4826789f56eae2e6b8719",
|
||||
"docs/aircraft-route.md": "c23d28a742546cc774df045c3668406b77c573bb4183aa3eef333dc6b26821f7",
|
||||
"docs/ordinary-input-observer.md": "a068702b345fd9645367606a766d57912fb5d7c6dbf615d4ba5b731b4b817d90",
|
||||
"docs/headless-input-proof.md": "da0053ff71264178de63417b28a5e2fd53d641d0188b83e5bb7c75a95773a408",
|
||||
"docs/inventory-slot-diagnosis.md": "d661908156717cd8f3545a721374a6d82c3755859267f951cd3a7625e891bd80",
|
||||
"docs/inventory-layout.md": "f22bf592a0f560ac3db2de5526d8937f899af28006b873ada4d42acd7920f088",
|
||||
"docs/prison-input-proof-plan.md": "5003c8cc190ebf9bb3c0e6b53138480b91c38c4bea2d063e01b55dc934ce7cfd",
|
||||
"docs/ordinary-look-observer.md": "20a17b23bd1c057f2c6af96d24078362c132689e87ea41d331a44f0dde54345f",
|
||||
"docs/prison-approach-design.md": "2cc363678200287d9bc13a25f5b3f8fdd749d266b1734640079cd11c29e97084",
|
||||
"docs/ordinary-gate-observer.md": "75c2ad994dbdcd8cfed1c29c83d6a73de677edc98700327e36868ae8169731c1",
|
||||
"docs/private-pointer-edge-audit.md": "29eef2bbb8ff932523f0ff501a6b3609c171224544a6b7e02461aa1f519a8cc0",
|
||||
"docs/prison-lock-alignment-plan.md": "c857bb12700a5a6be0b63735d38efe6a9c03062ab10a450bac09fed66192434b",
|
||||
"docs/prison-held-action-design.md": "89af762f9d33e8a0cc4f461ff6cf0b55036df84a05ca26fda8292d9d9a7647d7",
|
||||
"docs/prison-action-selection-design.md": "9505c865248904c21a8096a53a18baaf11799a615968c6047dcc1ab2773637b1",
|
||||
"docs/prison-approach-reliability.md": "2d6e1e243788beb27cdb6bfe1afa5a15384931625ccc075f8ebd25e9f5135596",
|
||||
"docs/native-packaging-next-audit.md": "9746148ebc0ccb5c49ccbe7aa55ed6f8a509b95ba39c83bcaca706ff88e4a454",
|
||||
"docs/aircraft-service.md": "601bd40cdce1de39cbef3cff373b17cb77371493370bf57fa20de937c50c7b1f",
|
||||
"docs/aircraft-hq-integration-plan.md": "c6d2e5dfea4379c0b2b57cc028b7555f62d47661eb9afbf6611a3dd509179238",
|
||||
"docs/aircraft-field-route-plan.md": "a44e8f670363b85543d19fb508adc6840fc9f02b3cdd80737d36872ed6e3732c",
|
||||
"docs/prison-held-action.md": "3d1360d19d73d13189b4351e2c2fdb50da1e97a393f9f17191d4531921f09d7c",
|
||||
"docs/playtest-build.md": "d894ff9d73487775828b942daf9d915ce5596af664b85077e8cbd65e7e7ee892",
|
||||
"docs/owned-ai-intel-migration.md": "be048099213bbf2daca4d38a9126f2f4d68e267894163f2ac641209a92f2c7e2",
|
||||
"docs/chat-integration.md": "28a94422f4339ef47a549540518c14afc419add48bd25b9aa98cdb9e3297e181",
|
||||
"docs/external-addons.json": "c340fe315efa9bad37ec9f249a259f51b833e66ea6f38bd774f1573753216ece",
|
||||
"docs/external-addons.md": "8deff9567694245390cccd8a22176c6d7791ab56686d93ee732841f111f6d3b8",
|
||||
"docs/ai-equipment-migration.md": "819ed66d7f68a83ca979ec0d78dc8dc8b9538e44317d5c5e70904a15cf488be6",
|
||||
"docs/convoy-bmp-seat-audit.json": "54811861f71c320c026b4d870cc4773a1afd16f9d7b894d709fff99db7959b21",
|
||||
"docs/ai-feature-migration.md": "3f5d301e48d9dac57be8ea0bb1e67a897c90462a9289d9227f02e58bb9648f07",
|
||||
"docs/ai-feature-migration.json": "68dfb0b523b650fc82648953d3ed390dc68617d0ed9cc5bce86145b3e7b99eea",
|
||||
"docs/convoy-migration.md": "1cf205d1ea3579a8300f75fb31b260f73f3267269c67925196d13ee548e1e461",
|
||||
"docs/hq-ammunition.md": "4e9e78855e33d6381ebf89a5586062d264d5a2c6a862faa7f9b58f1f1e10480f",
|
||||
"docs/ai-migration-progress.md": "3af61e888d2de139fac21b9dc9163ecd8b83bebd29921906559687d938dc0986",
|
||||
"docs/vehicle-security.md": "3ba235ec441d4215925b275a7a4f261d8851285deb7d0e4474958d3a78501193",
|
||||
"docs/vehicle-security-vanilla-sha256.json": "16ee4be00be331023668238f5f0272050f83031ee627f8c0fa234f88552aec5a",
|
||||
"docs/vanilla-resources.json": "d80edf67d429b578051cad1630d3c44fae70714d14a277e40294242f9b439783",
|
||||
"docs/vehicle-maintenance.md": "94362113ce91d248485b2ce25f9f99e60e55d1ac50d6d6dd728cba1fc797043c",
|
||||
"docs/vehicle-maintenance-source-evidence.json": "c84283c91ef554d8c6ded79ae9aecdfe00ad6922a150d4733260dc7a5a3d2fa2",
|
||||
"docs/radio-equipment-provenance.json": "ec67aeec4ec116dda41aba4f3f2448e739859b8f4082d548a5deb7992371f021",
|
||||
"docs/hq-originating-call.md": "ca1bbaa5f511b65a392d6dd6e361b6898a85b201f219f8e0bce25c30cef27a77",
|
||||
"docs/packed-external-development.md": "6e7cd3e3efc143de42ba44febe9b03811f7c263d4000593dfacaf28fcc3ef287",
|
||||
"docs/convoy-startup.md": "754b2ef659749d3307809f314eb2fcb4b16506c03e019f191ee5cf4e68a630aa",
|
||||
"docs/infantry-resupply-access.md": "8eb812945ba95660501ec3fd6626a354eadf9e68eddffb34bc66071e250e5fca",
|
||||
"docs/hq-local-handoff.md": "8225ba1ea2cef47930a4e04fea82a87dab92a8761349c3b7da5c918079ef675b",
|
||||
"docs/road-interception.md": "4a5a2e029e94ccd26ff578fdc6948d73e9193839474c9d39d573b7f3d5e7e114",
|
||||
"docs/single-mod.md": "31c628fb5bcf00486bddba527a8955e3f996cf31f9342b6e0bb2bdb314e38c19",
|
||||
"docs/multiplayer-prefab-ids.md": "b9dc13f6d5448871959d2f7872847af8824f21ec773f2683ed117d43c1a2a77d",
|
||||
"docs/prison-opening.md": "be60fee1542185bfae38cba9bacf1f181acf2a032af33d5eb853468a036cc54a",
|
||||
"docs/content-packs.md": "c543cbec225d6feb722c5f0a7bc848e3bda265bf89092bf5629b71d1ee4bf0ed",
|
||||
"docs/supply-convoys.md": "2193581f4f339879d1409fe90881ad0801e72d98d1b57325d09cd9300f11ef61",
|
||||
"docs/generated-sites.md": "0caf082c45e4ac84af5749ff6554312f6db66bfcb7e3485611c0040bb9d2196d",
|
||||
"docs/mortar-stations.md": "eda8ce9201fc1fda4c777174dd83aec93e6b5aad35c3632aef7494969ca539df",
|
||||
"docs/prison-patrol-and-debug-intel.md": "c02f57e65981eb74773fc4db2a9a82ac80b5b45276735ad5cf2af4a767caf172",
|
||||
"docs/airfield-extraction-and-map-icons.md": "5f21746c0b685811992765e6909f83d4a47eb6ff11b17974405136bb5d858350",
|
||||
"docs/mortar-intel-and-prison-map.md": "116f87df517804919363836ea577ac032e9bdcebf33da83c19ca1323e1731076",
|
||||
"docs/radio-camp-security.md": "ffd6f794601dcfe46e3c373aa7a868782366fa6e234b189d81af78a40d84fc81",
|
||||
"docs/hill-scouts.md": "8d6ff1a57334fd915925396558c9f8fb915fbb1f8689fb72e7bad3ddc7367a9f",
|
||||
"docs/search-helicopter.md": "6220eb11e64245a580d85bad683baa07f0ae499b5d7673e973bc401e87907482",
|
||||
"docs/hq-air-support.md": "b090de3a96b93f67987c27de182d5c05ee1890e98816c6a5441a7e54d626614d",
|
||||
"docs/aggression-ai.md": "62c2c8aeb23eaf085b54e2e480ce066588fd2a4df2e1a5180333f7107bc2ebdd",
|
||||
"docs/enemy-loadouts.md": "3d00ed31e6a169658a5d950c12b278cccdd7501c791b18d6ab8b2ffb90d06cef",
|
||||
"docs/gameplay-recovery.md": "ae1ffa270ab27afe9e2542be2f0b96b6a8527f4ad243ba4247e1f772b242f9f1",
|
||||
"docs/field-sites.md": "9c3928a04b4b242dcf806d7b20ecf2f4cc636aff9a31ed90d9fd75cfaf776aa0",
|
||||
"docs/town-garrisons.md": "c58e6b669997f8e1763a3da289e6ac6b777b15f0852eb2cd81b4c83fe2783eb4",
|
||||
"docs/ai-local-awareness.md": "9583de1d5233dde3cd259d464e0d5a859de9a69b24725acc2d141822fd3f9908",
|
||||
"docs/response-medics-combat.md": "17192d50d1a406de0547ce30a19eb8d9b216730d6c07ba2a89939687096faf1e",
|
||||
"docs/infantry-combat-priority.md": "a2609f8596d58d320f088b0f5c2e5de8ced6d94365ae1a8407fe763ea2da5db7",
|
||||
"docs/gameplay-review-2026-09-27.md": "ee66710a5fdefc1d1ced769e15119f6f1449fb9268b9a62733a8b2f9b733bc71",
|
||||
"docs/helicopter-standoff.md": "d804e148383f71d4457e773f62664b99d3e28401ba756f3fe6e447419aaa4350",
|
||||
"docs/airborne-validation-2026-09-27.md": "54b4655df8a449da5abf6ff04097119f8b6ae2ce69613b57e9dca3cd6f821000",
|
||||
"docs/mortar-rapid-fire.md": "412ef3c1cda90f774f9134db1ab150cb1e1d09189598e1beaecf5d1395b04a98",
|
||||
"docs/convoy-coordination.md": "095fa1f425688ad920e86363c88490aac6bd623f0dbe8dd2f039674cdc5908ff",
|
||||
"docs/server-log-fixes-2026-09-29.md": "44f69289ae12f1f38b71045d613c2500da6b7b3adbbdfec7166d7b216bfbf576",
|
||||
"docs/body-recovery-fixes-2026-09-29.md": "ce9f2978e3f2da13fab0bbbf88150b1f6dc7400a74c6ba7418f8a8b704c6f82b",
|
||||
"docs/infantry-resupply.md": "77eab95b9c9e33fb7a72c90025c5f36cc65ef3293eaa240a8e6019202d03721b",
|
||||
"docs/resupply-fixes-2026-09-30.md": "9e21d5b29f20350a2ee8c7b1fdc839c199e5c98777e88b310f14f7a583d70cdd",
|
||||
"docs/mission-checkpoint-2026-09-30.md": "48104b9c2a089404ed93da20d15a0e57283004bc8dfe0cea0b7477909791c7d0",
|
||||
"docs/combined-candidate-2026-09-30.md": "c53428454b2a6ea16f5e691fd4333f6f1bf2a6ad882f0fd05504f8e71b414d92",
|
||||
"docs/multiconvoy-resupply.md": "90e699e15914461392808802ec6029382dab1a2fc1a63eb0ab534557565661a4",
|
||||
"docs/hq-chronology-and-admission-2026-09-30.md": "1254daf6a44f27df8917805ce506d2005379641d9e4c10d9b396f5f0464fa1c9",
|
||||
"docs/empty-magazine-return.md": "d08e227c4b7d273687e9aca6645cdcdef8d6a88843ba00fb938fecfd4c8df154",
|
||||
"docs/next-gameplay-increments.md": "ee1a22dd3a79acf95fd3e59aad4599788a0f10f22eb4dbe1577875a651a18430",
|
||||
"docs/terrain-adapters.md": "70cfd9f50ef5e339de7ae98f48bf501eb4feb018d6a5739b465cf7407fcfcd95",
|
||||
"docs/nogova-publishing.md": "1a80072599a3e9bd460091c4b3ea39ff78324304730494641c94deb2b00adab7",
|
||||
"docs/mission-hq-fixes-2026-10-01.md": "5379ddb403f7c3611b2e92e0a9b4c043278fe136e28f93293dae1027ddc30ab9",
|
||||
"docs/player-route.md": "57165a47ef27c2fbeada41c2a68e3567f1e2ceef99fd1ac1ca89277fdc0041d5",
|
||||
"docs/terrain-takeover.md": "3504c5bcf820adcdfc4640f90ec2ea4347ac96b4b425d11658b2868c21bd5db1",
|
||||
"docs/ground-depot-loading.md": "1e4188d0818baea57086274ae6713a15fa414eec171e8d18e3ae8f64a85208f8",
|
||||
"docs/objective-map-presentation.md": "eccf546db122634ad3528207070b5aaa4005e72bd615f7ddd477d08481875305",
|
||||
"docs/mounted-interception.md": "f40d1dd93deb7e89f48c3a9645cf35c32531fd5ce3d9ce3247b6561d60155ebb",
|
||||
"README.md": "bd0bb8d87c4dfcfbaf4b48d89f86aac91d3ecbd0d05b8fe5e18bea8a92e40609",
|
||||
".gitignore": "b965eff620081f103bc18f8e6a37c670629e1275261448ea3af22688695edc2b"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,356 @@
|
||||
ERR_ScenarioDefinition {
|
||||
MinimumRadioSources 2
|
||||
ScoutCount 10
|
||||
Sites {
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-prison-1"
|
||||
RandomClear 1
|
||||
Label "Prison"
|
||||
Kind 0
|
||||
Prefab "{BE6B8D56349038A6}Prefabs/ERR/Prison.et"
|
||||
Position 6090 0 7160
|
||||
Guarded 1
|
||||
GuardOffset 35 0 0
|
||||
Container "{D93480F29E73C1AB}Prefabs/ERR/PrisonBackpack.et"
|
||||
ContainerOffset -4 0 0
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{C0F7DD85A86B2900}Prefabs/Weapons/Handguns/PM/Handgun_PM.et" Count 5 }
|
||||
ERR_SiteStock { Prefab "{8B853CDD11BA916E}Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et" Count 8 }
|
||||
ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-supply-1"
|
||||
AllowFactionPool 1
|
||||
Label "Southern supply cache"
|
||||
Kind 4
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 6150 0 7050
|
||||
Guarded 1
|
||||
GuardOffset 18 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 0
|
||||
Transport ERR_SiteTransport {
|
||||
Optional 1
|
||||
Prefab "{FA65287C19DE304B}Prefabs/ERR/Vehicles/SupplyUAZ.et"
|
||||
Offset 0 0 -12
|
||||
Heading 180
|
||||
ClearanceRadius 4
|
||||
MaximumTerrainRange 1
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 8 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 16 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
|
||||
ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 }
|
||||
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
|
||||
ERR_SiteStock { Prefab "{C09C7C97EFA34909}Prefabs/ERR/Items/EmergencyRepairKit.et" Count 1 }
|
||||
ERR_SiteStock { Prefab "{12D5AD21E383B768}Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et" Count 2 }
|
||||
}
|
||||
RevealOnEscape 1
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-radio-1"
|
||||
RandomClear 1
|
||||
RootHeight 0.8
|
||||
Label "Radio station"
|
||||
DiscoverRadius 8
|
||||
Kind 1
|
||||
Prefab "{47D725F56A904ACE}Prefabs/ERR/RadioCamp.et"
|
||||
Position 6500 0 7200
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 0 }
|
||||
ERR_SiteProp { Prefab "{B3949F6D215A9F78}Prefabs/Props/Military/Antennas/Antenna_FIA_02/Antenna_FIA_02_base.et" Offset -7 0 2 }
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -1.5 0 0 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -4.5 0 -6 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 4.5 0 -6 }
|
||||
}
|
||||
Guarded 1
|
||||
GuardOffset 30 0 0
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-extraction-1"
|
||||
Label "Initial helicopter pickup site"
|
||||
Kind 2
|
||||
Prefab "{033503110AC34EAC}Prefabs/ERR/Extraction.et"
|
||||
Position 4800.953 0 11487.412
|
||||
AircraftOffset 0 0 0
|
||||
RequireAirfield 1
|
||||
Guarded 1
|
||||
GuardOffset 30 0 0
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-medical-1"
|
||||
Label "Field hospital 1"
|
||||
Kind 6
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 6340 0 7400
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 6 0 -3
|
||||
DiscoverRadius 60
|
||||
RevealOnEscape 1
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{F8427C3EFC52644E}Prefabs/Structures/Military/Camps/TentUS_01/TentUSMedical_01.et" Offset 0 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 6 0 0 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -6 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 6 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
|
||||
ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 8 }
|
||||
ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-outpost-1"
|
||||
Label "Field camp 1"
|
||||
Kind 3
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 6740 0 7300
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 -4
|
||||
DiscoverRadius 60
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -4 0 2 }
|
||||
ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 5 0 2 Angles 180 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 -1 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -5 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-mortar-1"
|
||||
Label "Mortar site 1"
|
||||
Kind 5
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 6000 0 7000
|
||||
RandomClear 1
|
||||
DiscoverRadius 35
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-mortar-2"
|
||||
Label "Mortar site 2"
|
||||
Kind 5
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 4500 0 6500
|
||||
RandomClear 1
|
||||
DiscoverRadius 35
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-mortar-3"
|
||||
Label "Mortar site 3"
|
||||
Kind 5
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 7000 0 9500
|
||||
RandomClear 1
|
||||
DiscoverRadius 35
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-mortar-4"
|
||||
Label "Mortar site 4"
|
||||
Kind 5
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 4000 0 10500
|
||||
RandomClear 1
|
||||
DiscoverRadius 35
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-medical-2"
|
||||
Label "Field hospital 2"
|
||||
Kind 6
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 3000 0 6000
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 6 0 -3
|
||||
DiscoverRadius 60
|
||||
RevealOnEscape 0
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{F8427C3EFC52644E}Prefabs/Structures/Military/Camps/TentUS_01/TentUSMedical_01.et" Offset 0 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 6 0 0 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -6 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 6 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
|
||||
ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 8 }
|
||||
ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-medical-3"
|
||||
Label "Field hospital 3"
|
||||
Kind 6
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 8000 0 9500
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 6 0 -3
|
||||
DiscoverRadius 60
|
||||
RevealOnEscape 0
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{F8427C3EFC52644E}Prefabs/Structures/Military/Camps/TentUS_01/TentUSMedical_01.et" Offset 0 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 6 0 0 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -6 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 6 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 }
|
||||
ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 8 }
|
||||
ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-camp-2"
|
||||
Label "Field camp 2"
|
||||
Kind 3
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 2500 0 4500
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 -4
|
||||
DiscoverRadius 60
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -4 0 2 }
|
||||
ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 5 0 2 Angles 180 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 -1 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -5 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-camp-3"
|
||||
Label "Field camp 3"
|
||||
Kind 3
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 5500 0 3500
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 -4
|
||||
DiscoverRadius 60
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -4 0 2 }
|
||||
ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 5 0 2 Angles 180 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 -1 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -5 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-camp-4"
|
||||
Label "Field camp 4"
|
||||
Kind 3
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 7800 0 6000
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 -4
|
||||
DiscoverRadius 60
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -4 0 2 }
|
||||
ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 5 0 2 Angles 180 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 -1 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -5 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
|
||||
}
|
||||
}
|
||||
ERR_SiteDefinition {
|
||||
Id "everon-camp-5"
|
||||
Label "Field camp 5"
|
||||
Kind 3
|
||||
Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et"
|
||||
Position 5200 0 10000
|
||||
RandomClear 1
|
||||
Guarded 1
|
||||
GuardCount 4
|
||||
ResponseCount 2
|
||||
GuardOffset 12 0 0
|
||||
ResponseOffset -12 0 0
|
||||
Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et"
|
||||
ContainerOffset 0 0 -4
|
||||
DiscoverRadius 60
|
||||
Props {
|
||||
ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -4 0 2 }
|
||||
ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 5 0 2 Angles 180 0 0 }
|
||||
ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 -1 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -5 0 -7 }
|
||||
ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 5 0 -7 }
|
||||
}
|
||||
Stock {
|
||||
ERR_SiteStock { Prefab "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 }
|
||||
ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 }
|
||||
ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+783
@@ -0,0 +1,783 @@
|
||||
enum ERR_PrepareResult { FAILED = -1, PENDING, READY }
|
||||
|
||||
class ERR_StockPlacement
|
||||
{
|
||||
IEntity Item;
|
||||
InventoryStorageManagerComponent Inventory;
|
||||
bool Accepted;
|
||||
}
|
||||
|
||||
class ERR_SiteRuntime
|
||||
{
|
||||
ref ERR_SiteDefinition Definition;
|
||||
ERR_LocationComponent Location;
|
||||
IEntity Container;
|
||||
ref array<IEntity> DepotMagazines = {}; // Exact authored startup identities; never refreshed from live inventory.
|
||||
ref array<IEntity> DepotMines = {}; // At most two authored inert PMN4 per camp, never replenished.
|
||||
SCR_AIGroup Group;
|
||||
ref ERR_SiteRuntime Responders;
|
||||
string ExpectedGuardFaction;
|
||||
int InitialGuardCount;
|
||||
ref ERR_PrisonPatrol PrisonPatrol;
|
||||
int LastInitialPhysical = -1;
|
||||
int LastInitialConscious = -1;
|
||||
Vehicle Transport;
|
||||
IEntity TransportEntity;
|
||||
bool TransportAttempted;
|
||||
bool TransportOmitted;
|
||||
float TransportDeadline = -1;
|
||||
AIWaypointCycle PatrolCycle;
|
||||
ref array<AIWaypoint> PatrolWaypoints = {};
|
||||
ref array<IEntity> Props = {};
|
||||
}
|
||||
|
||||
// One owner for finite physical site contents. No population or stock refill tick.
|
||||
class ERR_SiteService
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected int m_ContentGuardIndex;
|
||||
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;
|
||||
protected bool m_Obstructed;
|
||||
protected string m_FailureReason;
|
||||
protected float m_NextDiscovery;
|
||||
string FailureReason() { return m_FailureReason; }
|
||||
|
||||
void ERR_SiteService(ERR_GameMode mode) { m_Mode = mode; }
|
||||
int Count() { return m_Sites.Count(); }
|
||||
ERR_SiteRuntime At(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_Sites.Count()) return null;
|
||||
return m_Sites[index];
|
||||
}
|
||||
// Optional ground loading consumes only retained original camp items.
|
||||
int DepotMagazineCount(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || m_State != ERR_PrepareResult.READY || !site || !m_Sites.Contains(site)) return 0;
|
||||
if (!site.Definition || site.Definition.Kind != ERR_LocationKind.OUTPOST || site.Definition.RevealOnEscape) return 0;
|
||||
if (!site.Container || !Owns(site.Container) || !site.Responders || !site.Responders.Group) return 0;
|
||||
if (site.DepotMagazines.Count() > 96) return 0;
|
||||
return site.DepotMagazines.Count();
|
||||
}
|
||||
int DepotMineCount(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || m_State != ERR_PrepareResult.READY || !site || !m_Sites.Contains(site)) return 0;
|
||||
if (!site.Definition || site.Definition.Kind != ERR_LocationKind.OUTPOST || site.Definition.RevealOnEscape) return 0;
|
||||
if (!site.Container || !Owns(site.Container) || !site.Responders || !site.Responders.Group) return 0;
|
||||
if (site.DepotMines.Count() > 2) return 0;
|
||||
return site.DepotMines.Count();
|
||||
}
|
||||
int DepotItemCount(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!site || site.DepotMagazines.Count() > 96 || site.DepotMines.Count() > 2) return 0;
|
||||
int count = DepotMagazineCount(site) + DepotMineCount(site);
|
||||
if (count > 96) return 0;
|
||||
return count;
|
||||
}
|
||||
IEntity DepotItem(ERR_SiteRuntime site, int index)
|
||||
{
|
||||
if (index < 0 || index >= DepotItemCount(site)) return null;
|
||||
int magazines = DepotMagazineCount(site);
|
||||
if (index < magazines) return site.DepotMagazines[index];
|
||||
return site.DepotMines[index - magazines];
|
||||
}
|
||||
void DepotStock(ERR_SiteRuntime site, out array<IEntity> items)
|
||||
{
|
||||
items = {};
|
||||
int count = DepotItemCount(site);
|
||||
for (int i = 0; i < count; i++) items.Insert(DepotItem(site, i));
|
||||
}
|
||||
IEntity DepotMagazine(ERR_SiteRuntime site, int index)
|
||||
{
|
||||
if (index < 0 || index >= DepotMagazineCount(site)) return null;
|
||||
return site.DepotMagazines[index];
|
||||
}
|
||||
bool DepotOriginal(ERR_SiteRuntime site, IEntity item)
|
||||
{
|
||||
return item && DepotItemCount(site) > 0 && (site.DepotMagazines.Contains(item) || site.DepotMines.Contains(item));
|
||||
}
|
||||
bool Owns(IEntity entity) { return entity && m_Entities.Contains(entity); }
|
||||
// Snapshot only nearby mission-owned objects. Distant sites must not block
|
||||
// arrival, and vanilla map streaming remains the native preload's job.
|
||||
bool SpawnScene(vector position, out array<IEntity> result)
|
||||
{
|
||||
result = {};
|
||||
array<IEntity> pending = {};
|
||||
foreach (IEntity root : m_Entities)
|
||||
if (root && vector.DistanceXZ(root.GetOrigin(), position) <= 120) pending.Insert(root);
|
||||
int visited;
|
||||
while (!pending.IsEmpty())
|
||||
{
|
||||
if (++visited > 512) return false;
|
||||
IEntity entity = pending[0]; pending.Remove(0);
|
||||
if (!entity) continue;
|
||||
RplComponent component = RplComponent.Cast(entity.FindComponent(RplComponent));
|
||||
if (component && !result.Contains(entity)) result.Insert(entity);
|
||||
if (result.Count() > 256) return false;
|
||||
IEntity child = entity.GetChildren();
|
||||
while (child) { pending.Insert(child); child = child.GetSibling(); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int TransportCount()
|
||||
{
|
||||
int count;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
if (site.Transport) count++;
|
||||
return count;
|
||||
}
|
||||
// Own physical group identity only; command providers do not inspect players.
|
||||
ERR_SiteRuntime FindGroup(SCR_AIGroup group)
|
||||
{
|
||||
if (!group) return null;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
if (site.Group == group || (site.Responders && site.Responders.Group == group)) return site;
|
||||
return null;
|
||||
}
|
||||
ERR_SiteRuntime Find(string id)
|
||||
{
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
if (site.Definition.Id == id) return site;
|
||||
return null;
|
||||
}
|
||||
protected bool CheckClearance(IEntity entity)
|
||||
{
|
||||
if (entity && entity.GetVObject()) m_Obstructed = true;
|
||||
return !m_Obstructed;
|
||||
}
|
||||
protected bool CacheClearance(vector position)
|
||||
{
|
||||
m_Obstructed = false;
|
||||
vector ground = ERR_Actors.Ground(position);
|
||||
GetGame().GetWorld().QueryEntitiesByAABB(ground + "-1.3 0.1 -1.3", ground + "1.3 2 1.3", CheckClearance);
|
||||
PrintFormat("Reintroduced [sites]: cache clearance position=%1 clear=%2", ground, !m_Obstructed);
|
||||
return !m_Obstructed;
|
||||
}
|
||||
protected bool GeneratedCacheClearance(vector position)
|
||||
{
|
||||
// Match the physical terrain survey. An entity's broad bounding box may
|
||||
// overlap an empty volume near a tree or ruin without blocking the cache.
|
||||
vector ground = ERR_Actors.Ground(position);
|
||||
TraceBox trace = new TraceBox();
|
||||
trace.Start = ground + "0 0.12 0"; trace.End = ground + "0 2 0";
|
||||
trace.Mins = "-1.3 0 -1.3"; trace.Maxs = "1.3 0.1 1.3";
|
||||
trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD;
|
||||
return GetGame().GetWorld().TraceMove(trace, null) >= 1;
|
||||
}
|
||||
protected bool BackpackClearance(vector position)
|
||||
{
|
||||
vector floor = ERR_Actors.Ground(position);
|
||||
TraceBox trace = new TraceBox();
|
||||
trace.Start = floor + "0 0.15 0"; trace.End = floor + "0 1.15 0";
|
||||
trace.Mins = "-0.5 0 -0.5"; trace.Maxs = "0.5 0.1 0.5";
|
||||
trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD;
|
||||
return GetGame().GetWorld().TraceMove(trace, null) >= 1;
|
||||
}
|
||||
protected bool CreateGuardOrders(ERR_SiteRuntime site, vector anchor)
|
||||
{
|
||||
if (site.Definition.Kind == ERR_LocationKind.RADIO) anchor = ERR_Actors.Ground(site.Location.Position());
|
||||
if (!site.Definition.Patrol || site.Definition.Patrol.IsEmpty())
|
||||
{
|
||||
AIWaypoint defend = AIWaypoint.Cast(Spawn(ERR_Resources.DefendWaypoint(), anchor));
|
||||
if (!defend) return false;
|
||||
if (site.Definition.Kind == ERR_LocationKind.RADIO) defend.SetCompletionRadius(20);
|
||||
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));
|
||||
if (entity) m_Entities.Insert(entity);
|
||||
return entity;
|
||||
}
|
||||
// Read-only placement survey. It neither removes scenery nor searches for a
|
||||
// replacement position; authors must correct a rejected parking location.
|
||||
bool TransportClearance(vector position, float radius, float maximumRange)
|
||||
{
|
||||
if (radius < 2 || radius > 8 || maximumRange < 0 || maximumRange > 1.5) return false;
|
||||
vector ground = ERR_Actors.Ground(position);
|
||||
float lowest = ground[1];
|
||||
float highest = ground[1];
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int z = -1; z <= 1; z++)
|
||||
{
|
||||
vector sample = ERR_Actors.Ground(position + Vector(x * radius, 0, z * radius));
|
||||
lowest = Math.Min(lowest, sample[1]);
|
||||
highest = Math.Max(highest, sample[1]);
|
||||
}
|
||||
}
|
||||
m_Obstructed = false;
|
||||
vector low = Vector(position[0] - radius, lowest + 0.1, position[2] - radius);
|
||||
vector high = Vector(position[0] + radius, highest + 3, position[2] + radius);
|
||||
GetGame().GetWorld().QueryEntitiesByAABB(low, high, CheckClearance);
|
||||
bool clear = lowest >= 1 && highest - lowest <= maximumRange && !m_Obstructed;
|
||||
PrintFormat("Reintroduced [sites]: transport parking=%1 radius=%2 terrainRange=%3 obstructed=%4 clear=%5", ERR_Actors.Ground(position), radius, highest - lowest, m_Obstructed, clear);
|
||||
return clear;
|
||||
}
|
||||
// Native recursive deletion must never consume an occupant or character that
|
||||
// acquired this candidate. Unknown/oversized hierarchies are relinquished.
|
||||
protected bool TransportEmpty(IEntity exact)
|
||||
{
|
||||
array<IEntity> pending = {exact};
|
||||
int visited;
|
||||
while (!pending.IsEmpty())
|
||||
{
|
||||
if (++visited > 128) return false;
|
||||
IEntity entity = pending[0]; pending.Remove(0);
|
||||
if (!entity) continue;
|
||||
if (ERR_Actors.Player(entity) || ChimeraCharacter.Cast(entity) || SCR_AIGroup.Cast(entity)) return false;
|
||||
BaseCompartmentManagerComponent manager = BaseCompartmentManagerComponent.Cast(entity.FindComponent(BaseCompartmentManagerComponent));
|
||||
if (Vehicle.Cast(entity) && !manager) return false;
|
||||
if (manager)
|
||||
{
|
||||
array<BaseCompartmentSlot> seats = {}; manager.GetCompartments(seats);
|
||||
if (seats.Count() > 64) return false;
|
||||
foreach (BaseCompartmentSlot seat : seats) if (!seat || seat.GetOccupant()) return false;
|
||||
}
|
||||
IEntity child = entity.GetChildren();
|
||||
while (child)
|
||||
{
|
||||
if (pending.Count() >= 128) return false;
|
||||
pending.Insert(child); child = child.GetSibling();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Only the transport identity recorded by CreateTransport may be omitted.
|
||||
// Required transports preserve the existing whole-preparation failure policy.
|
||||
protected bool TransportFailure(ERR_SiteRuntime site, string reason)
|
||||
{
|
||||
if (!site.Definition.Transport.Optional) return Fail(reason);
|
||||
if (site.TransportOmitted) return true;
|
||||
site.TransportOmitted = true;
|
||||
IEntity exact = site.TransportEntity;
|
||||
site.TransportEntity = null;
|
||||
site.Transport = null;
|
||||
if (exact && m_Entities.Contains(exact))
|
||||
{
|
||||
m_Entities.RemoveItem(exact);
|
||||
if (TransportEmpty(exact)) ERR_Actors.DeleteSpawned(exact);
|
||||
else PrintFormat("Reintroduced [sites]: optional transport cleanup relinquished: %1; occupied or uncertain candidate retained", site.Definition.Id);
|
||||
}
|
||||
PrintFormat("Reintroduced [sites]: optional transport omitted: %1; %2", site.Definition.Id, reason);
|
||||
return true;
|
||||
}
|
||||
protected bool CreateTransport(ERR_SiteRuntime site, vector sitePosition, bool allowOptional = false)
|
||||
{
|
||||
ERR_SiteTransport spec = site.Definition.Transport;
|
||||
if (!spec || (spec.Optional && !allowOptional)) return true;
|
||||
if (site.TransportAttempted) return spec.Optional || site.TransportOmitted || site.Transport != null;
|
||||
site.TransportAttempted = true;
|
||||
vector position = ERR_Actors.Ground(sitePosition + spec.Offset);
|
||||
if (!TransportClearance(position, spec.ClearanceRadius, spec.MaximumTerrainRange)) return TransportFailure(site, "obstructed or unsafe transport parking: " + site.Definition.Id);
|
||||
IEntity entity = ERR_Actors.Spawn(spec.Prefab, position, Vector(spec.Heading, 0, 0));
|
||||
if (!entity) return TransportFailure(site, "transport prefab: " + site.Definition.Id);
|
||||
m_Entities.Insert(entity);
|
||||
site.TransportEntity = entity;
|
||||
if (spec.Optional) site.TransportDeadline = GetGame().GetWorld().GetWorldTime() + 15000;
|
||||
site.Transport = Vehicle.Cast(entity);
|
||||
if (!site.Transport) return TransportFailure(site, "transport must be a vehicle: " + site.Definition.Id);
|
||||
CarControllerComponent controller = CarControllerComponent.Cast(site.Transport.FindComponent(CarControllerComponent));
|
||||
if (!controller) return TransportFailure(site, "transport must be wheeled: " + site.Definition.Id);
|
||||
controller.SetPersistentHandBrake(true);
|
||||
ERR_VehicleSecurityComponent security = ERR_VehicleSecurityComponent.Find(site.Transport);
|
||||
if (security && !security.Configure()) return TransportFailure(site, "transport security configuration: " + site.Definition.Id);
|
||||
return true;
|
||||
}
|
||||
protected bool TransportReady(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!site.Definition.Transport || site.TransportOmitted) return true;
|
||||
Vehicle vehicle = site.Transport;
|
||||
if (!ERR_Actors.Alive(vehicle)) return false;
|
||||
vector low, high;
|
||||
vehicle.GetWorldBounds(low, high);
|
||||
vector center = ERR_Actors.Ground(site.Definition.Position + site.Definition.Transport.Offset);
|
||||
float radius = site.Definition.Transport.ClearanceRadius - 0.5;
|
||||
if (Math.AbsFloat(low[0] - center[0]) > radius || Math.AbsFloat(high[0] - center[0]) > radius || Math.AbsFloat(low[2] - center[2]) > radius || Math.AbsFloat(high[2] - center[2]) > radius)
|
||||
{
|
||||
if (GetGame().GetWorld().GetWorldTime() > m_Deadline) PrintFormat("Reintroduced [sites]: transport footprint low=%1 high=%2 surveyedCenter=%3 origin=%4 allowedRadius=%5", low, high, center, vehicle.GetOrigin(), radius);
|
||||
return false;
|
||||
}
|
||||
FuelManagerComponent fuel = FuelManagerComponent.Cast(vehicle.FindComponent(FuelManagerComponent));
|
||||
if (!fuel || !fuel.HasFuel())
|
||||
{
|
||||
if (GetGame().GetWorld().GetWorldTime() > m_Deadline) PrintFormat("Reintroduced [sites]: transport fuel manager=%1 hasFuel=%2", fuel != null, fuel && fuel.HasFuel());
|
||||
return false;
|
||||
}
|
||||
BaseCompartmentManagerComponent manager = BaseCompartmentManagerComponent.Cast(vehicle.FindComponent(BaseCompartmentManagerComponent));
|
||||
if (!manager) return false;
|
||||
array<BaseCompartmentSlot> seats = {};
|
||||
manager.GetCompartments(seats);
|
||||
bool driver, passenger;
|
||||
foreach (BaseCompartmentSlot slot : seats)
|
||||
{
|
||||
if (!slot) continue;
|
||||
ECompartmentType type = SCR_CompartmentAccessComponent.GetCompartmentType(slot);
|
||||
if (type == ECompartmentType.PILOT) driver = true;
|
||||
if (type == ECompartmentType.CARGO) passenger = true;
|
||||
}
|
||||
if ((!driver || !passenger) && GetGame().GetWorld().GetWorldTime() > m_Deadline) PrintFormat("Reintroduced [sites]: transport seats=%1 driver=%2 passenger=%3", seats.Count(), driver, passenger);
|
||||
return driver && passenger;
|
||||
}
|
||||
protected bool Fail(string reason)
|
||||
{
|
||||
m_FailureReason = reason;
|
||||
Print("Reintroduced [sites]: preparation failed: " + reason, LogLevel.ERROR);
|
||||
Rollback();
|
||||
m_State = ERR_PrepareResult.FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Begin(ERR_ScenarioDefinition definition, ResourceName fieldMap)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Begun || m_Stopped) return false;
|
||||
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);
|
||||
if (position[1] < 1) return Fail("site below sea level: " + spec.Id);
|
||||
vector rootPosition = position;
|
||||
if (spec.PlacementResolved && spec.Kind == ERR_LocationKind.PRISON) rootPosition = spec.Position;
|
||||
rootPosition[1] = rootPosition[1] + spec.RootHeight;
|
||||
IEntity root = ERR_Actors.Spawn(spec.Prefab, rootPosition, Vector(spec.Heading, 0, 0));
|
||||
if (root) m_Entities.Insert(root);
|
||||
if (!root) return Fail("site composition: " + spec.Id);
|
||||
ERR_SiteRuntime site = new ERR_SiteRuntime();
|
||||
site.Definition = spec;
|
||||
site.Location = ERR_LocationComponent.Cast(root.FindComponent(ERR_LocationComponent));
|
||||
if (!site.Location || !site.Location.Configure(spec.Id, spec.Kind, spec.Label)) return Fail("location identity: " + spec.Id);
|
||||
m_Sites.Insert(site);
|
||||
if (spec.Kind == ERR_LocationKind.PRISON) m_Mode.ConfigureStart(position, spec.Heading);
|
||||
if (spec.Kind == ERR_LocationKind.EXTRACTION)
|
||||
{
|
||||
vector aircraftPosition = ERR_Actors.Ground(position + ERR_CampTerrain.Rotate(spec.AircraftOffset, spec.Heading));
|
||||
if (spec.RequireAirfield && !ERR_AirfieldPlacement.Clear(aircraftPosition)) return Fail("extraction airfield pad is missing or obstructed; no off-airfield fallback");
|
||||
if (definition.TerrainGenerated && !spec.RequireAirfield && !ERR_AirfieldPlacement.ClearGround(aircraftPosition)) return Fail("generated extraction landing zone is obstructed");
|
||||
Vehicle helicopter = Vehicle.Cast(Spawn(m_Mode.Factions().ExtractionPrefab, aircraftPosition));
|
||||
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())
|
||||
{
|
||||
vector containerPosition = position + ERR_CampTerrain.Rotate(spec.ContainerOffset, spec.Heading);
|
||||
bool clearContainer;
|
||||
if (spec.Kind == ERR_LocationKind.PRISON) clearContainer = BackpackClearance(containerPosition);
|
||||
else if (spec.PlacementResolved) clearContainer = GeneratedCacheClearance(containerPosition);
|
||||
else clearContainer = CacheClearance(containerPosition);
|
||||
if (!clearContainer) return Fail("obstructed cache position: " + spec.Id);
|
||||
site.Container = Spawn(spec.Container, position + ERR_CampTerrain.Rotate(spec.ContainerOffset, spec.Heading));
|
||||
if (!site.Container) return Fail("container: " + spec.Id);
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(site.Container.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) return Fail("container inventory: " + spec.Id);
|
||||
BaseInventoryStorageComponent storage = BaseInventoryStorageComponent.Cast(site.Container.FindComponent(BaseInventoryStorageComponent));
|
||||
if (!storage) return Fail("container storage: " + spec.Id);
|
||||
inventory.AddStorage(storage);
|
||||
if (spec.Stock)
|
||||
{
|
||||
foreach (ERR_SiteStock stock : spec.Stock)
|
||||
{
|
||||
ResourceName resource = stock.Prefab;
|
||||
if (resource == ERR_Supplies.Map()) resource = fieldMap;
|
||||
for (int i = 0; i < stock.Count; i++)
|
||||
{
|
||||
// Created exactly once; insertion retries always use this same entity.
|
||||
IEntity item = Spawn(resource, site.Container.GetOrigin());
|
||||
if (!item) return Fail("stock resource: " + spec.Id);
|
||||
if (!stock.TargetId.IsEmpty())
|
||||
{
|
||||
ERR_DocumentComponent document = ERR_DocumentComponent.Cast(item.FindComponent(ERR_DocumentComponent));
|
||||
if (!document) return Fail("targeted document component");
|
||||
document.SetTarget(stock.TargetId);
|
||||
}
|
||||
ERR_StockPlacement placement = new ERR_StockPlacement();
|
||||
if (spec.Kind == ERR_LocationKind.OUTPOST && !spec.RevealOnEscape && stock.TargetId.IsEmpty()
|
||||
&& site.DepotMagazines.Count() + site.DepotMines.Count() < 96)
|
||||
{
|
||||
if (item.FindComponent(BaseMagazineComponent)) site.DepotMagazines.Insert(item);
|
||||
else if (stock.Prefab == "{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et"
|
||||
&& site.DepotMines.Count() < 2) site.DepotMines.Insert(item);
|
||||
}
|
||||
placement.Item = item;
|
||||
placement.Inventory = inventory;
|
||||
m_Placements.Insert(placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spec.Props)
|
||||
{
|
||||
foreach (ERR_SiteProp prop : spec.Props)
|
||||
{
|
||||
vector propPosition = ERR_Actors.Ground(position + ERR_CampTerrain.Rotate(prop.Offset, spec.Heading));
|
||||
// Radio furniture intentionally surrounds/supports its own elevated radio.
|
||||
// Generated camp terrain was checked before any of these objects existed.
|
||||
if (!spec.PlacementResolved && spec.Kind != ERR_LocationKind.RADIO && !CacheClearance(propPosition)) return Fail("obstructed scenery position: " + spec.Id);
|
||||
propPosition[1] = propPosition[1] + prop.Offset[1];
|
||||
IEntity scenery = ERR_Actors.Spawn(prop.Prefab, propPosition, prop.Angles + Vector(spec.Heading, 0, 0));
|
||||
if (!scenery) return Fail("scenery prefab: " + spec.Id);
|
||||
m_Entities.Insert(scenery); site.Props.Insert(scenery);
|
||||
SCR_AIWorld aiWorld = SCR_AIWorld.Cast(GetGame().GetAIWorld());
|
||||
if (aiWorld) aiWorld.RequestNavmeshRebuildEntity(scenery);
|
||||
}
|
||||
}
|
||||
if (!CreateTransport(site, position)) return false;
|
||||
if (spec.Guarded || !spec.Guards.IsEmpty())
|
||||
{
|
||||
vector guardPosition = position + ERR_CampTerrain.Rotate(spec.GuardOffset, spec.Heading);
|
||||
ResourceName groupPrefab = spec.Guards;
|
||||
site.ExpectedGuardFaction = m_Mode.Factions().EnemyFactionKey;
|
||||
if (spec.AllowFactionPool && m_Mode.Content())
|
||||
{
|
||||
ResourceName selectedGroup = m_Mode.Content().GuardGroup(m_ContentGuardIndex++);
|
||||
if (!selectedGroup.IsEmpty())
|
||||
{
|
||||
groupPrefab = selectedGroup;
|
||||
site.ExpectedGuardFaction = m_Mode.Content().GuardFaction(selectedGroup);
|
||||
}
|
||||
}
|
||||
if (groupPrefab.IsEmpty()) groupPrefab = m_Mode.Factions().GuardGroupPrefab;
|
||||
if (spec.Kind == ERR_LocationKind.PRISON)
|
||||
{
|
||||
site.Group = SCR_AIGroup.Cast(Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", guardPosition));
|
||||
if (!ERR_PrisonPatrol.Configure(site.Group, groupPrefab, m_Mode.EnemyFaction())) return Fail("prison patrol roster: " + spec.Id);
|
||||
site.PrisonPatrol = new ERR_PrisonPatrol();
|
||||
}
|
||||
else if (spec.GuardCount > 0)
|
||||
{
|
||||
site.Group = SCR_AIGroup.Cast(Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", guardPosition));
|
||||
Faction faction = GetGame().GetFactionManager().GetFactionByKey(site.ExpectedGuardFaction);
|
||||
if (!ERR_SiteSquads.Configure(site.Group, groupPrefab, faction, spec.GuardCount)) return Fail("site defender roster: " + spec.Id);
|
||||
}
|
||||
else site.Group = SCR_AIGroup.Cast(Spawn(groupPrefab, guardPosition));
|
||||
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);
|
||||
if (!CreateResponders(site, groupPrefab)) return Fail("site mobile roster: " + spec.Id);
|
||||
}
|
||||
PrintFormat("Reintroduced [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 (!m_Mode.IsMissionEnemy(site.Group.GetFaction()))
|
||||
{
|
||||
Fail("guard group faction disagrees with catalog: " + site.Definition.Id);
|
||||
return m_State;
|
||||
}
|
||||
if (site.Group.GetFaction().GetFactionKey() != site.ExpectedGuardFaction)
|
||||
{
|
||||
Fail("guard prefab faction disagrees with its content definition: " + 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) != site.Group.GetFaction())
|
||||
{
|
||||
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("Reintroduced [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("Reintroduced [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));
|
||||
}
|
||||
if (result == ERR_PrepareResult.READY && site.PrisonPatrol)
|
||||
{
|
||||
if (!site.PrisonPatrol.Place(site.Group, site.Location.Position()))
|
||||
{
|
||||
Fail("no clear perimeter positions for prison patrol"); return ERR_PrepareResult.FAILED;
|
||||
}
|
||||
result = site.PrisonPatrol.Radio(m_Mode, site.Group, m_GuardDeadline);
|
||||
if (result == ERR_PrepareResult.FAILED) Fail("prison patrol large radio could not be equipped");
|
||||
}
|
||||
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;
|
||||
array<ERR_SiteRuntime> pendingGroups = {};
|
||||
foreach (ERR_SiteRuntime owner : m_Sites) { pendingGroups.Insert(owner); if (owner.Responders) pendingGroups.Insert(owner.Responders); }
|
||||
foreach (ERR_SiteRuntime site : pendingGroups)
|
||||
{
|
||||
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;
|
||||
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 (site.Definition.Transport && !site.Definition.Transport.Optional && !TransportReady(site))
|
||||
{
|
||||
if (GetGame().GetWorld().GetWorldTime() > m_Deadline) Fail("transport needs fuel, driver/passenger seats and a fitting parking footprint: " + 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++;
|
||||
if (site.Responders)
|
||||
{
|
||||
ERR_PrepareResult mobile = InitialGuards(site.Responders);
|
||||
if (mobile == ERR_PrepareResult.FAILED) return m_State;
|
||||
if (mobile == ERR_PrepareResult.PENDING) pendingGuards++;
|
||||
}
|
||||
}
|
||||
string firstRejected;
|
||||
foreach (ERR_StockPlacement placement : m_Placements)
|
||||
{
|
||||
if (!placement.Item || !placement.Inventory) { Fail("stock disappeared during initialization"); return m_State; }
|
||||
array<IEntity> items = {};
|
||||
placement.Inventory.GetItems(items);
|
||||
if (items.Contains(placement.Item)) continue;
|
||||
pending++;
|
||||
if (firstRejected.IsEmpty() && placement.Item.GetPrefabData()) firstRejected = placement.Item.GetPrefabData().GetPrefabName();
|
||||
if (placement.Accepted) accepted++;
|
||||
if (!placement.Accepted) placement.Accepted = placement.Inventory.TryInsertItem(placement.Item);
|
||||
}
|
||||
if (pending)
|
||||
{
|
||||
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;
|
||||
// All required scenery, stock and physical guards now exist. Survey optional
|
||||
// parking once against that real population, then bound only vehicle settling.
|
||||
int pendingTransports;
|
||||
foreach (ERR_SiteRuntime optionalSite : m_Sites)
|
||||
{
|
||||
if (!optionalSite.Definition.Transport || !optionalSite.Definition.Transport.Optional) continue;
|
||||
if (!CreateTransport(optionalSite, optionalSite.Definition.Position, true)) return m_State;
|
||||
if (TransportReady(optionalSite)) continue;
|
||||
if (GetGame().GetWorld().GetWorldTime() > optionalSite.TransportDeadline)
|
||||
{
|
||||
if (!TransportFailure(optionalSite, "transport needs fuel, driver/passenger seats and a fitting parking footprint: " + optionalSite.Definition.Id)) return m_State;
|
||||
}
|
||||
else pendingTransports++;
|
||||
}
|
||||
if (pendingTransports > 0) return m_State;
|
||||
foreach (IEntity entity : m_Entities) m_Mode.Own(entity);
|
||||
m_State = ERR_PrepareResult.READY;
|
||||
PrintFormat("Reintroduced [sites]: %1 sites and %2 physical stock items ready", m_Sites.Count(), m_Placements.Count());
|
||||
m_Placements.Clear();
|
||||
return m_State;
|
||||
}
|
||||
|
||||
void Activate()
|
||||
{
|
||||
if (m_State != ERR_PrepareResult.READY || m_Stopped || m_Activated) return;
|
||||
m_Activated = true;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
{
|
||||
if (site.Definition.Kind == ERR_LocationKind.PRISON && site.Location) site.Location.Discover(0, 100);
|
||||
if (site.Group)
|
||||
{
|
||||
ERR_ForceRoute route;
|
||||
ERR_ForceKind kind = ERR_ForceKind.GARRISON;
|
||||
if (site.Definition.Patrol && !site.Definition.Patrol.IsEmpty())
|
||||
{
|
||||
route = new ERR_ForceRoute(true);
|
||||
vector anchor = site.Definition.Position + site.Definition.GuardOffset;
|
||||
foreach (ERR_SitePatrolPoint point : site.Definition.Patrol) route.Add(anchor + point.Offset);
|
||||
kind = ERR_ForceKind.PATROL;
|
||||
}
|
||||
m_Mode.Forces().Register(site.Definition.Id, kind, site.Group.GetOrigin(), m_Mode.ForceLiving(site.Group), route, site.Group, GetGame().GetWorld().GetWorldTime());
|
||||
m_Mode.RegisterGroup(site.Group);
|
||||
ActivateResponders(site);
|
||||
}
|
||||
}
|
||||
}
|
||||
void PhaseChanged(ERR_Phase previous, ERR_Phase current)
|
||||
{
|
||||
if (!Replication.IsServer() || current != ERR_Phase.RADIO_SEARCH) return;
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
if (site.Definition.RevealOnEscape && site.Location) site.Location.Discover(0, 100);
|
||||
}
|
||||
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.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 (!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";
|
||||
trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
|
||||
trace.LayerMask = TRACE_LAYER_CAMERA;
|
||||
trace.Exclude = player;
|
||||
return GetGame().GetWorld().TraceMove(trace, null) >= 1;
|
||||
}
|
||||
void Tick(float now)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopped || now < m_NextDiscovery) return;
|
||||
m_NextDiscovery = now + 5000;
|
||||
array<IEntity> players = {};
|
||||
ERR_Actors.Players(players, true);
|
||||
foreach (ERR_SiteRuntime site : m_Sites)
|
||||
{
|
||||
if (!site.Location || site.Location.Knowledge() >= 2) continue;
|
||||
foreach (IEntity player : players)
|
||||
{
|
||||
if (!CanObserve(player, site)) continue;
|
||||
site.Location.Discover(0, 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Rollback()
|
||||
{
|
||||
// An unrelated required failure can arrive while an optional candidate is
|
||||
// settling. Apply the same occupant-safe omission before recursive rollback.
|
||||
if (m_State == ERR_PrepareResult.PENDING)
|
||||
foreach (ERR_SiteRuntime optionalSite : m_Sites)
|
||||
if (optionalSite.Definition.Transport && optionalSite.Definition.Transport.Optional && optionalSite.TransportEntity)
|
||||
TransportFailure(optionalSite, "preparation rolled back before optional transport readiness");
|
||||
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()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
m_Stopped = true;
|
||||
if (m_ExtractionPlacement) m_ExtractionPlacement.Stop();
|
||||
if (m_State == ERR_PrepareResult.PENDING) CancelInitialGuardRequests();
|
||||
StopPatrols();
|
||||
}
|
||||
protected bool CreateResponders(ERR_SiteRuntime site, ResourceName profile)
|
||||
{
|
||||
ERR_SiteDefinition spec = site.Definition;
|
||||
if (spec.ResponseCount == 0) return true;
|
||||
ERR_SiteRuntime mobile = new ERR_SiteRuntime();
|
||||
site.Responders = mobile;
|
||||
mobile.Definition = spec; mobile.Location = site.Location;
|
||||
mobile.ExpectedGuardFaction = site.ExpectedGuardFaction;
|
||||
vector position = ERR_Actors.Ground(spec.Position + ERR_CampTerrain.Rotate(spec.ResponseOffset, spec.Heading));
|
||||
mobile.Group = SCR_AIGroup.Cast(Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", position));
|
||||
mobile.InitialGuardCount = spec.ResponseCount;
|
||||
if (!ERR_SiteSquads.Configure(mobile.Group, profile, site.Group.GetFaction(), spec.ResponseCount)) return false;
|
||||
// Local guard duty resumes when an HQ search expires. HQ inserts its delivered
|
||||
// search ahead of this waypoint; only this mobile group is eligible to leave.
|
||||
AIWaypoint home = AIWaypoint.Cast(Spawn(ERR_Resources.DefendWaypoint(), position));
|
||||
if (!home) return false;
|
||||
home.SetCompletionRadius(25); mobile.Group.AddWaypoint(home);
|
||||
return true;
|
||||
}
|
||||
protected void ActivateResponders(ERR_SiteRuntime site)
|
||||
{
|
||||
if (!site.Responders || !site.Responders.Group) return;
|
||||
SCR_AIGroup group = site.Responders.Group;
|
||||
m_Mode.Forces().Register(site.Definition.Id + "-responders", ERR_ForceKind.PATROL, group.GetOrigin(), m_Mode.ForceLiving(group), null, group, GetGame().GetWorld().GetWorldTime());
|
||||
m_Mode.RegisterGroup(group);
|
||||
ERR_HQ.Event("SITE GARRISON", string.Format("%1 (%2) at %3: %4 permanent defenders stay at the site; %5 mobile soldiers may receive HQ hunting orders; faction=%6", site.Definition.Label, site.Definition.Id, site.Location.Position(), m_Mode.ForceLiving(site.Group), m_Mode.ForceLiving(group), site.ExpectedGuardFaction));
|
||||
}
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// Optional depot work runs after all existing tactical/logistics planners.
|
||||
modded class ERR_HQ
|
||||
{
|
||||
protected ref ERR_GroundDepotLoading m_GroundDepot;
|
||||
int GroundSupplyCount()
|
||||
{
|
||||
if (!m_Resupply) return 0;
|
||||
return m_Resupply.Count();
|
||||
}
|
||||
ERR_InfantryResupply GroundSupplyAt(int index)
|
||||
{
|
||||
if (!m_Resupply) return null;
|
||||
return m_Resupply.At(index);
|
||||
}
|
||||
ERR_HQUnit GroundUnit(SCR_AIGroup group)
|
||||
{
|
||||
if (!group) return null;
|
||||
foreach (ERR_HQUnit unit : m_Units) if (unit && unit.Group == group) return unit;
|
||||
return null;
|
||||
}
|
||||
bool ReserveGroundDepot(ERR_HQUnit crew, ERR_HQUnit donor, ERR_InfantryResupply service, int token, bool mineCargo = false)
|
||||
{
|
||||
if (!Replication.IsServer() || m_Stopping || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return false;
|
||||
if (m_Mode.Command() != this) return false;
|
||||
if (token <= 300000 || token > 300096 || !crew || !donor || crew == donor || !m_Units.Contains(crew)) return false;
|
||||
if (!service || !MountedLogisticsEligible(donor)) return false;
|
||||
if (mineCargo) { if (!service.DepotMineNeeded()) return false; }
|
||||
else if (!service.DepotNeeded()) return false;
|
||||
ERR_ConvoyVehicle truck = service.DepotTruck();
|
||||
if (!truck || truck.Group != donor.Group || truck.SupplyToken > 0) return false;
|
||||
if (crew.HomeGuard || crew.ReservedForSupport || crew.Task || crew.PendingTask || crew.PendingCheckin || crew.PendingConvoyOrder) return false;
|
||||
if (!ReserveLogistics(crew.Group, token)) return false;
|
||||
// Single authoritative call, no native mutation between validation and claims.
|
||||
donor.LogisticsReservation = token; truck.SupplyToken = token;
|
||||
return true;
|
||||
}
|
||||
void ReleaseGroundDepot(ERR_HQUnit crew, ERR_HQUnit donor, ERR_ConvoyVehicle truck, int token)
|
||||
{
|
||||
if (!Replication.IsServer() || token <= 300000 || token > 300096) return;
|
||||
// These retained exact unit objects outlive base Stop's m_Units.Clear().
|
||||
if (crew && crew.LogisticsReservation == token) crew.LogisticsReservation = 0;
|
||||
if (donor && donor.LogisticsReservation == token) donor.LogisticsReservation = 0;
|
||||
if (truck && truck.SupplyToken == token) { truck.SupplyToken = 0; truck.SupplyHeld = false; }
|
||||
}
|
||||
override string Status()
|
||||
{
|
||||
string result = super.Status();
|
||||
if (m_GroundDepot) result += "\n" + m_GroundDepot.Status();
|
||||
return result;
|
||||
}
|
||||
override void Tick(float now)
|
||||
{
|
||||
super.Tick(now);
|
||||
if (!Replication.IsServer() || !m_Mode || m_Mode != ERR_GameMode.Get() || m_Mode.Command() != this) return;
|
||||
if (m_GroundDepot) m_GroundDepot.Tick(now);
|
||||
if (m_Stopping || !m_Mode.Active() || m_Mode.Phase() < ERR_Phase.RADIO_SEARCH) return;
|
||||
if (!m_GroundDepot) m_GroundDepot = new ERR_GroundDepotLoading(this, m_Mode);
|
||||
m_GroundDepot.Plan(now);
|
||||
}
|
||||
protected void CancelGroundDepotPoll()
|
||||
{
|
||||
if (GetGame() && GetGame().GetCallqueue()) GetGame().GetCallqueue().Remove(PollGroundDepot);
|
||||
}
|
||||
protected void PollGroundDepot()
|
||||
{
|
||||
CancelGroundDepotPoll();
|
||||
if (!m_Stopping || !Replication.IsServer() || !m_Mode || m_Mode != ERR_GameMode.Get() || m_Mode.Command() != this) return;
|
||||
if (!m_GroundDepot || !GetGame() || !GetGame().GetWorld() || !GetGame().GetCallqueue()) return;
|
||||
m_GroundDepot.Tick(GetGame().GetWorld().GetWorldTime());
|
||||
if (m_GroundDepot.Unresolved()) GetGame().GetCallqueue().CallLater(PollGroundDepot, 1000, false);
|
||||
}
|
||||
override void Stop()
|
||||
{
|
||||
if (m_GroundDepot) m_GroundDepot.Stop();
|
||||
super.Stop();
|
||||
PollGroundDepot();
|
||||
}
|
||||
void ~ERR_HQ() { CancelGroundDepotPoll(); }
|
||||
}
|
||||
+365
@@ -0,0 +1,365 @@
|
||||
// Native storage anchors only; no invented interaction point or remote move.
|
||||
class ERR_GroundDepotAccess
|
||||
{
|
||||
protected IEntity m_Root;
|
||||
protected IEntity m_Actor;
|
||||
protected bool Filter(notnull IEntity entity)
|
||||
{
|
||||
return !ERR_ConvoyRules.PartOf(entity, m_Root) && !ERR_ConvoyRules.PartOf(entity, m_Actor);
|
||||
}
|
||||
static bool Points(IEntity root, out array<vector> points)
|
||||
{
|
||||
points = {};
|
||||
if (!root) return false;
|
||||
ActionsManagerComponent manager = ActionsManagerComponent.Cast(root.FindComponent(ActionsManagerComponent));
|
||||
if (!manager || !manager.IsEnabled()) return false;
|
||||
array<UserActionContext> contexts = {}; manager.GetContextList(contexts);
|
||||
if (contexts.IsEmpty() || contexts.Count() > 128) return false;
|
||||
foreach (UserActionContext context : contexts)
|
||||
{
|
||||
if (!context) return false;
|
||||
array<BaseUserAction> actions = {}; context.GetActionsList(actions);
|
||||
if (actions.Count() > 64) return false;
|
||||
bool storage;
|
||||
foreach (BaseUserAction action : actions)
|
||||
if (action && action.GetOwner() == root && (SCR_OpenStorageAction.Cast(action) || SCR_OpenVehicleStorageAction.Cast(action))) storage = true;
|
||||
if (!storage) continue;
|
||||
vector transform[4];
|
||||
if (!context.GetTransformationWorld(transform) || !ERR_ForceRules.FiniteVector(transform[3])) return false;
|
||||
points.Insert(transform[3]);
|
||||
}
|
||||
return !points.IsEmpty();
|
||||
}
|
||||
bool Check(IEntity root, IEntity actor)
|
||||
{
|
||||
ChimeraCharacter character = ChimeraCharacter.Cast(actor);
|
||||
if (!character || !GetGame() || !GetGame().GetWorld()) return false;
|
||||
array<vector> points;
|
||||
if (!Points(root, points)) return false;
|
||||
vector start = character.AimingPosition();
|
||||
if (!ERR_ForceRules.FiniteVector(start)) return false;
|
||||
m_Root = root; m_Actor = actor;
|
||||
foreach (vector point : points)
|
||||
{
|
||||
float distance = vector.Distance(start, point);
|
||||
if (!(distance >= 0.05 && distance <= 3)) continue;
|
||||
TraceParam trace = new TraceParam(); trace.Start = start; trace.End = point;
|
||||
trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS; trace.LayerMask = TRACE_LAYER_CAMERA;
|
||||
if (GetGame().GetWorld().TraceMove(trace, Filter) == 1) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool Clear(IEntity root, IEntity actor)
|
||||
{
|
||||
ERR_GroundDepotAccess access = new ERR_GroundDepotAccess(); return access.Check(root, actor);
|
||||
}
|
||||
}
|
||||
|
||||
// Opportunistic camp -> original responder -> original ammo truck. One job
|
||||
// mission-wide; no new force, warehouse, stock, native inventory retry or refill.
|
||||
class ERR_GroundDepotLoading
|
||||
{
|
||||
protected ERR_HQ m_HQ;
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ref array<IEntity> m_Original = {};
|
||||
protected ref array<IEntity> m_Spent = {};
|
||||
protected bool m_Captured;
|
||||
protected bool m_Stopped;
|
||||
protected int m_Attempts;
|
||||
protected int m_Delivered;
|
||||
protected int m_State; // 0 idle,1 truck radio,2 stopped report,3 porter radio,4 pickup,5 delivery,6 returning,7 quarantine
|
||||
protected int m_Token;
|
||||
protected float m_Deadline;
|
||||
protected float m_HeldAt = -1;
|
||||
protected float m_NextPlan;
|
||||
protected float m_NextTick;
|
||||
protected float m_Last = -1;
|
||||
protected ERR_SiteRuntime m_Site;
|
||||
protected IEntity m_Cache;
|
||||
protected InventoryStorageManagerComponent m_CacheInventory;
|
||||
protected IEntity m_Worker;
|
||||
protected SCR_AIUtilityComponent m_Utility;
|
||||
protected int m_WorkerSlot;
|
||||
protected ref ERR_HQUnit m_Crew;
|
||||
protected ref ERR_HQUnit m_Donor;
|
||||
protected ref ERR_ForceRecord m_CrewRecord;
|
||||
protected ERR_InfantryResupply m_Service;
|
||||
protected ERR_ConvoyTask m_Task;
|
||||
protected ERR_ConvoyVehicle m_Truck;
|
||||
protected IEntity m_Item;
|
||||
protected vector m_CachePosition;
|
||||
protected vector m_TruckPosition;
|
||||
protected ref ERR_HQRoute m_Order;
|
||||
protected ref SCR_AIBehaviorBase m_Action;
|
||||
protected ref ERR_GroundDepotTransfer m_Move;
|
||||
protected ref ERR_FiniteMagazineReservation m_Reservation;
|
||||
protected bool m_PickedUp;
|
||||
protected bool m_DeliveryClaimed;
|
||||
protected bool m_Imported;
|
||||
protected bool m_MineCargo;
|
||||
bool MineCargo() { return m_MineCargo; }
|
||||
void ERR_GroundDepotLoading(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; m_Mode = mode; }
|
||||
bool Busy() { return m_State != 0; }
|
||||
bool Unresolved() { return m_Move && m_Move.Unresolved(); }
|
||||
string Status() { return string.Format("Ground depot: one job, state=%1; delivered=%2; attempts=%3/96; original sources=%4", m_State, m_Delivered, m_Attempts, m_Original.Count()); }
|
||||
protected bool Active()
|
||||
{
|
||||
return !m_Stopped && Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active() && m_Mode.Command() == m_HQ;
|
||||
}
|
||||
protected void Note(string reason)
|
||||
{
|
||||
if (m_HQ) m_HQ.Journal().Write("GROUND DEPOT", reason, m_Token);
|
||||
}
|
||||
protected static bool Present(IEntity entity)
|
||||
{
|
||||
if (!entity) return false;
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(entity.FindComponent(DamageManagerComponent));
|
||||
return !damage || !damage.IsDestroyed();
|
||||
}
|
||||
protected bool Stationary()
|
||||
{
|
||||
if (!m_Truck || !m_Truck.Entity || !m_Truck.Entity.GetPhysics()) return false;
|
||||
Physics physics = m_Truck.Entity.GetPhysics();
|
||||
float speed = physics.GetVelocity().Length(); float angular = physics.GetAngularVelocity().Length();
|
||||
return speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1;
|
||||
}
|
||||
protected bool Quiet(ERR_HQUnit unit)
|
||||
{
|
||||
return unit && unit.Group && unit.Utility && unit.StatusSampler && !unit.Group.IsSlave()
|
||||
&& unit.Group.GetPlayerCount(true) == 0 && unit.Group.GetFaction() == m_Mode.EnemyFaction()
|
||||
&& (!unit.Utility.m_Perception || unit.Utility.m_Perception.m_aTargets.IsEmpty());
|
||||
}
|
||||
protected bool WorkerValid()
|
||||
{
|
||||
if (!Quiet(m_Crew) || !m_Worker || !m_Utility || !m_Utility.m_AIInfo || !ERR_Actors.CanFight(m_Worker)) return false;
|
||||
if (!m_Crew.StatusSampler.OwnsRoster(m_Crew.Group) || !m_Crew.StatusSampler.CanAttribute(m_WorkerSlot, m_Worker, false)) return false;
|
||||
if (!ERR_EnemyEquipmentRules.Eligible(m_Mode, m_Crew.Group, m_Worker) || CompartmentAccessComponent.GetVehicleIn(m_Worker)) return false;
|
||||
SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(m_Worker));
|
||||
return agent && agent.m_UtilityComponent == m_Utility && m_CrewRecord && m_Mode.Forces().FindGroup(m_Crew.Group) == m_CrewRecord
|
||||
&& m_CrewRecord.Physical && !m_CrewRecord.Eliminated;
|
||||
}
|
||||
protected bool Valid()
|
||||
{
|
||||
if (!ERR_GroundDepotTransfer.Cargo(m_Item, m_MineCargo)) return false;
|
||||
if (!Active() || !m_Service || m_Service.Task() != m_Task || !m_Service.DepotCurrent() || m_Service.DepotTruck() != m_Truck) return false;
|
||||
if (!m_Task || !m_Task.Receipt || !m_Task.Receipt.Consumed || m_Task.Vehicles.Count() != 6 || m_Task.Vehicles[1] != m_Truck) return false;
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Task);
|
||||
if (!supply || !supply.Tactics || supply.Tactics.State() != 0 || !m_Truck.Combat || m_Truck.Combat.Held) return false;
|
||||
if (!Quiet(m_Donor) || m_Donor.Group != m_Truck.Group || !m_HQ.ValidateBoundVehicle(m_Donor.Group, m_Truck.Entity)) return false;
|
||||
if (!m_Site || !m_Mode.Sites() || !m_Site.Definition || m_Mode.Sites().Find(m_Site.Definition.Id) != m_Site) return false;
|
||||
if (m_Site.Container != m_Cache || !Present(m_Cache) || m_Cache.FindComponent(InventoryStorageManagerComponent) != m_CacheInventory) return false;
|
||||
if (!m_Site.Responders || m_Site.Responders.Group != m_Crew.Group || !m_Mode.Sites().DepotOriginal(m_Site, m_Item)) return false;
|
||||
if (vector.Distance(m_Cache.GetOrigin(), m_CachePosition) > 2 || !WorkerValid()) return false;
|
||||
return m_Token > 300000 && m_Truck.SupplyToken == m_Token && m_Crew.LogisticsReservation == m_Token && m_Donor.LogisticsReservation == m_Token;
|
||||
}
|
||||
protected void Capture()
|
||||
{
|
||||
if (m_Captured || !m_Mode.Sites()) return;
|
||||
m_Captured = true;
|
||||
for (int i = 0; i < m_Mode.Sites().Count() && i < 64; i++)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().At(i);
|
||||
array<IEntity> originals = {}; m_Mode.Sites().DepotStock(site, originals);
|
||||
foreach (IEntity item : originals)
|
||||
{
|
||||
if (m_Original.Count() >= 96) return;
|
||||
if (item && !m_Original.Contains(item)) m_Original.Insert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected bool Stored(IEntity item, IEntity owner)
|
||||
{
|
||||
if (!item || !owner || !ERR_InfantryAmmoTransfer.StoredUnder(item, owner)) return false;
|
||||
InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
if (!carried || !carried.GetParentSlot() || carried.GetParentSlot().GetAttachedEntity() != item) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory || inventory.GetOwner() != owner) return false;
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
return items.Count() <= 128 && items.Contains(item);
|
||||
}
|
||||
protected bool SelectWorker(ERR_HQUnit crew, IEntity item, bool mineCargo = false)
|
||||
{
|
||||
if (!item || !Quiet(crew) || crew.HomeGuard || crew.ReservedForSupport || crew.LogisticsReservation > 0) return false;
|
||||
if (crew.Assignment || crew.Task || crew.PendingTask || crew.PendingOrder || crew.Downlink || crew.Waypoint) return false;
|
||||
int count = crew.StatusSampler.InitialStrength();
|
||||
if (count < 1 || count > 32 || !crew.StatusSampler.OwnsRoster(crew.Group)) return false;
|
||||
for (int slot = 0; slot < count; slot++)
|
||||
{
|
||||
IEntity actor = crew.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !crew.StatusSampler.CanAttribute(slot, actor, false) || !ERR_EnemyEquipmentRules.Eligible(m_Mode, crew.Group, actor) || CompartmentAccessComponent.GetVehicleIn(actor)) continue;
|
||||
SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(actor));
|
||||
if (!agent || !agent.m_UtilityComponent || !agent.m_UtilityComponent.m_AIInfo) continue;
|
||||
if (!mineCargo && !ERR_InfantryAmmoTransfer.Compatible(actor, item)) continue;
|
||||
m_Worker = actor; m_WorkerSlot = slot; m_Utility = agent.m_UtilityComponent; return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Plan(float now)
|
||||
{
|
||||
if (!Active() || Busy() || !ERR_ForceRules.Finite(now) || now < m_NextPlan || m_Attempts >= 96) return;
|
||||
m_NextPlan = now + 5000; Capture();
|
||||
for (int index = 0; index < m_HQ.GroundSupplyCount() && index < 20; index++)
|
||||
{
|
||||
ERR_InfantryResupply service = m_HQ.GroundSupplyAt(index);
|
||||
if (!service || (!service.DepotNeeded() && !service.DepotMineNeeded())) continue;
|
||||
ERR_ConvoyVehicle truck = service.DepotTruck();
|
||||
if (!truck || truck.SupplyToken > 0) continue;
|
||||
ERR_HQUnit donor = m_HQ.GroundUnit(truck.Group);
|
||||
if (!Quiet(donor)) continue;
|
||||
ERR_HQWatchEntry report = m_HQ.Watch().Find(donor.ForceSourceId);
|
||||
if (!ERR_InfantryResupplyRules.Fresh(report, now)) continue;
|
||||
for (int siteIndex = 0; siteIndex < m_Mode.Sites().Count() && siteIndex < 64; siteIndex++)
|
||||
{
|
||||
ERR_SiteRuntime site = m_Mode.Sites().At(siteIndex);
|
||||
if (!site || !site.Definition || m_Mode.Sites().DepotItemCount(site) <= 0) continue;
|
||||
// The camp is an authored own location; only the truck position is reported.
|
||||
if (vector.DistanceXZ(site.Definition.Position, report.Position) > 150) continue;
|
||||
ERR_HQUnit crew = m_HQ.GroundUnit(site.Responders.Group);
|
||||
for (int itemIndex = 0; itemIndex < m_Mode.Sites().DepotItemCount(site) && itemIndex < 96; itemIndex++)
|
||||
{
|
||||
IEntity item = m_Mode.Sites().DepotItem(site, itemIndex);
|
||||
bool mineCargo = ERR_InfantryMineTransfer.ReadyMine(item);
|
||||
if (mineCargo) { if (!service.DepotMineNeeded()) continue; }
|
||||
else if (!service.DepotNeeded()) continue;
|
||||
if (!m_Original.Contains(item) || m_Spent.Contains(item) || !ERR_GroundDepotTransfer.Cargo(item, mineCargo) || !Stored(item, site.Container)) continue;
|
||||
// Select an original worker for this exact item; an incompatible first
|
||||
// member must not hide a later eligible carrier of finite camp stock.
|
||||
if (!SelectWorker(crew, item, mineCargo)) continue;
|
||||
int token = 300000 + m_Attempts + 1;
|
||||
if (!m_HQ.ReserveGroundDepot(crew, donor, service, token, mineCargo)) continue;
|
||||
m_Reservation = new ERR_FiniteMagazineReservation(m_Original, m_Spent, item);
|
||||
if (!m_Reservation.Reserve()) { m_HQ.ReleaseGroundDepot(crew, donor, truck, token); continue; }
|
||||
m_MineCargo = mineCargo;
|
||||
m_Attempts++; m_Token = token; m_Crew = crew; m_Donor = donor; m_Service = service; m_Task = service.Task(); m_Truck = truck;
|
||||
m_Site = site; m_Cache = site.Container; m_CachePosition = m_Cache.GetOrigin(); m_Item = item;
|
||||
m_CacheInventory = InventoryStorageManagerComponent.Cast(m_Cache.FindComponent(InventoryStorageManagerComponent));
|
||||
m_CrewRecord = m_Mode.Forces().FindGroup(crew.Group);
|
||||
m_PickedUp = false; m_DeliveryClaimed = false; m_Imported = false; m_HeldAt = -1;
|
||||
m_Deadline = Math.Min(now + 180000, report.ObservedAt + 240000); m_State = 1;
|
||||
m_Order = m_HQ.Downlink(donor.Group, "DEPOT HOLD", "hold original truck for one finite camp item", report.MessageId);
|
||||
if (!m_Order) Abort("truck radio unavailable"); else Note("one original camp item reserved; awaiting truck hold radio");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected void ClearAction()
|
||||
{
|
||||
if (m_Action && m_Worker && m_Utility && m_Utility.m_AIInfo)
|
||||
{
|
||||
SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(m_Worker));
|
||||
if (agent && agent.m_UtilityComponent == m_Utility)
|
||||
{
|
||||
array<ref AIActionBase> actions = {}; m_Utility.GetActions(actions);
|
||||
if (actions.Count() <= 128 && actions.Contains(m_Action)) m_Action.Complete();
|
||||
}
|
||||
}
|
||||
m_Action = null;
|
||||
}
|
||||
protected bool Walk(vector position)
|
||||
{
|
||||
if (!WorkerValid() || !ERR_ForceRules.FiniteVector(position)) return false;
|
||||
ClearAction(); m_Action = new SCR_AIMoveIndividuallyBehavior(m_Utility, null, ERR_Actors.Ground(position), 1000, 0, null, 0.5);
|
||||
m_Utility.AddAction(m_Action); return true;
|
||||
}
|
||||
protected void Cleanup()
|
||||
{
|
||||
ClearAction();
|
||||
if (m_Reservation) m_Reservation.ReleaseUnsubmitted();
|
||||
if (m_HQ) m_HQ.ReleaseGroundDepot(m_Crew, m_Donor, m_Truck, m_Token);
|
||||
m_State = 0; m_MineCargo = false; m_Token = 0; m_Order = null; m_Move = null; m_Reservation = null;
|
||||
m_Crew = null; m_Donor = null; m_Service = null; m_Task = null; m_Truck = null;
|
||||
m_Worker = null; m_Utility = null; m_Site = null; m_Cache = null; m_Item = null; m_CacheInventory = null; m_CrewRecord = null;
|
||||
}
|
||||
protected void Abort(string reason)
|
||||
{
|
||||
Note(reason); ClearAction(); m_Order = null;
|
||||
if (m_Move) m_Move.Stop();
|
||||
if (Unresolved()) { m_State = 7; return; }
|
||||
Cleanup();
|
||||
}
|
||||
void Stop() { if (m_Stopped) return; m_Stopped = true; Abort("depot service stopped; any submitted uncertainty retains original claims"); }
|
||||
bool TransferValid(ERR_GroundDepotTransfer operation)
|
||||
{
|
||||
if (!operation || operation != m_Move || operation.Item() != m_Item || operation.MineCargo() != m_MineCargo || !Valid() || !Stationary() || !m_Truck.SupplyHeld) return false;
|
||||
if (operation.Delivery()) return m_PickedUp && m_State == 5 && ERR_GroundDepotAccess.Clear(m_Truck.Entity, m_Worker);
|
||||
return !m_PickedUp && m_State == 4 && ERR_GroundDepotAccess.Clear(m_Cache, m_Worker);
|
||||
}
|
||||
bool ClaimDelivery(ERR_GroundDepotTransfer operation)
|
||||
{
|
||||
if (!TransferValid(operation) || !operation.Delivery() || m_DeliveryClaimed || !m_Reservation.CommittedFor(m_Item)) return false;
|
||||
if (m_MineCargo) { if (!m_Service.DepotMineNeeded()) return false; }
|
||||
else if (!m_Service.DepotNeeded()) return false;
|
||||
m_DeliveryClaimed = true; return true;
|
||||
}
|
||||
bool DeliveredTo(ERR_InfantryResupply service, IEntity item, bool mineCargo = false)
|
||||
{
|
||||
return mineCargo == m_MineCargo && !m_Imported && m_State == 5 && service == m_Service && item == m_Item && m_Move && m_Move.Delivery() && m_Move.MineCargo() == m_MineCargo
|
||||
&& m_Move.Confirmed() && m_Reservation && m_Reservation.CommittedFor(item) && Valid();
|
||||
}
|
||||
void Tick(float now)
|
||||
{
|
||||
// Terminal proof only: a late callback cannot resume walking or admit stock.
|
||||
if (m_State == 7) { if (!Unresolved()) Cleanup(); return; }
|
||||
if (!Busy()) return;
|
||||
if (!ERR_ForceRules.Finite(now) || now < m_Last || now >= m_Deadline || !Valid()) { Abort("depot deadline or original ownership lost"); return; }
|
||||
m_Last = now;
|
||||
if (now < m_NextTick) return;
|
||||
m_NextTick = now + 1000;
|
||||
if (m_State == 1 || m_State == 3)
|
||||
{
|
||||
int result = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Abort("depot radio interrupted"); return; }
|
||||
m_Order = null;
|
||||
if (m_State == 1) { m_Truck.SupplyHeld = true; m_Truck.ClearOrder(); m_State = 2; return; }
|
||||
if (!Walk(m_CachePosition + "2 0 0")) { Abort("original porter cannot walk to camp cache"); return; }
|
||||
m_State = 4; return;
|
||||
}
|
||||
if (m_State == 2)
|
||||
{
|
||||
if (!Stationary()) return;
|
||||
if (m_HeldAt < 0) { m_HeldAt = now; m_Donor.NextStatus = now; return; }
|
||||
ERR_HQWatchEntry report = m_HQ.Watch().Find(m_Donor.ForceSourceId);
|
||||
if (!ERR_InfantryResupplyRules.Fresh(report, now) || report.ObservedAt < m_HeldAt) return;
|
||||
if (vector.DistanceXZ(report.Position, m_Site.Definition.Position) > 150) { Abort("reported stopped truck outside camp service range"); return; }
|
||||
m_TruckPosition = report.Position + "3 0 0";
|
||||
m_Order = m_HQ.Downlink(m_Crew.Group, "DEPOT COURIER", string.Format("carry one existing item from camp to stopped truck at %1", m_TruckPosition), report.MessageId);
|
||||
if (!m_Order) { Abort("porter radio unavailable"); return; }
|
||||
m_State = 3; return;
|
||||
}
|
||||
if (m_State == 6)
|
||||
{
|
||||
if (vector.DistanceXZ(m_Worker.GetOrigin(), m_CachePosition) <= 5
|
||||
&& vector.DistanceXZ(m_Worker.GetOrigin(), m_Truck.Entity.GetOrigin()) >= 6) Cleanup();
|
||||
return;
|
||||
}
|
||||
if (!Stationary()) { Abort("held truck moved during physical loading"); return; }
|
||||
if (!m_Move)
|
||||
{
|
||||
IEntity source = m_Cache; IEntity destination = m_Worker;
|
||||
bool delivery = m_State == 5;
|
||||
if (delivery) { source = m_Worker; destination = m_Truck.Entity; }
|
||||
IEntity access = m_Cache; if (delivery) access = m_Truck.Entity;
|
||||
if (!ERR_GroundDepotAccess.Clear(access, m_Worker)) return;
|
||||
m_Move = new ERR_GroundDepotTransfer(this, source, destination, m_Item, m_Reservation, delivery, m_MineCargo);
|
||||
}
|
||||
int moved = m_Move.Tick(now);
|
||||
if (moved == 0) return;
|
||||
if (moved < 0) { Abort("native depot move refused, changed or expired; no submitted retry"); return; }
|
||||
if (m_State == 4)
|
||||
{
|
||||
m_PickedUp = true; m_Move = null; // Retire first-leg proof before custody changes again.
|
||||
if (!Walk(m_TruckPosition)) { Abort("porter cannot walk to reported truck"); return; }
|
||||
m_State = 5; return;
|
||||
}
|
||||
bool admitted;
|
||||
if (m_MineCargo) admitted = m_Service.AdmitDepotMine(this, m_Item);
|
||||
else admitted = m_Service.AdmitDepot(this, m_Item);
|
||||
if (!admitted) { Abort("proved physical delivery could not enter finite truck allowance"); return; }
|
||||
m_Imported = true; m_Delivered++; m_Move = null;
|
||||
Note("one original camp item physically delivered and admitted; porter returning to camp");
|
||||
if (!Walk(m_CachePosition + "2 0 0")) { Cleanup(); return; }
|
||||
m_State = 6;
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
class ERR_GroundDepotCallback : ScriptedInventoryOperationCallback
|
||||
{
|
||||
ERR_GroundDepotTransfer Transfer;
|
||||
protected override void OnComplete() { if (Transfer) Transfer.Acknowledge(true); }
|
||||
protected override void OnAllComplete() { if (Transfer) Transfer.Acknowledge(true); }
|
||||
protected override void OnFailed() { if (Transfer) Transfer.Acknowledge(false); }
|
||||
protected override void OnAllFailed() { if (Transfer) Transfer.Acknowledge(false); }
|
||||
}
|
||||
|
||||
// One exact native move. Its owner retains the leaf until uncertain custody
|
||||
// settles; pickup and delivery never share callback state.
|
||||
class ERR_GroundDepotTransfer
|
||||
{
|
||||
protected ERR_GroundDepotLoading m_Owner;
|
||||
protected IEntity m_From;
|
||||
protected IEntity m_To;
|
||||
protected IEntity m_Item;
|
||||
protected InventoryStorageManagerComponent m_Source;
|
||||
protected InventoryStorageManagerComponent m_Destination;
|
||||
protected InventoryStorageSlot m_FromSlot;
|
||||
protected BaseInventoryStorageComponent m_FromStorage;
|
||||
protected BaseInventoryStorageComponent m_ToStorage;
|
||||
protected ref ERR_FiniteMagazineReservation m_Reservation;
|
||||
protected ref ERR_GroundDepotCallback m_Callback;
|
||||
protected bool m_Delivery;
|
||||
protected bool m_MineCargo;
|
||||
protected bool m_Submitted;
|
||||
protected int m_Ack;
|
||||
protected int m_State;
|
||||
protected int m_Rounds;
|
||||
protected int m_Capacity;
|
||||
protected float m_Started = -1;
|
||||
protected float m_Last = -1;
|
||||
void ERR_GroundDepotTransfer(ERR_GroundDepotLoading owner, IEntity source, IEntity destination, IEntity item, ERR_FiniteMagazineReservation reservation, bool delivery, bool mineCargo = false)
|
||||
{
|
||||
m_Owner = owner; m_From = source; m_To = destination; m_Item = item; m_Reservation = reservation; m_Delivery = delivery; m_MineCargo = mineCargo;
|
||||
if (!source || !destination || !item) return;
|
||||
m_Source = InventoryStorageManagerComponent.Cast(source.FindComponent(InventoryStorageManagerComponent));
|
||||
m_Destination = InventoryStorageManagerComponent.Cast(destination.FindComponent(InventoryStorageManagerComponent));
|
||||
InventoryItemComponent inventoryItem = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
if (inventoryItem) m_FromSlot = inventoryItem.GetParentSlot();
|
||||
if (m_FromSlot) m_FromStorage = m_FromSlot.GetStorage();
|
||||
BaseMagazineComponent magazine = BaseMagazineComponent.Cast(item.FindComponent(BaseMagazineComponent));
|
||||
if (magazine) { m_Rounds = magazine.GetAmmoCount(); m_Capacity = magazine.GetMaxAmmoCount(); }
|
||||
}
|
||||
static bool Magazine(IEntity item)
|
||||
{
|
||||
if (!item) return false;
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(item.FindComponent(DamageManagerComponent));
|
||||
if (damage && damage.IsDestroyed()) return false;
|
||||
BaseMagazineComponent magazine = BaseMagazineComponent.Cast(item.FindComponent(BaseMagazineComponent));
|
||||
return magazine && !magazine.IsUsed() && magazine.GetMagazineWell() && magazine.GetAmmoCount() > 0
|
||||
&& magazine.GetAmmoCount() <= magazine.GetMaxAmmoCount() && magazine.GetMaxAmmoCount() <= 100000;
|
||||
}
|
||||
static bool Cargo(IEntity item, bool mineCargo = false)
|
||||
{
|
||||
if (mineCargo) return ERR_InfantryMineTransfer.ReadyMine(item);
|
||||
return Magazine(item);
|
||||
}
|
||||
protected bool CargoUnchanged()
|
||||
{
|
||||
if (!Cargo(m_Item, m_MineCargo)) return false;
|
||||
if (m_MineCargo) return true;
|
||||
BaseMagazineComponent magazine = BaseMagazineComponent.Cast(m_Item.FindComponent(BaseMagazineComponent));
|
||||
return magazine.GetAmmoCount() == m_Rounds && magazine.GetMaxAmmoCount() == m_Capacity;
|
||||
}
|
||||
bool MineCargo() { return m_MineCargo; }
|
||||
bool Submitted() { return m_Submitted; }
|
||||
bool Delivery() { return m_Delivery; }
|
||||
IEntity Item() { return m_Item; }
|
||||
void Acknowledge(bool success)
|
||||
{
|
||||
if (!m_Submitted) return;
|
||||
if (!success) m_Ack = -1;
|
||||
else if (m_Ack == 0) m_Ack = 1;
|
||||
}
|
||||
protected bool StorageManaged(InventoryStorageManagerComponent inventory, BaseInventoryStorageComponent storage, IEntity owner)
|
||||
{
|
||||
if (!inventory || !storage || !owner || inventory.GetOwner() != owner) return false;
|
||||
if (!ERR_InfantryAmmoTransfer.StoredUnder(storage.GetOwner(), owner)) return false;
|
||||
array<BaseInventoryStorageComponent> storages = {}; inventory.GetStorages(storages, EStoragePurpose.PURPOSE_DEPOSIT);
|
||||
return storages.Count() <= 64 && storages.Contains(storage);
|
||||
}
|
||||
protected int Contains(InventoryStorageManagerComponent inventory)
|
||||
{
|
||||
if (!inventory || !m_Item) return -1;
|
||||
array<IEntity> items = {}; inventory.GetItems(items, EStoragePurpose.PURPOSE_DEPOSIT);
|
||||
if (items.Count() > 128) return -1;
|
||||
if (items.Contains(m_Item)) return 1;
|
||||
return 0;
|
||||
}
|
||||
protected bool Slot(InventoryStorageSlot slot)
|
||||
{
|
||||
if (!m_Item || !slot || slot.GetAttachedEntity() != m_Item) return false;
|
||||
InventoryItemComponent item = InventoryItemComponent.Cast(m_Item.FindComponent(InventoryItemComponent));
|
||||
return item && item.GetParentSlot() == slot;
|
||||
}
|
||||
protected bool OriginalProof()
|
||||
{
|
||||
return m_FromSlot && m_FromSlot.GetStorage() == m_FromStorage && StorageManaged(m_Source, m_FromStorage, m_From)
|
||||
&& Slot(m_FromSlot) && m_Destination && m_Destination.GetOwner() == m_To
|
||||
&& Contains(m_Source) == 1 && Contains(m_Destination) == 0;
|
||||
}
|
||||
bool PhysicalProof()
|
||||
{
|
||||
if (!m_Item || !m_Source || !m_From || m_Source.GetOwner() != m_From) return false;
|
||||
if (!StorageManaged(m_Destination, m_ToStorage, m_To) || Contains(m_Source) != 0 || Contains(m_Destination) != 1) return false;
|
||||
InventoryItemComponent item = InventoryItemComponent.Cast(m_Item.FindComponent(InventoryItemComponent));
|
||||
return item && item.GetParentSlot() && item.GetParentSlot().GetStorage() == m_ToStorage && Slot(item.GetParentSlot());
|
||||
}
|
||||
bool Unresolved()
|
||||
{
|
||||
if (!m_Submitted || !m_Item) return false;
|
||||
if (m_Ack == 1 && PhysicalProof()) return false;
|
||||
if (m_Ack < 0 && OriginalProof()) return false;
|
||||
return true;
|
||||
}
|
||||
void Stop() { if (m_State == 0) m_State = -1; }
|
||||
bool Confirmed() { return m_State == 1 && m_Ack == 1 && CargoUnchanged() && PhysicalProof(); }
|
||||
int Tick(float now)
|
||||
{
|
||||
if (m_State != 0) return m_State;
|
||||
if (!ERR_ForceRules.Finite(now) || now < 0 || now < m_Last) { Stop(); return m_State; }
|
||||
if (m_Started < 0) m_Started = now;
|
||||
m_Last = now;
|
||||
if (now - m_Started >= 8000 || !m_Owner || !m_Owner.TransferValid(this) || !CargoUnchanged()) { Stop(); return m_State; }
|
||||
if (!m_From || !m_To || m_From.FindComponent(InventoryStorageManagerComponent) != m_Source
|
||||
|| m_To.FindComponent(InventoryStorageManagerComponent) != m_Destination) { Stop(); return m_State; }
|
||||
if (!m_Submitted)
|
||||
{
|
||||
if (!m_Reservation || !OriginalProof()) { Stop(); return m_State; }
|
||||
m_ToStorage = m_Destination.FindStorageForItem(m_Item, EStoragePurpose.PURPOSE_DEPOSIT);
|
||||
if (!StorageManaged(m_Destination, m_ToStorage, m_To) || !m_Source.CanMoveItemToStorage(m_Item, m_ToStorage, -1)) { Stop(); return m_State; }
|
||||
if (!m_Delivery && !m_Reservation.Commit()) { Stop(); return m_State; }
|
||||
if (!m_Reservation.CommittedFor(m_Item)) { Stop(); return m_State; }
|
||||
if (m_Delivery && !m_Owner.ClaimDelivery(this)) { Stop(); return m_State; }
|
||||
m_Callback = new ERR_GroundDepotCallback(); m_Callback.Transfer = this;
|
||||
m_Submitted = true;
|
||||
bool accepted = m_Source.TryMoveItemToStorage(m_Item, m_ToStorage, -1, m_Callback);
|
||||
if (!accepted && m_Ack != 1) { Stop(); return m_State; }
|
||||
}
|
||||
// Native callbacks may synchronously cancel the owner or this exact leaf.
|
||||
if (m_State != 0) return m_State;
|
||||
if (!m_Owner || !m_Owner.TransferValid(this) || !CargoUnchanged()) { Stop(); return m_State; }
|
||||
if (m_Ack < 0) { Stop(); return m_State; }
|
||||
if (m_Ack == 1 && PhysicalProof()) m_State = 1;
|
||||
return m_State;
|
||||
}
|
||||
}
|
||||
+592
@@ -0,0 +1,592 @@
|
||||
// HQ-owned ground rendezvous using delivered positions and existing finite cargo.
|
||||
class ERR_InfantryResupplyRules
|
||||
{
|
||||
static bool Fresh(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return entry && !entry.Closed && entry.Count > 0 && entry.Fit > 0
|
||||
&& ERR_ForceRules.Finite(now) && entry.ObservedAt >= 0 && now >= entry.ObservedAt
|
||||
&& now - entry.ObservedAt <= 120000 && ERR_ForceRules.FiniteVector(entry.Position);
|
||||
}
|
||||
static bool Need(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.Complete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.SmallArmsMuzzles > 0
|
||||
&& entry.AmmoState.SmallArmsRounds + entry.AmmoState.SmallArmsChambers <= entry.Count * 30;
|
||||
}
|
||||
// Only positively sampled reloadable magazine-well muzzles establish launcher demand.
|
||||
static bool LauncherNeed(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.LauncherComplete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.LauncherMuzzles > 0
|
||||
&& entry.AmmoState.LauncherRounds == 0 && entry.AmmoState.LauncherChambers == 0;
|
||||
}
|
||||
static bool LauncherPair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return LauncherNeed(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool MinePair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Fresh(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& recipient.AmmoState && recipient.AmmoState.Valid(recipient.Count)
|
||||
&& recipient.AmmoState.MineComplete && recipient.AmmoState.MineMembers == recipient.Count
|
||||
&& recipient.AmmoState.ReadyMines <= 1 && vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool Pair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Need(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_InfantryResupply
|
||||
{
|
||||
protected ERR_HQ m_HQ;
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ERR_ConvoyTask m_Convoy;
|
||||
protected int m_ConvoySlot = -1;
|
||||
protected ERR_ConvoyVehicle m_Truck;
|
||||
protected ERR_HQUnit m_Recipient;
|
||||
protected ERR_HQUnit m_Donor;
|
||||
protected ref array<IEntity> m_Stock = {};
|
||||
protected ref array<IEntity> m_Spent = {};
|
||||
protected ref array<IEntity> m_MineStock = {};
|
||||
protected ref ERR_ConvoyMineStock m_MineBatch;
|
||||
protected bool m_MineStockCaptured;
|
||||
protected bool m_MineTrip;
|
||||
protected bool m_LauncherTrip;
|
||||
protected int m_MineRecipientSlot = -1;
|
||||
protected bool m_EmptyMineReplacement;
|
||||
protected int m_MinesDelivered;
|
||||
protected ref array<IEntity> m_Members = {};
|
||||
protected ref array<IEntity> m_Served = {};
|
||||
protected ref map<string, int> m_Consumed = new map<string, int>();
|
||||
protected ref map<string, float> m_NextAttempt = new map<string, float>();
|
||||
protected ref ERR_HQRoute m_Order;
|
||||
protected ref ERR_InfantryAmmoTransfer m_Move;
|
||||
protected ref ERR_InfantryMineTransfer m_MineMove;
|
||||
protected ref ERR_MountedResupply m_Mounted;
|
||||
protected IEntity m_Receiving;
|
||||
protected AIWaypoint m_MoveWaypoint;
|
||||
protected AIWaypoint m_HoldWaypoint;
|
||||
protected vector m_Rendezvous;
|
||||
protected int m_State; // 0 stock startup, 1 idle, 2 truck downlink, 3 stopped status, 4 infantry downlink, 5 transfer, 7 unresolved item custody
|
||||
protected int m_Trip;
|
||||
protected int m_Token;
|
||||
protected int m_ReportId;
|
||||
protected int m_Delivered;
|
||||
protected int m_TripDelivered;
|
||||
protected float m_Deadline;
|
||||
protected float m_StockDeadline = -1;
|
||||
protected float m_HeldAt;
|
||||
protected float m_NextTick;
|
||||
protected bool m_Stopped;
|
||||
protected string m_Reason;
|
||||
void ERR_InfantryResupply(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; m_Mode = mode; }
|
||||
// Bind before startup; every coordinator retains its exact finite convoy identity.
|
||||
bool Bind(ERR_ConvoyTask task, int slot, map<string, int> consumed, map<string, float> nextAttempt)
|
||||
{
|
||||
if (!task || !consumed || !nextAttempt || !m_HQ || !m_HQ.Convoys() || slot < 0 || slot >= 20
|
||||
|| slot >= m_HQ.Convoys().Count() || m_HQ.Convoys().At(slot) != task) return false;
|
||||
if (m_Stopped || m_Convoy || m_ConvoySlot >= 0 || m_State != 0 || m_Trip != 0 || m_NextTick != 0
|
||||
|| m_StockDeadline >= 0 || !m_Stock.IsEmpty() || m_Move || m_Truck) return false;
|
||||
m_Convoy = task; m_ConvoySlot = slot; m_Consumed = consumed; m_NextAttempt = nextAttempt;
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyTask Task() { return m_Convoy; }
|
||||
int State()
|
||||
{
|
||||
if (m_Mounted && m_Mounted.Busy()) return 6;
|
||||
return m_State;
|
||||
}
|
||||
ERR_MountedResupply Mounted() { return m_Mounted; }
|
||||
bool Unresolved() { return (m_Move && m_Move.Unresolved()) || (m_MineMove && m_MineMove.Unresolved()) || (m_Mounted && m_Mounted.Unresolved()); }
|
||||
protected void PollTransfers(float now)
|
||||
{
|
||||
if (m_Mounted) m_Mounted.Tick(now);
|
||||
if (m_Move && !m_Move.Unresolved() && (m_State <= 1 || (m_State == 7 && m_LauncherTrip)))
|
||||
{
|
||||
m_Move = null;
|
||||
if (m_State == 7) Finish("launcher custody settled; original claims released without retry or refund");
|
||||
}
|
||||
if (m_MineMove && !m_MineMove.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
m_MineMove = null;
|
||||
if (m_State == 7) Finish("mine custody settled; original claims released without retry or refund");
|
||||
}
|
||||
}
|
||||
int Delivered() { return m_Delivered; }
|
||||
int MinesDelivered() { return m_MinesDelivered; }
|
||||
int StockCount() { return m_Stock.Count(); }
|
||||
// Admission uses the existing array object so an already-created mounted
|
||||
// coordinator observes this exact finite addition without a replacement ledger.
|
||||
protected int m_DepotImports;
|
||||
protected int m_DepotMineImports;
|
||||
bool DepotCurrent()
|
||||
{
|
||||
return Current() && m_State == 1 && !m_Move && !m_MineMove && !Unresolved()
|
||||
&& (!m_Mounted || !m_Mounted.Busy()) && TruckValid(true);
|
||||
}
|
||||
bool DepotAvailable() { return DepotCurrent() && m_Stock.Count() < 96 && m_Spent.Count() < 96; }
|
||||
bool DepotNeeded()
|
||||
{
|
||||
if (!DepotAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_Stock.Contains(item)) committed++;
|
||||
return committed > m_DepotImports;
|
||||
}
|
||||
// Mine imports replace only proved outgoing original mine commitments.
|
||||
// Keep the startup batch binding and both lifetime identity/spent ceilings.
|
||||
bool DepotMineAvailable()
|
||||
{
|
||||
return DepotCurrent() && CaptureMines() && m_MineStock.Count() < 96 && m_Spent.Count() < 96;
|
||||
}
|
||||
bool DepotMineNeeded()
|
||||
{
|
||||
if (!DepotMineAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_MineStock.Contains(item)) committed++;
|
||||
return committed > m_DepotMineImports;
|
||||
}
|
||||
bool AdmitDepotMine(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotMineNeeded() || !ERR_InfantryMineTransfer.ReadyMine(item)
|
||||
|| m_MineStock.Contains(item) || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item, true) || !Contains(m_Truck.Entity, item)
|
||||
|| !ERR_InfantryAmmoTransfer.StoredUnder(item, m_Truck.Entity)) return false;
|
||||
InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
if (!carried || !carried.GetParentSlot() || carried.GetParentSlot().GetAttachedEntity() != item) return false;
|
||||
m_MineStock.Insert(item); m_DepotMineImports++;
|
||||
Audit("one exact finite camp PMN4 admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyVehicle DepotTruck()
|
||||
{
|
||||
if (!DepotCurrent()) return null;
|
||||
return m_Truck;
|
||||
}
|
||||
bool AdmitDepot(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotAvailable() || !item || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item) || !Contains(m_Truck.Entity, item)) return false;
|
||||
m_Stock.Insert(item); m_DepotImports++; Audit("one exact finite camp magazine admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void Audit(string reason)
|
||||
{
|
||||
if (m_MineTrip) reason = "mine top-up: " + reason;
|
||||
if (m_LauncherTrip) reason = "depleted launcher magazine: " + reason;
|
||||
m_Reason = reason;
|
||||
m_HQ.Journal().Write("INFANTRY SUPPLY", string.Format("convoy-slot=%1 trip=%2 state=%3 moved=%4 spent=%5/%6; %7", m_ConvoySlot, m_Trip, m_State, m_Delivered, m_Spent.Count(), m_Stock.Count(), reason), m_ReportId);
|
||||
}
|
||||
protected bool Current()
|
||||
{
|
||||
return !m_Stopped && Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active();
|
||||
}
|
||||
protected bool Contains(IEntity owner, IEntity item)
|
||||
{
|
||||
if (!owner || !item) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) return false;
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
return items.Count() <= 128 && items.Contains(item);
|
||||
}
|
||||
protected bool ConvoyCurrent()
|
||||
{
|
||||
if (!m_HQ || !m_Convoy) return false;
|
||||
if (m_ConvoySlot < 0) return m_HQ.ConvoyTask() == m_Convoy;
|
||||
return m_HQ.Convoys() && m_ConvoySlot < m_HQ.Convoys().Count() && m_HQ.Convoys().At(m_ConvoySlot) == m_Convoy;
|
||||
}
|
||||
protected bool TruckValid(bool allowArrived = false)
|
||||
{
|
||||
if (!m_Convoy || m_Convoy.Stopped || !m_Convoy.Ready || !m_Convoy.Receipt || !m_Convoy.Receipt.Consumed
|
||||
|| !ConvoyCurrent() || m_Convoy.Vehicles.Count() != 6 || m_Convoy.Vehicles[1] != m_Truck) return false;
|
||||
if (!m_Truck || m_Truck.Index != 1 || !m_Truck.Registered || m_Truck.Released || (m_Truck.Arrived && !allowArrived)
|
||||
|| !m_Truck.CrewValid(m_Mode) || ERR_ConvoyRules.Captured(m_Truck.Entity, m_Truck.Group)) return false;
|
||||
ERR_ForceRecord record = m_Mode.Forces().FindGroup(m_Truck.Group);
|
||||
return record && record.Physical && !record.Eliminated && record.Kind == ERR_ForceKind.CONVOY
|
||||
&& m_Convoy.Receipt.Records.Count() >= 6 && record.Id == m_Convoy.Receipt.Records[1];
|
||||
}
|
||||
protected bool Quiet(ERR_HQUnit unit)
|
||||
{
|
||||
return unit && unit.Group && unit.Utility && !unit.Group.IsSlave() && unit.Group.GetPlayerCount(true) == 0
|
||||
&& unit.Group.GetFaction() == m_Mode.EnemyFaction()
|
||||
&& (!unit.Utility.m_Perception || unit.Utility.m_Perception.m_aTargets.IsEmpty());
|
||||
}
|
||||
protected bool Roster()
|
||||
{
|
||||
if (!m_Recipient || !Quiet(m_Recipient) || !m_Recipient.StatusSampler.OwnsRoster(m_Recipient.Group)) return false;
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
array<AIAgent> agents = {}; m_Recipient.Group.GetAgents(agents);
|
||||
if (agents.IsEmpty() || agents.Count() > 32) return false;
|
||||
foreach (AIAgent agent : agents)
|
||||
if (!agent || !m_Members.Contains(agent.GetControlledEntity())) return false;
|
||||
bool living;
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!actor || !ERR_Actors.Alive(actor)) continue;
|
||||
// Returning to the group cannot undo a sampler's permanent release of an
|
||||
// original slot after transfer or player control during this trip.
|
||||
bool attributed = false;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (m_Recipient.StatusSampler.InitialMember(slot) != actor) continue;
|
||||
attributed = m_Recipient.StatusSampler.CanAttribute(slot, actor);
|
||||
break;
|
||||
}
|
||||
if (!attributed) return false;
|
||||
if (ERR_Actors.Player(actor) || ERR_Actors.Group(actor) != m_Recipient.Group
|
||||
|| SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction() || CompartmentAccessComponent.GetVehicleIn(actor)) return false;
|
||||
if (ERR_Actors.CanFight(actor)) living = true;
|
||||
}
|
||||
return living;
|
||||
}
|
||||
protected void Stock(float now)
|
||||
{
|
||||
if (!m_Convoy) m_Convoy = m_HQ.ConvoyTask();
|
||||
if (m_Convoy && !ConvoyCurrent()) { Stop(); return; }
|
||||
if (!m_Convoy || !m_Convoy.Ready || m_Convoy.Vehicles.Count() != 6) return;
|
||||
m_Truck = m_Convoy.Vehicles[1];
|
||||
if (!TruckValid()) { Stop(); return; }
|
||||
// Cargo has a later, separately bounded lifecycle than native crew admission.
|
||||
// Supply convoys first request faction weapons, then their matching magazines.
|
||||
if (m_StockDeadline < 0) m_StockDeadline = now + 90000;
|
||||
if (now >= m_StockDeadline) { Stop(); return; }
|
||||
if (!m_Convoy.CargoIssued) return;
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (supply && !supply.MagazinesIssued) return;
|
||||
if (supply) m_MineBatch = supply.MineStock;
|
||||
foreach (ERR_ConvoyCargoCallback operation : m_Convoy.Cargo)
|
||||
if (!operation.Finished) return;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(m_Truck.Entity.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) { Stop(); return; }
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
if (items.Count() > 128) { Stop(); return; }
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (!item || !item.FindComponent(BaseMagazineComponent)) continue;
|
||||
if (m_Stock.Count() >= 96) { Stop(); return; }
|
||||
m_Stock.Insert(item);
|
||||
}
|
||||
m_State = 1; Audit("truck magazine identities captured once after startup; absent/looted stock is never replaced");
|
||||
}
|
||||
bool TryPlan(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now, bool mineTrip = false, bool launcherTrip = false)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || (m_Mounted && m_Mounted.Busy()) || m_Trip >= 128 || !TruckValid()) return false;
|
||||
if ((mineTrip && launcherTrip) || m_Truck.Combat.Held || m_Truck.SupplyToken > 0 || !recipient || !donor) return false;
|
||||
if (donor.Group != m_Truck.Group || recipient.HomeGuard || !Quiet(recipient) || !Quiet(donor)) return false;
|
||||
if (donor.Downlink || donor.PendingOrder || donor.PendingConvoyOrder) return false;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.MinePair(demand, donorStatus, now)) return false;
|
||||
// Empty reports authorize only an original startup-designated engineer.
|
||||
// This reads retained entitlement, never live positions/inventory for planning.
|
||||
if (demand.AmmoState.ReadyMines == 0)
|
||||
{
|
||||
bool designated;
|
||||
for (int member = 0; member < recipient.StatusSampler.InitialStrength() && member < 32; member++)
|
||||
{
|
||||
IEntity original = recipient.StatusSampler.InitialMember(member);
|
||||
if (original && recipient.StatusSampler.CanAttribute(member, original)
|
||||
&& m_HQ.MineSupplyReady(recipient.Group, original, true)) { designated = true; break; }
|
||||
}
|
||||
if (!designated) return false;
|
||||
}
|
||||
}
|
||||
else if (launcherTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.LauncherPair(demand, donorStatus, now)) return false;
|
||||
}
|
||||
else if (!ERR_InfantryResupplyRules.Pair(demand, donorStatus, now)) return false;
|
||||
if (demand.SourceId != recipient.ForceSourceId || donorStatus.SourceId != donor.ForceSourceId) return false;
|
||||
if (demand.MessageId <= m_Consumed.Get(demand.SourceId) || now < m_NextAttempt.Get(demand.SourceId)) return false;
|
||||
bool available;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!CaptureMines()) return false;
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
if (ERR_InfantryMineTransfer.ReadyMine(mine) && !m_Spent.Contains(mine) && Contains(m_Truck.Entity, mine)) { available = true; break; }
|
||||
}
|
||||
else if (launcherTrip) available = LauncherStock(recipient);
|
||||
else available = CompatibleStock(recipient, false);
|
||||
if (m_Spent.Count() >= 96) return false;
|
||||
if (!available) return false;
|
||||
m_Members.Clear();
|
||||
for (int i = 0; i < recipient.StatusSampler.InitialStrength(); i++)
|
||||
{
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(i);
|
||||
if (actor && recipient.StatusSampler.CanAttribute(i, actor)) m_Members.Insert(actor);
|
||||
}
|
||||
m_Recipient = recipient; m_Donor = donor;
|
||||
if (!Roster()) { m_Recipient = null; m_Donor = null; return false; }
|
||||
// Disjoint bounded token range from the existing mortar courier's trip IDs.
|
||||
int slot = m_ConvoySlot;
|
||||
if (slot < 0) slot = 0; // Isolated legacy fixture uses the first convoy's range.
|
||||
int token = 100000 + slot * 128 + m_Trip + 1;
|
||||
if (!m_HQ.ReserveLogistics(recipient.Group, token)) { m_Recipient = null; m_Donor = null; return false; }
|
||||
m_MineTrip = mineTrip; m_LauncherTrip = launcherTrip; m_MineRecipientSlot = -1; m_Receiving = null; m_EmptyMineReplacement = false;
|
||||
m_Trip++; m_Token = token; m_Truck.SupplyToken = token; m_ReportId = demand.MessageId; m_TripDelivered = 0; m_Served.Clear();
|
||||
m_Consumed.Set(demand.SourceId, demand.MessageId); m_NextAttempt.Set(demand.SourceId, now + 180000);
|
||||
m_Deadline = Math.Min(now + 120000, demand.ObservedAt + 180000); m_State = 2;
|
||||
string purpose = "stop existing ammo truck and report position";
|
||||
if (mineTrip) purpose += "; one finite PMN4 top-up for an existing carrier";
|
||||
if (launcherTrip) purpose += "; finite compatible magazine for a reported depleted launcher";
|
||||
m_Order = m_HQ.Downlink(donor.Group, "INFANTRY SUPPLY HOLD", purpose, m_ReportId);
|
||||
if (!m_Order) Finish("truck radio downlink unavailable");
|
||||
else Audit("existing patrol reserved; truck hold awaits radio delivery");
|
||||
return true;
|
||||
}
|
||||
// Optional mine startup must never delay normal magazine readiness. Pin the
|
||||
// original batch during Stock(), then copy its closed exact identities once.
|
||||
protected bool CaptureMines()
|
||||
{
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (!supply || !m_MineBatch || supply.MineStock != m_MineBatch || !m_MineBatch.Complete()) return false;
|
||||
if (m_MineStockCaptured) return !m_MineStock.IsEmpty();
|
||||
m_MineStockCaptured = true;
|
||||
int count = m_MineBatch.Count();
|
||||
if (count < 0 || count > 2) return false;
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
IEntity item = m_MineBatch.At(index);
|
||||
if (item && !m_MineStock.Contains(item)) m_MineStock.Insert(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Compatibility-only preflight of original own carriers; HQ still uses the
|
||||
// delivered report for demand and positions. No item is reserved or moved here.
|
||||
protected bool CompatibleStock(ERR_HQUnit recipient, bool launcherMagazine)
|
||||
{
|
||||
if (!recipient || !recipient.StatusSampler || m_Stock.Count() > 96) return false;
|
||||
int strength = recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
int checks;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine)) continue;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (++checks > 96 * 32) return false;
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !recipient.StatusSampler.CanAttribute(slot, actor) || !ERR_Actors.CanFight(actor)) continue;
|
||||
if (ERR_InfantryAmmoTransfer.Compatible(actor, magazine, launcherMagazine)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected bool LauncherStock(ERR_HQUnit recipient)
|
||||
{
|
||||
return CompatibleStock(recipient, true);
|
||||
}
|
||||
bool TryPlanLauncher(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, false, true);
|
||||
}
|
||||
bool TryPlanMines(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, true);
|
||||
}
|
||||
// Share exact frozen inventory identities and global radio replay state.
|
||||
bool TryPlanMounted(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || m_ConvoySlot < 0 || !TruckValid(true)) return false;
|
||||
if (m_Mounted && m_Mounted.Busy()) return false;
|
||||
if (!m_Mounted) m_Mounted = new ERR_MountedResupply(m_HQ, m_Mode, m_Convoy, m_ConvoySlot, m_Stock, m_Spent, m_Consumed, m_NextAttempt);
|
||||
return m_Mounted.Begin(recipient, donor, demand, donorStatus, now);
|
||||
}
|
||||
protected bool Waypoints()
|
||||
{
|
||||
m_MoveWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
m_HoldWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
if (!m_MoveWaypoint || !m_HoldWaypoint) return false;
|
||||
// The reported rendezvous is 3 m from the donor report. A 2 m move
|
||||
// radius allowed arrival 5 m away, beyond the transfer's physical reach.
|
||||
m_MoveWaypoint.SetCompletionRadius(0.5); m_HoldWaypoint.SetCompletionRadius(0.5);
|
||||
m_Recipient.Group.AddWaypointAt(m_HoldWaypoint, 0); m_Recipient.Group.AddWaypointAt(m_MoveWaypoint, 0);
|
||||
m_Recipient.Group.ActivateAI(); return true;
|
||||
}
|
||||
protected void ClearWaypoints()
|
||||
{
|
||||
if (m_MoveWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_MoveWaypoint); ERR_Actors.DeleteSpawned(m_MoveWaypoint); }
|
||||
if (m_HoldWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_HoldWaypoint); ERR_Actors.DeleteSpawned(m_HoldWaypoint); }
|
||||
m_MoveWaypoint = null; m_HoldWaypoint = null;
|
||||
}
|
||||
protected void Finish(string reason)
|
||||
{
|
||||
Audit(reason);
|
||||
if (m_Move) m_Move.Stop();
|
||||
if (m_MineMove) m_MineMove.Stop();
|
||||
ClearWaypoints();
|
||||
m_Order = null;
|
||||
// A late native move must not race another truck's newer report. Retain both
|
||||
// exact claims until this one submitted identity proves custody or deletion.
|
||||
if ((m_MineMove && m_MineMove.Unresolved()) || (m_LauncherTrip && m_Move && m_Move.Unresolved())) { m_State = 7; return; }
|
||||
if (m_Recipient) m_HQ.ReleaseLogistics(m_Recipient.Group, m_Token);
|
||||
if (m_Truck && m_Truck.SupplyToken == m_Token) { m_Truck.SupplyToken = 0; m_Truck.SupplyHeld = false; }
|
||||
m_Recipient = null; m_Donor = null; m_Order = null; m_Receiving = null; m_State = 1; m_MineTrip = false; m_LauncherTrip = false; m_MineRecipientSlot = -1;
|
||||
}
|
||||
protected void TransferMine(float now)
|
||||
{
|
||||
if (m_MineMove)
|
||||
{
|
||||
int result = m_MineMove.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native mine transfer failed or expired; exact submitted identity stays spent"); return; }
|
||||
m_MineMove = null; m_MinesDelivered++;
|
||||
Finish("one exact finite PMN4 confirmed in the original carrier inventory"); return;
|
||||
}
|
||||
if (!m_Receiving)
|
||||
{
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
for (int slot = 0; slot < strength && slot < 32; slot++)
|
||||
{
|
||||
IEntity actor = m_Recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !m_Members.Contains(actor) || !m_Recipient.StatusSampler.CanAttribute(slot, actor, false)) continue;
|
||||
if (!ERR_Actors.CanFight(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, actor)) continue;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(actor, m_Recipient.Group, carried);
|
||||
if (count != 1 && (count != 0 || !m_HQ.MineSupplyReady(m_Recipient.Group, actor, true))) continue;
|
||||
m_EmptyMineReplacement = count == 0;
|
||||
m_Receiving = actor; m_MineRecipientSlot = slot; break;
|
||||
}
|
||||
if (!m_Receiving) return;
|
||||
}
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, m_Receiving, m_EmptyMineReplacement)) return;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(m_Receiving, m_Recipient.Group, carried);
|
||||
if (!m_Recipient.StatusSampler.CanAttribute(m_MineRecipientSlot, m_Receiving, false)
|
||||
|| (m_EmptyMineReplacement && count != 0) || (!m_EmptyMineReplacement && count != 1))
|
||||
{ Finish("original mine recipient lost or its pinned zero/one stock changed"); return; }
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
{
|
||||
if (!ERR_InfantryMineTransfer.ReadyMine(mine) || m_Spent.Contains(mine) || !Contains(m_Truck.Entity, mine)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_MineStock, m_Spent, mine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_MineMove = new ERR_InfantryMineTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, m_Receiving, m_Recipient.Group,
|
||||
mine, reservation, m_Recipient.StatusSampler, m_MineRecipientSlot, m_EmptyMineReplacement);
|
||||
m_MineMove.Tick(now);
|
||||
// The leaf commits before the one native move. Only an unsubmitted refusal
|
||||
// may release its tentative claim while the same carrier approaches/retries.
|
||||
if (m_MineMove.Submitted()) return;
|
||||
reservation.ReleaseUnsubmitted(); m_MineMove = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
protected void Transfer(float now)
|
||||
{
|
||||
if (m_Move)
|
||||
{
|
||||
int result = m_Move.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native transfer rejected, expired or lost authority; no item retry"); return; }
|
||||
m_Move = null; m_Delivered++; m_TripDelivered++; m_Served.Insert(m_Receiving); m_Receiving = null;
|
||||
Audit("exact finite magazine confirmed in original soldier inventory");
|
||||
if (m_TripDelivered >= 6) { Finish("six-magazine trip allowance reached"); return; }
|
||||
}
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!ERR_Actors.CanFight(actor) || m_Served.Contains(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
ERR_HQAmmoSnapshot local = new ERR_HQAmmoSnapshot(); local.Complete = true; local.LauncherComplete = true;
|
||||
ERR_HQAmmoSampler.Inspect(actor, m_Recipient.Group, local);
|
||||
if (m_LauncherTrip)
|
||||
{
|
||||
if (!local.Valid(1) || !local.LauncherComplete || local.Members != 1 || local.LauncherMuzzles <= 0
|
||||
|| local.LauncherRounds != 0 || local.LauncherChambers != 0) continue;
|
||||
}
|
||||
else if (!local.Complete || local.SmallArmsMuzzles <= 0 || local.SmallArmsRounds + local.SmallArmsChambers > 30) continue;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine) || !ERR_InfantryAmmoTransfer.Compatible(actor, magazine, m_LauncherTrip)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_Stock, m_Spent, magazine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_Receiving = actor;
|
||||
m_Move = new ERR_InfantryAmmoTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, actor, m_Recipient.Group, magazine, !m_LauncherTrip, m_LauncherTrip);
|
||||
m_Move.Tick(now);
|
||||
if (m_Move.Submitted()) { reservation.Commit(); return; }
|
||||
// No native operation exists yet: approach geometry, stopped state or
|
||||
// capacity may improve while the same bounded rendezvous remains valid.
|
||||
// Keep every submitted identity spent, including a synchronous rejection.
|
||||
reservation.ReleaseUnsubmitted(); m_Move = null; m_Receiving = null;
|
||||
break; // At most one unsubmitted preflight per member on this slow tick.
|
||||
}
|
||||
}
|
||||
}
|
||||
void Tick(float now)
|
||||
{
|
||||
if (!ERR_ForceRules.Finite(now) || now < 0) return;
|
||||
// Stopped services retain uncertain leaf refs until exact late proof settles.
|
||||
if (m_Stopped) { PollTransfers(now); return; }
|
||||
if (!Current() || now < m_NextTick) return;
|
||||
m_NextTick = now + 1000;
|
||||
PollTransfers(now);
|
||||
if (m_Mounted && m_Mounted.Busy()) return;
|
||||
if (m_State == 7) return;
|
||||
if (m_State == 0) { Stock(now); return; }
|
||||
if (m_State == 1)
|
||||
{
|
||||
if (m_Move && !m_Move.Unresolved()) m_Move = null;
|
||||
return;
|
||||
}
|
||||
if (now >= m_Deadline || !TruckValid() || !Quiet(m_Donor) || !Roster() || m_Truck.Combat.Held
|
||||
|| m_HQ.LogisticsToken(m_Recipient.Group) != m_Token)
|
||||
{ Finish("rendezvous expired, contact appeared or original ownership changed"); return; }
|
||||
if (m_Truck.SupplyToken != m_Token) { Finish("truck hold authority lost"); return; }
|
||||
if (m_State == 2)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || m_Truck.SupplyToken != m_Token) { Finish("truck hold downlink interrupted or reservation lost"); return; }
|
||||
m_Truck.SupplyHeld = true; m_Truck.ClearOrder(); m_HeldAt = -1;
|
||||
m_Order = null; m_State = 3; Audit("truck received stop; waiting for delivered stopped-position report"); return;
|
||||
}
|
||||
if (m_State == 3)
|
||||
{
|
||||
// The delivered hold asks the original crew to report only after physically stopping.
|
||||
if (m_HeldAt < 0)
|
||||
{
|
||||
Physics physics = m_Truck.Entity.GetPhysics();
|
||||
if (!physics) return;
|
||||
float speed = physics.GetVelocity().Length();
|
||||
float angular = physics.GetAngularVelocity().Length();
|
||||
if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1)) return;
|
||||
m_HeldAt = now; m_Donor.NextStatus = now; return;
|
||||
}
|
||||
ERR_HQWatchEntry stopped = m_HQ.Watch().Find(m_Donor.ForceSourceId);
|
||||
if (!ERR_InfantryResupplyRules.Fresh(stopped, now) || stopped.ObservedAt < m_HeldAt) return;
|
||||
m_Rendezvous = stopped.Position + "3 0 0";
|
||||
m_Order = m_HQ.Downlink(m_Recipient.Group, "INFANTRY SUPPLY RENDEZVOUS", string.Format("walk to reported stopped ammo truck at %1", m_Rendezvous), m_ReportId);
|
||||
if (!m_Order) { Finish("infantry radio downlink unavailable"); return; }
|
||||
m_State = 4; return;
|
||||
}
|
||||
if (m_State == 4)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || !Waypoints()) { Finish("infantry order interrupted or native waypoint creation failed"); return; }
|
||||
m_Order = null; m_State = 5; Audit("infantry received reported rendezvous; native movement and physical transfer required");
|
||||
}
|
||||
if (m_State == 5)
|
||||
{
|
||||
if (m_MineTrip) TransferMine(now);
|
||||
else Transfer(now);
|
||||
}
|
||||
}
|
||||
string Status()
|
||||
{
|
||||
string detail = string.Format("Ground supply: state=%1 trips=%2 infantry moved=%3 stock=%4 spent=%5", State(), m_Trip, m_Delivered, m_Stock.Count(), m_Spent.Count());
|
||||
return detail + string.Format("; mines moved=%1 allowance=%2; %3", m_MinesDelivered, m_MineStock.Count(), m_Reason);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
if (m_Mounted) m_Mounted.Stop();
|
||||
Finish("service stopped; original forces and all remaining cargo retained"); m_Stopped = true;
|
||||
}
|
||||
}
|
||||
+1164
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
"""Actual depot porter selection/planner/state transitions and final finite import; native boundaries doubled."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,body,run
|
||||
BASE=Path(os.environ.get('ERR_DEPOT_ROOT',ROOT))
|
||||
P=BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c'
|
||||
S=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',BASE/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
source=P.read_text()
|
||||
valid=body(P,'protected bool Valid(')
|
||||
assert 'ERR_GroundDepotTransfer.Cargo(m_Item, m_MineCargo)' in valid
|
||||
assert 'm_Service.DepotCurrent()' in valid and 'DepotAvailable()' not in valid and 'DepotNeeded()' not in valid
|
||||
for forbidden in ('Teleport(', 'TrySpawn', 'SetAmmoCount', 'SetOrigin(', 'SetTransform('):assert forbidden not in source
|
||||
|
||||
def cpp(s):
|
||||
s=s.replace('protected ','').replace('ref ','').replace('null','nullptr')
|
||||
for t in ('ERR_HQUnit','ERR_InfantryResupply','ERR_ConvoyVehicle','ERR_HQWatchEntry','ERR_SiteRuntime','ERR_GroundDepotTransfer','ERR_GroundDepotLoading','ERR_FiniteMagazineReservation','SCR_ChimeraAIAgent'):
|
||||
s=re.sub(r'\b'+t+r' (\w+)',t+r'* \1',s)
|
||||
s=s.replace('ERR_FiniteMagazineReservation(m_Original, m_Spent, item)','ERR_FiniteMagazineReservation(&m_Original, &m_Spent, item)')
|
||||
for ns in ('ERR_ForceRules','ERR_InfantryResupplyRules','ERR_GroundDepotTransfer','ERR_InfantryAmmoTransfer','ERR_GroundDepotAccess','ERR_Actors','ERR_EnemyEquipmentRules','CompartmentAccessComponent','ERR_InfantryMineTransfer','Math'):
|
||||
s=s.replace(ns+'.',ns+'::')
|
||||
for n in ('m_HQ','m_Mode','m_Service','m_Move','m_Reservation','m_Order','m_Truck','m_Crew','m_Donor','m_Worker','m_Site','m_Cache','service','truck','donor','report','site','crew','operation','actor','agent'):
|
||||
s=re.sub(r'\b'+n+r'\.',n+'->',s)
|
||||
s=s.replace('crew->StatusSampler.', 'crew->StatusSampler->').replace('agent->m_UtilityComponent.', 'agent->m_UtilityComponent->')
|
||||
s=s.replace('SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(actor))', 'actor->agent')
|
||||
s=s.replace('InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent))','item->carried').replace('InventoryItemComponent carried','InventoryItem* carried').replace('carried.GetParentSlot()', 'carried->GetParentSlot()').replace('GetParentSlot().','GetParentSlot()->')
|
||||
s=s.replace('Sites().','Sites()->').replace('Watch().','Watch()->').replace('Forces().','Forces()->')
|
||||
s=s.replace('site->Responders.Group','site->Responders->Group').replace('site->Definition.Position','site->Definition->Position').replace('m_Site->Definition.Position','m_Site->Definition->Position')
|
||||
s=s.replace('m_Truck->Entity.GetOrigin()', 'm_Truck->Entity->GetOrigin()')
|
||||
s=s.replace('vector.DistanceXZ','Vec::DistanceXZ').replace('string.Format','Format')
|
||||
s=s.replace('InventoryStorageManagerComponent.Cast(m_Cache->FindComponent(InventoryStorageManagerComponent))','m_Cache->inventory')
|
||||
s=s.replace('"3 0 0"','Vec{3}').replace('"2 0 0"','Vec{2}')
|
||||
return s
|
||||
methods='\n'.join(cpp(body(P,x)) for x in ('bool MineCargo(', 'protected bool SelectWorker(', 'void Plan(', 'void Tick(', 'protected void Abort(', 'void Stop(', 'bool TransferValid(', 'bool ClaimDelivery(', 'bool DeliveredTo('))
|
||||
admit=(cpp(body(S,'bool AdmitDepot('))+cpp(body(S,'bool AdmitDepotMine('))).replace('job.','job->').replace('m_Stock.Insert(item); Audit(', 'm_Stock.Insert(item); Audit(')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
using string=std::string;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}void Insert(T v){this->push_back(v);}void RemoveItem(T v){this->erase(std::remove(this->begin(),this->end(),v),this->end());}};
|
||||
struct Vec{float x=0;Vec operator+(Vec b){return {x+b.x};}static float DistanceXZ(Vec a,Vec b){return std::abs(a.x-b.x);}};
|
||||
template<class...T>string Format(string s,T...){return s;}
|
||||
struct ERR_ForceRules{static bool Finite(float f){return std::isfinite(f);}};
|
||||
struct Math{static float Min(float a,float b){return std::min(a,b);}};
|
||||
struct Entity;struct Slot{Entity*attached=nullptr;Entity*GetAttachedEntity(){return attached;}};struct InventoryItem{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct Group{int faction=1;};struct Inventory{};struct Utility{bool m_AIInfo=true;};struct SCR_ChimeraAIAgent{Utility*m_UtilityComponent=nullptr;};
|
||||
struct Entity{Vec pos;Inventory*inventory=nullptr;bool stock=true,compatible=true,alive=true,player=false,aboard=false,attributed=true,equipmentEligible=true,mine=false,armed=false,defaultArmed=false,collision=true;InventoryItem*carried=nullptr;Entity*parent=nullptr;int faction=1,well=1,rounds=30,maxRounds=30;Group*group=nullptr;SCR_ChimeraAIAgent*agent=nullptr;Vec GetOrigin(){return pos;}};using IEntity=Entity*;
|
||||
struct Sampler{Array<IEntity>members;Group*group=nullptr;bool owns=true;int InitialStrength(){return members.Count();}bool OwnsRoster(Group*g){return owns&&g==group;}IEntity InitialMember(int i){return members[i];}bool CanAttribute(int i,IEntity a,bool){return a&&members[i]==a&&a->attributed&&a->group==group&&!a->player&&a->faction==group->faction;}};
|
||||
struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->alive;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity a){return a&&a->aboard;}};
|
||||
struct Definition{Vec Position;};struct ERR_SiteRuntime{struct Definition*Definition=nullptr;ERR_SiteRuntime*Responders=nullptr;struct Group*Group=nullptr;IEntity Container=nullptr;Array<IEntity>items;};
|
||||
struct Sites{Array<ERR_SiteRuntime*>sites;int Count(){return sites.Count();}ERR_SiteRuntime*At(int i){return sites[i];}int DepotItemCount(ERR_SiteRuntime*s){return s?s->items.Count():0;}IEntity DepotItem(ERR_SiteRuntime*s,int i){return s->items[i];}};
|
||||
struct ERR_HQUnit{struct Group*Group=nullptr;int ForceSourceId=0,LogisticsReservation=0;float NextStatus=0;bool eligible=true,HomeGuard=false,ReservedForSupport=false,Assignment=false,Task=false,PendingTask=false,PendingOrder=false,Downlink=false,Waypoint=false;Sampler*StatusSampler=nullptr;};
|
||||
struct ERR_ConvoyTask{};
|
||||
struct ERR_ConvoyVehicle{struct Group*Group=nullptr;IEntity Entity=nullptr;int SupplyToken=0;bool SupplyHeld=false;int clears=0;void ClearOrder(){clears++;}};
|
||||
struct ERR_HQWatchEntry{int SourceId=2,MessageId=1;float ObservedAt=0;Vec Position;bool valid=true;};
|
||||
struct ERR_InfantryResupplyRules{static bool Fresh(ERR_HQWatchEntry*r,float n){return r&&r->valid&&n>=r->ObservedAt&&n-r->ObservedAt<=120000;}};
|
||||
struct Watch{ERR_HQWatchEntry report;ERR_HQWatchEntry*Find(int){return &report;}};
|
||||
struct Ledger{void*FindGroup(Group*){return this;}};
|
||||
struct Mode{struct Sites sites;Ledger ledger;struct Sites*Sites(){return &sites;}Ledger*Forces(){return &ledger;}};
|
||||
struct ERR_EnemyEquipmentRules{static bool Eligible(Mode*,Group*g,IEntity a){return a&&a->equipmentEligible&&a->group==g&&a->faction==g->faction&&!a->player&&a->alive;}};
|
||||
struct ERR_GroundDepotLoading;struct ERR_InfantryResupply;
|
||||
struct ERR_FiniteMagazineReservation{Array<IEntity>*original,*spent;IEntity item;bool committed=false,closed=false;ERR_FiniteMagazineReservation(Array<IEntity>*a,Array<IEntity>*b,IEntity i):original(a),spent(b),item(i){}bool Reserve(){if(!item||!original->Contains(item)||spent->Contains(item)||spent->Count()>=96)return false;spent->Insert(item);return true;}bool ReleaseUnsubmitted(){if(closed||committed)return false;closed=true;spent->RemoveItem(item);return true;}bool CommittedFor(IEntity i){return committed&&i==item&&spent->Contains(i);}};
|
||||
struct Route{int outcome=1,calls=0;int Advance(float,void*){calls++;return outcome;}};
|
||||
struct HQ{Array<ERR_InfantryResupply*>services;ERR_HQUnit*crew=nullptr,*donor=nullptr;struct Watch watch;Route route;bool claim=true,radio=true;int orders=0,releases=0,claims=0;
|
||||
int GroundSupplyCount(){return services.Count();}ERR_InfantryResupply*GroundSupplyAt(int i){return services[i];}ERR_HQUnit*GroundUnit(Group*g){return crew&&crew->Group==g?crew:donor&&donor->Group==g?donor:nullptr;}struct Watch*Watch(){return &watch;}void*Journal(){return this;}
|
||||
bool ReserveGroundDepot(ERR_HQUnit*,ERR_HQUnit*,ERR_InfantryResupply*,int,bool=false);
|
||||
void ReleaseGroundDepot(ERR_HQUnit*c,ERR_HQUnit*d,ERR_ConvoyVehicle*t,int token){releases++;if(c&&c->LogisticsReservation==token)c->LogisticsReservation=0;if(d&&d->LogisticsReservation==token)d->LogisticsReservation=0;if(t&&t->SupplyToken==token){t->SupplyToken=0;t->SupplyHeld=false;}}
|
||||
Route*Downlink(Group*,string,string,int){orders++;return radio?&route:nullptr;}
|
||||
};
|
||||
// Native compatibility boundary double: pair-specific carried weapon well,
|
||||
// supported weapon flag, and sane positive ammo. Real Compatible's full native
|
||||
// weapon/muzzle/type/ownership logic remains covered by the transfer/planning suites.
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity i,IEntity owner){return i&&i->parent==owner;}static bool Compatible(IEntity a,IEntity i){return a&&i&&i->compatible&&a->compatible&&a->well>0&&a->well==i->well&&i->rounds>0&&i->maxRounds>0&&i->rounds<=i->maxRounds;}};
|
||||
struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity i){return i&&i->mine&&i->alive&&!i->armed&&!i->defaultArmed&&i->collision;}};
|
||||
struct ERR_GroundDepotAccess{static inline bool clear=true;static bool Clear(IEntity,IEntity){return clear;}};
|
||||
struct ERR_GroundDepotTransfer{static inline int constructed=0;bool mineCargo=false,delivery=false,submitted=true,unknown=true,confirmed=false;int result=0;IEntity item;ERR_FiniteMagazineReservation*r;
|
||||
ERR_GroundDepotTransfer(ERR_GroundDepotLoading*,IEntity,IEntity,IEntity i,ERR_FiniteMagazineReservation*q,bool d,bool m=false):mineCargo(m),delivery(d),item(i),r(q){constructed++;r->committed=true;}
|
||||
static bool Magazine(IEntity i){return i&&i->stock&&!i->mine;}static bool Cargo(IEntity i,bool mine=false){return mine?ERR_InfantryMineTransfer::ReadyMine(i):Magazine(i);}bool MineCargo(){return mineCargo;}bool Delivery(){return delivery;}IEntity Item(){return item;}bool Unresolved(){return submitted&&unknown;}bool Confirmed(){return confirmed&&Cargo(item,mineCargo);}void Stop(){result=-1;}int Tick(float){return result;}
|
||||
};
|
||||
struct ERR_InfantryResupply{bool available=true,needed=true,mineNeeded=false;int m_DepotImports=0,m_DepotMineImports=0;ERR_ConvoyVehicle*truck=nullptr;ERR_ConvoyTask task;Array<IEntity>m_Stock,m_MineStock,m_Spent;ERR_ConvoyVehicle*m_Truck=nullptr;
|
||||
bool DepotAvailable(){return available&&m_Stock.Count()<96;}bool DepotNeeded(){return DepotAvailable()&&needed;}bool DepotMineNeeded(){return available&&mineNeeded&&m_MineStock.Count()<96&&m_DepotMineImports==0;}ERR_ConvoyVehicle*DepotTruck(){return available?truck:nullptr;}ERR_ConvoyTask*Task(){return &task;}bool Contains(IEntity,IEntity i){return i!=nullptr;}void Audit(string){}bool AdmitDepot(ERR_GroundDepotLoading*,IEntity);bool AdmitDepotMine(ERR_GroundDepotLoading*,IEntity);
|
||||
};
|
||||
struct ERR_GroundDepotLoading{HQ*m_HQ;Mode*m_Mode;Array<IEntity>m_Original,m_Spent;bool active=true,valid=true,stationary=true,canWalk=true,m_Stopped=false,m_Captured=false,m_PickedUp=false,m_DeliveryClaimed=false,m_Imported=false,m_MineCargo=false;int m_State=0,m_Attempts=0,m_Delivered=0,m_Token=0,m_WorkerSlot=0,walks=0,cleanups=0,notes=0;float m_NextPlan=0,m_Deadline=0,m_Last=-1,m_NextTick=0,m_HeldAt=-1;Vec m_CachePosition,m_TruckPosition;
|
||||
Utility*m_Utility=nullptr;ERR_HQUnit*m_Crew=nullptr,*m_Donor=nullptr;ERR_SiteRuntime*m_Site=nullptr;IEntity m_Worker=nullptr,m_Cache=nullptr,m_Item=nullptr;Inventory*m_CacheInventory=nullptr;void*m_CrewRecord=nullptr;ERR_InfantryResupply*m_Service=nullptr;ERR_ConvoyTask*m_Task=nullptr;ERR_ConvoyVehicle*m_Truck=nullptr;Route*m_Order=nullptr;ERR_GroundDepotTransfer*m_Move=nullptr;ERR_FiniteMagazineReservation*m_Reservation=nullptr;
|
||||
bool Active(){return active&&!m_Stopped;}bool Busy(){return m_State!=0;}bool Unresolved(){return m_Move&&m_Move->Unresolved();}bool Valid(){return Active()&&valid&&(!m_Service||m_Service->available)&&ERR_GroundDepotTransfer::Cargo(m_Item,m_MineCargo);}bool Stationary(){return stationary;}bool Quiet(ERR_HQUnit*u){return u&&u->eligible;}bool Stored(IEntity,IEntity){return true;}void Capture(){m_Captured=true;}void Note(string){notes++;}void ClearAction(){}bool Walk(Vec){walks++;return canWalk;}
|
||||
void Cleanup(){cleanups++;if(m_Reservation)m_Reservation->ReleaseUnsubmitted();m_HQ->ReleaseGroundDepot(m_Crew,m_Donor,m_Truck,m_Token);m_State=0;m_Token=0;m_Move=nullptr;m_Order=nullptr;}
|
||||
METHODS
|
||||
};
|
||||
ADMISSION
|
||||
bool HQ::ReserveGroundDepot(ERR_HQUnit*c,ERR_HQUnit*d,ERR_InfantryResupply*s,int token,bool mineCargo){if(!(mineCargo?s->DepotMineNeeded():s->DepotNeeded())||!claim||c->LogisticsReservation||d->LogisticsReservation||s->truck->SupplyToken)return false;claims++;c->LogisticsReservation=d->LogisticsReservation=s->truck->SupplyToken=token;return true;}
|
||||
struct F{Mode mode;HQ hq;ERR_GroundDepotLoading job;Group cg,dg;ERR_HQUnit crew,donor;Definition def;ERR_SiteRuntime site,responders;Entity worker,second,cache,truck,item;Inventory inv;Slot itemSlot;InventoryItem carriedItem;Utility workerUtility,secondUtility;SCR_ChimeraAIAgent workerAgent,secondAgent;Sampler sampler;ERR_ConvoyVehicle vehicle;ERR_InfantryResupply service;
|
||||
F(){itemSlot.attached=&item;carriedItem.slot=&itemSlot;item.carried=&carriedItem;item.parent=&truck;worker.group=second.group=&cg;workerAgent.m_UtilityComponent=&workerUtility;secondAgent.m_UtilityComponent=&secondUtility;worker.agent=&workerAgent;second.agent=&secondAgent;sampler.group=&cg;sampler.members={&worker};crew.StatusSampler=&sampler;truck.pos={20};crew.Group=&cg;donor.Group=&dg;hq.crew=&crew;hq.donor=&donor;vehicle.Group=&dg;vehicle.Entity=&truck;service.truck=service.m_Truck=&vehicle;hq.services={&service};site.Definition=&def;site.Responders=&responders;responders.Group=&cg;site.Container=&cache;site.items={&item};cache.inventory=&inv;mode.sites.sites={&site};job.m_HQ=&hq;job.m_Mode=&mode;job.m_Worker=&worker;job.m_Original={&item};ERR_GroundDepotAccess::clear=true;}
|
||||
void Mine(){item.mine=true;service.mineNeeded=true;service.needed=false;worker.compatible=false;}
|
||||
void Start(){job.Plan(0);assert(job.m_State==1&&hq.claims==1&&hq.orders==1);}
|
||||
void Reach(){Start();job.Tick(0);assert(job.m_State==2&&vehicle.SupplyHeld&&vehicle.clears==1);job.Tick(1000);assert(donor.NextStatus==1000&&job.walks==0);job.Tick(2000);assert(job.m_State==2);hq.watch.report.ObservedAt=3000;job.Tick(3000);assert(job.m_State==3&&hq.orders==2&&job.walks==0);job.Tick(4000);assert(job.m_State==4&&job.walks==1);}
|
||||
};
|
||||
int main(){
|
||||
// A mine-only deficit chooses the original porter without rifle compatibility,
|
||||
// but still follows both delivered radio orders and exact two-leg proof.
|
||||
{F f;f.Mine();f.Reach();assert(f.job.MineCargo()&&f.job.m_Worker==&f.worker);f.job.Tick(5000);auto*pick=f.job.m_Move;assert(pick->MineCargo());pick->unknown=false;pick->confirmed=true;pick->result=1;f.job.Tick(6000);f.job.Tick(7000);auto*drop=f.job.m_Move;assert(drop->MineCargo());drop->unknown=false;drop->confirmed=true;drop->result=1;assert(!f.service.AdmitDepot(&f.job,&f.item));f.job.Tick(8000);assert(f.job.m_State==6&&f.service.m_Stock.empty()&&f.service.m_MineStock.Count()==1&&f.service.m_DepotMineImports==1&&f.service.m_DepotImports==0);f.job.Tick(9000);assert(!f.job.Busy());}
|
||||
// Armed or changed cargo aborts at each active stage; uncertain native moves
|
||||
// retain claims until proof settles, and never import through a late callback.
|
||||
for(int phase=1;phase<=5;phase++){F f;f.Mine();if(phase<=2){f.Start();if(phase==2)f.job.Tick(0);}else{f.Reach();if(phase==3)f.job.m_State=3;if(phase==5){f.job.Tick(5000);f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);}}
|
||||
f.item.armed=true;f.job.Tick(10000);assert(!f.job.Busy()&&f.service.m_MineStock.empty()&&f.job.m_Delivered==0);}
|
||||
{F f;f.Mine();f.Reach();f.job.Tick(5000);auto*leaf=f.job.m_Move;f.item.armed=true;f.job.Tick(6000);assert(f.job.m_State==7&&f.crew.LogisticsReservation>0);leaf->unknown=false;leaf->confirmed=true;leaf->result=1;f.job.Tick(7000);assert(!f.job.Busy()&&f.service.m_MineStock.empty()&&f.job.m_Delivered==0&&f.job.m_Spent.Count()==1);}
|
||||
{F f;f.Mine();f.Reach();f.job.Tick(5000);f.job.m_Move->mineCargo=false;assert(!f.job.TransferValid(f.job.m_Move));}
|
||||
{F f;f.Mine();f.Reach();f.job.Tick(5000);f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);f.job.Tick(7000);f.service.mineNeeded=false;assert(!f.job.ClaimDelivery(f.job.m_Move));f.job.m_Move->unknown=false;f.job.m_Move->confirmed=true;f.job.m_Move->result=1;f.job.Tick(8000);assert(f.service.m_MineStock.empty()&&f.job.m_Delivered==0);}
|
||||
for(int kind=0;kind<5;kind++){F f;f.Mine();if(kind==0)f.item.armed=true;if(kind==1)f.item.defaultArmed=true;if(kind==2)f.item.alive=false;if(kind==3)f.item.collision=false;if(kind==4)f.service.mineNeeded=false;f.job.Plan(0);assert(!f.job.Busy()&&f.hq.orders==0&&f.hq.claims==0&&f.job.m_Attempts==0);}
|
||||
|
||||
// Actual Plan must enumerate worker/item pairs: the first fit original can
|
||||
// carry the wrong weapon while a second original can use this exact magazine.
|
||||
{F f;f.worker.well=2;f.second.well=1;f.sampler.members={&f.worker,&f.second};f.job.Plan(0);assert(f.job.m_State==1&&f.hq.claims==1&&f.hq.orders==1&&"compatible second original must permit planning despite incompatible first original");assert(f.job.m_Worker==&f.second&&f.job.m_WorkerSlot==1&&f.job.m_Item==&f.item&&f.job.m_Attempts==1);}
|
||||
{F f;f.worker.well=2;f.second.well=1;f.sampler.members={&f.second,&f.worker};f.Start();assert(f.job.m_Worker==&f.second&&f.job.m_WorkerSlot==0);}
|
||||
// Bad first originals do not hide a later valid original; if no eligible
|
||||
// compatible member remains, planning must not reserve or issue a command.
|
||||
for(int k=0;k<11;k++)for(bool later:{false,true}){F f;Group foreign;f.sampler.members={&f.worker};
|
||||
if(k==0)f.sampler.members[0]=nullptr;
|
||||
if(k==1)f.worker.attributed=false;
|
||||
if(k==2)f.worker.group=&foreign;
|
||||
if(k==3)f.worker.player=true;
|
||||
if(k==4)f.worker.alive=false;
|
||||
if(k==5)f.worker.aboard=true;
|
||||
if(k==6)f.worker.agent=nullptr;
|
||||
if(k==7)f.workerAgent.m_UtilityComponent=nullptr;
|
||||
if(k==8)f.workerUtility.m_AIInfo=false;
|
||||
if(k==9)f.worker.faction=2;
|
||||
if(k==10)f.worker.equipmentEligible=false;
|
||||
if(later)f.sampler.members.Insert(&f.second);
|
||||
f.job.Plan(0);
|
||||
if(later){assert(f.job.Busy()&&f.job.m_Worker==&f.second&&f.job.m_WorkerSlot==1&&f.hq.claims==1&&f.hq.orders==1&&f.job.m_Attempts==1);}
|
||||
else{assert(!f.job.Busy()&&f.hq.claims==0&&f.hq.orders==0&&f.job.m_Attempts==0&&f.job.m_Spent.empty()&&f.crew.LogisticsReservation==0&&f.donor.LogisticsReservation==0&&f.vehicle.SupplyToken==0);}
|
||||
}
|
||||
for(int k=0;k<5;k++){F f;f.sampler.members={&f.worker,&f.second};if(k==0)f.worker.well=f.second.well=2;if(k==1)f.item.rounds=0;if(k==2)f.item.maxRounds=0;if(k==3)f.item.rounds=31;if(k==4)f.worker.compatible=f.second.compatible=false;f.job.Plan(0);assert(!f.job.Busy()&&f.hq.claims==0&&f.hq.orders==0&&f.job.m_Attempts==0&&f.job.m_Spent.empty());}
|
||||
{F f;f.sampler.owns=false;f.job.Plan(0);assert(!f.job.Busy()&&f.hq.claims==0&&f.hq.orders==0&&f.job.m_Attempts==0);}
|
||||
{F f;f.sampler.members.resize(33,&f.worker);f.job.Plan(0);assert(!f.job.Busy()&&f.hq.claims==0&&f.hq.orders==0&&f.job.m_Attempts==0);}
|
||||
// No new stock or commands on missing capacity/camp/worker/report/claim.
|
||||
for(int k=0;k<8;k++){F f;if(k==0)f.service.available=false;if(k==1)f.site.items.clear();if(k==2)f.crew.eligible=false;if(k==3)f.hq.watch.report.valid=false;if(k==4)f.hq.claim=false;if(k==5)f.item.compatible=false;if(k==6)f.job.m_Original.clear();if(k==7)f.service.needed=false;f.job.Plan(0);assert(!f.job.Busy()&&f.hq.orders==0&&f.job.m_Spent.empty());}
|
||||
{F f;f.Start();f.hq.route.outcome=-1;f.job.Tick(0);assert(!f.job.Busy()&&f.job.walks==0&&!f.vehicle.SupplyHeld&&f.job.m_Spent.empty());}
|
||||
// Complete actual state sequence; first proof retires before delivery callback.
|
||||
{F f;f.Reach();f.job.Tick(5000);auto*pickup=f.job.m_Move;assert(pickup&&!pickup->Delivery());pickup->unknown=false;pickup->confirmed=true;pickup->result=1;f.job.Tick(6000);assert(f.job.m_State==5&&!f.job.m_Move&&f.job.walks==2);f.job.Tick(7000);auto*delivery=f.job.m_Move;assert(delivery&&delivery!=pickup&&delivery->Delivery());delivery->unknown=false;delivery->confirmed=true;delivery->result=1;f.job.Tick(8000);assert(f.service.m_Stock.Count()==1&&f.job.m_Delivered==1&&f.job.m_State==6);f.job.Tick(9000);assert(!f.job.Busy()&&!f.vehicle.SupplyHeld&&f.job.m_Spent.Count()==1);}
|
||||
for(bool second:{false,true}){F f;f.Reach();f.job.Tick(5000);if(second){f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);f.job.Tick(7000);}auto*leaf=f.job.m_Move;int walks=f.job.walks;f.job.Stop();assert(f.job.m_State==7&&f.vehicle.SupplyHeld&&f.crew.LogisticsReservation>0);f.job.Tick(200000);assert(f.job.m_State==7&&f.service.m_Stock.empty()&&f.job.walks==walks);leaf->unknown=false;leaf->confirmed=true;f.job.Tick(200001);assert(!f.job.Busy()&&f.service.m_Stock.empty()&&f.job.m_Spent.Count()==1&&!f.vehicle.SupplyHeld);f.job.Plan(300000);assert(!f.job.Busy());}
|
||||
// Expiry never extends the job; late proof does not adopt cargo.
|
||||
{F f;f.Reach();f.job.Tick(5000);f.job.Tick(f.job.m_Deadline);assert(f.job.m_State==7);f.job.m_Move->unknown=false;f.job.Tick(999999);assert(!f.job.Busy()&&f.service.m_Stock.empty());}
|
||||
// Target lifetime96 allowance: no eviction of spent/deleted identities.
|
||||
{F f;f.service.m_Stock.resize(96,nullptr);f.job.Plan(0);assert(!f.job.Busy()&&f.hq.orders==0);}
|
||||
// Filling the final lifetime slot does not invalidate the return phase.
|
||||
{F f;f.service.m_Stock.resize(95,nullptr);f.Reach();f.job.Tick(5000);f.job.m_Move->unknown=false;f.job.m_Move->result=1;f.job.Tick(6000);f.job.Tick(7000);f.job.m_Move->unknown=false;f.job.m_Move->confirmed=true;f.job.m_Move->result=1;f.job.Tick(8000);assert(f.service.m_Stock.Count()==96&&f.job.m_State==6);f.truck.pos={3};f.job.Tick(9000);assert(f.job.m_State==6&&f.vehicle.SupplyHeld);f.truck.pos={20};f.job.Tick(10000);assert(!f.job.Busy());}
|
||||
// A completed physical move cannot import wrong/previously-spent/foreign identity.
|
||||
{F f;f.Reach();f.job.Tick(5000);auto*l=f.job.m_Move;l->unknown=false;l->result=1;f.job.Tick(6000);f.job.Tick(7000);f.job.m_Move->unknown=false;f.job.m_Move->confirmed=true;Entity foreign;assert(!f.service.AdmitDepot(&f.job,&foreign));f.service.m_Spent.Insert(&f.item);assert(!f.service.AdmitDepot(&f.job,&f.item));}
|
||||
}
|
||||
'''.replace('METHODS',methods).replace('ADMISSION',admit.replace('bool AdmitDepot(', 'bool ERR_InfantryResupply::AdmitDepot(').replace('bool AdmitDepotMine(', 'bool ERR_InfantryResupply::AdmitDepotMine(')))
|
||||
print('PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop')
|
||||
@@ -0,0 +1,47 @@
|
||||
"""Actual HQ cargo-class reservation and service demand; native availability doubled."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,body,run
|
||||
H=Path(os.environ.get('ERR_DEPOT_HQ_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c'))
|
||||
S=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
def cpp(s):
|
||||
s=s.replace('protected ','').replace('null','nullptr').replace('int committed;', 'int committed = 0;')
|
||||
for typ in ('ERR_HQUnit','ERR_InfantryResupply','ERR_ConvoyVehicle'):
|
||||
s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s)
|
||||
for name in ('m_Mode','crew','donor','service','truck'):
|
||||
s=re.sub(r'\b'+name+r'\.',name+'->',s)
|
||||
s=s.replace('Replication.IsServer()', 'server').replace('ERR_GameMode.Get()', 'current')
|
||||
s=s.replace('foreach (IEntity item : m_Spent)', 'for (IEntity item : m_Spent)')
|
||||
return s
|
||||
hq='\n'.join(cpp(body(H,x)) for x in ('bool ReserveGroundDepot(', 'void ReleaseGroundDepot('))
|
||||
demand='\n'.join(cpp(body(S,x)) for x in ('bool DepotNeeded(', 'bool DepotMineNeeded('))
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
struct Entity{};using IEntity=Entity*;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}};
|
||||
struct Group{};struct HQ;
|
||||
struct Mode{HQ*owner=nullptr;bool active=true;bool Active(){return active;}HQ*Command(){return owner;}};
|
||||
bool server=true;Mode*current=nullptr;
|
||||
struct ERR_HQUnit{struct Group*Group=nullptr;bool HomeGuard=false,ReservedForSupport=false,Task=false,PendingTask=false,PendingCheckin=false,PendingConvoyOrder=false;int LogisticsReservation=0;};
|
||||
struct ERR_ConvoyVehicle{struct Group*Group=nullptr;int SupplyToken=0;bool SupplyHeld=false;};
|
||||
struct ERR_InfantryResupply{bool magAvailable=true,mineAvailable=true,captured=true;int m_DepotImports=0,m_DepotMineImports=0;Array<IEntity>m_Stock,m_MineStock,m_Spent;ERR_ConvoyVehicle*truck=nullptr;bool DepotAvailable(){return magAvailable;}bool DepotMineAvailable(){return mineAvailable;}bool CaptureMines(){return captured;}ERR_ConvoyVehicle*DepotTruck(){return truck;}
|
||||
DEMAND
|
||||
};
|
||||
struct HQ{Mode*m_Mode=nullptr;bool m_Stopping=false,eligible=true,reserve=true;Array<ERR_HQUnit*>m_Units;int claims=0,releases=0;bool MountedLogisticsEligible(ERR_HQUnit*){return eligible;}bool ReserveLogistics(Group*g,int token){if(!reserve)return false;for(auto*u:m_Units)if(u->Group==g){if(u->LogisticsReservation)return false;u->LogisticsReservation=token;claims++;return true;}return false;}void ReleaseLogistics(Group*g,int token){for(auto*u:m_Units)if(u->Group==g&&u->LogisticsReservation==token){u->LogisticsReservation=0;releases++;}}
|
||||
HQMETHODS
|
||||
};
|
||||
struct F{Mode mode;HQ h;Group cg,dg;ERR_HQUnit crew,donor;ERR_ConvoyVehicle truck;ERR_InfantryResupply s;Entity mine,mag,foreign;F(){server=true;current=&mode;mode.owner=&h;h.m_Mode=&mode;crew.Group=&cg;donor.Group=truck.Group=&dg;h.m_Units={&crew,&donor};s.truck=&truck;s.m_Stock={&mag};s.m_MineStock={&mine};}void Unclaimed(){assert(h.claims==0&&crew.LogisticsReservation==0&&donor.LogisticsReservation==0&&truck.SupplyToken==0&&!truck.SupplyHeld);}};
|
||||
int main(){
|
||||
// Mine-only expenditure authorizes mine cargo only. Magazine-only is inverse.
|
||||
for(bool mines:{false,true})for(bool cargo:{false,true}){F f;f.s.m_Spent={mines?&f.mine:&f.mag};bool accepted=f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001,cargo);assert(accepted==(mines==cargo));if(!accepted)f.Unclaimed();else{assert(f.h.claims==1&&f.crew.LogisticsReservation==300001&&f.donor.LogisticsReservation==300001&&f.truck.SupplyToken==300001);assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300002,cargo));f.truck.SupplyHeld=true;f.h.ReleaseGroundDepot(&f.crew,&f.donor,&f.truck,300002);assert(f.truck.SupplyToken==300001&&f.truck.SupplyHeld);f.h.ReleaseGroundDepot(&f.crew,&f.donor,&f.truck,300001);assert(!f.crew.LogisticsReservation&&!f.donor.LogisticsReservation&&!f.truck.SupplyToken&&!f.truck.SupplyHeld);}}
|
||||
// Null/deleted/unrelated spent identities and satisfied imported demand never count.
|
||||
for(bool mines:{false,true})for(int k=0;k<4;k++){F f;if(k==0){f.s.m_Spent={nullptr};f.s.m_Stock.push_back(nullptr);f.s.m_MineStock.push_back(nullptr);}if(k==1)f.s.m_Spent={&f.foreign};if(k==2){f.s.m_Spent={mines?&f.mine:&f.mag};if(mines)f.s.m_DepotMineImports=1;else f.s.m_DepotImports=1;}if(k==3){f.s.m_Spent={mines?&f.mine:&f.mag};if(mines)f.s.mineAvailable=false;else f.s.magAvailable=false;}assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001,mines));f.Unclaimed();}
|
||||
// Existing authority, task ownership and token gates apply equally to mine jobs.
|
||||
for(int k=0;k<15;k++){F f;f.s.m_Spent={&f.mine};int token=300001;if(k==0)server=false;if(k==1)f.h.m_Stopping=true;if(k==2)current=nullptr;if(k==3)f.mode.active=false;if(k==4)f.mode.owner=nullptr;if(k==5)token=300000;if(k==6)token=300097;if(k==7)f.h.m_Units.clear();if(k==8)f.h.eligible=false;if(k==9)f.crew.HomeGuard=true;if(k==10)f.crew.ReservedForSupport=true;if(k==11)f.crew.PendingCheckin=true;if(k==12)f.crew.PendingConvoyOrder=true;if(k==13)f.h.reserve=false;if(k==14)f.truck.Group=&f.cg;assert(!f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,token,true));f.Unclaimed();}
|
||||
// Legacy default remains magazine demand; distinct import counters don't cross classes.
|
||||
{F f;f.s.m_Spent={&f.mag,&f.mine};f.s.m_DepotMineImports=1;assert(!f.s.DepotMineNeeded()&&f.s.DepotNeeded());assert(f.h.ReserveGroundDepot(&f.crew,&f.donor,&f.s,300001));}
|
||||
}
|
||||
'''.replace('DEMAND',demand).replace('HQMETHODS',hq))
|
||||
print('PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled')
|
||||
@@ -0,0 +1,131 @@
|
||||
"""Actual authored-stock capture/access and exact post-delivery stock admission."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,body,run
|
||||
from test_finite_magazine_reservation import translated_reservation
|
||||
B=Path(os.environ.get('ERR_GROUND_DEPOT_ROOT',ROOT))
|
||||
S=Path(os.environ.get('ERR_SITE_SERVICE_SOURCE',B/'addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c'))
|
||||
I=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',B/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
L=Path(os.environ.get('ERR_GROUND_DEPOT_LOADING_SOURCE',B/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c'))
|
||||
assert 'int DepotItemCount(' in S.read_text() and 'bool AdmitDepotMine(' in I.read_text(), 'finite authored camp mine provenance/import API is absent'
|
||||
# Read the actual authored configuration, not a duplicated stock fixture.
|
||||
conf=(B/'addons/core/Configs/ERR/EveronSites.conf').read_text()
|
||||
pmn='{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et'
|
||||
camps=[]
|
||||
for match in re.finditer(r' ERR_SiteDefinition \{',conf):
|
||||
end=match.end();depth=1
|
||||
while depth:
|
||||
if conf[end]=='{':depth+=1
|
||||
elif conf[end]=='}':depth-=1
|
||||
end+=1
|
||||
block=conf[match.start():end]
|
||||
eligible=bool(re.search(r'^ Kind 3$',block,re.M)) and not re.search(r'^ RevealOnEscape 1$',block,re.M)
|
||||
stocks=re.findall(r'ERR_SiteStock \{ Prefab "([^"\n]+)" Count (\d+)([^}]*?) \}',block)
|
||||
mines=[row for row in stocks if row[0]==pmn]
|
||||
if eligible:
|
||||
assert len(mines)==1 and mines[0][1]=='2' and 'TargetId' not in mines[0][2]
|
||||
camps.append(re.search(r'Id "([^"]+)"',block).group(1))
|
||||
else:assert not mines
|
||||
assert len(camps)==5
|
||||
assert 'ERR_InfantryMineTransfer' not in S.read_text(), 'Core must not depend on the AI mine transfer layer'
|
||||
source=S.read_text();start=source.index(' if (spec.Kind == ERR_LocationKind.OUTPOST');capture=source[start:source.index(' placement.Item = item;',start)]
|
||||
access='\n'.join(body(S,k) for k in ('int DepotMagazineCount(', 'int DepotMineCount(', 'int DepotItemCount(', 'IEntity DepotItem(', 'void DepotStock(', 'IEntity DepotMagazine(', 'bool DepotOriginal('))
|
||||
admit='\n'.join(body(I,k) for k in ('bool DepotCurrent(', 'bool DepotAvailable(', 'bool DepotNeeded(', 'bool AdmitDepot(', 'bool DepotMineAvailable(', 'bool DepotMineNeeded(', 'bool AdmitDepotMine(', 'protected bool CaptureMines('))
|
||||
delivered=body(L,'bool DeliveredTo(')
|
||||
def adapt(s):
|
||||
s=s.replace('array<IEntity>','Array<IEntity>').replace('out Array<IEntity> items','Array<IEntity>& items').replace('ERR_SiteRuntime site','Site* site').replace('ERR_GroundDepotLoading job','Loading* job').replace('ERR_InfantryResupply service','Service* service')
|
||||
s=s.replace('protected ', '').replace('ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);','Supply* supply = m_Convoy;')
|
||||
s=s.replace('InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));','InventoryItem* carried = item->inventoryItem;')
|
||||
s=s.replace('foreach (IEntity item : m_MineStock)', 'for (IEntity item : m_MineStock)')
|
||||
s=s.replace('ERR_InfantryMineTransfer.', 'ERR_InfantryMineTransfer::').replace('ERR_InfantryAmmoTransfer.', 'ERR_InfantryAmmoTransfer::')
|
||||
for name in ('supply','m_MineBatch','carried'):s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('GetParentSlot().','GetParentSlot()->')
|
||||
for name in ('site','spec','stock','item','m_Stock','m_Spent','m_Mounted','m_Truck','job','m_Move','m_Reservation'):
|
||||
if name not in ('m_Stock','m_Spent'): s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('site->Definition.', 'site->Definition->').replace('site->Responders.', 'site->Responders->')
|
||||
s=s.replace('stock->TargetId.IsEmpty()','stock->TargetId.empty()').replace('item->FindComponent(BaseMagazineComponent)','item->magazine')
|
||||
s=s.replace('foreach (IEntity item : m_Spent)', 'for (IEntity item : m_Spent)').replace('int committed;', 'int committed=0;')
|
||||
s=s.replace('Replication.IsServer()','server').replace('ERR_PrepareResult.READY','1').replace('ERR_LocationKind.OUTPOST','3').replace('null','nullptr')
|
||||
return s
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
using string=std::string;bool server=true;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}void Insert(T x){this->push_back(x);}void RemoveItem(T x){this->erase(std::remove(this->begin(),this->end(),x),this->end());}};
|
||||
struct Entity;using IEntity=Entity*;
|
||||
struct Slot{IEntity attached=nullptr;IEntity GetAttachedEntity(){return attached;}};
|
||||
struct InventoryItem{Slot* slot=nullptr;Slot* GetParentSlot(){return slot;}};
|
||||
struct Entity{bool magazine=true,ready=false,stored=true;Slot slot;InventoryItem inventory;InventoryItem*inventoryItem=&inventory;Entity(){slot.attached=this;inventory.slot=&slot;}};
|
||||
// Native ready predicate and storage graph are doubled; actual readiness is separately tested by mine-transfer suites.
|
||||
struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity item){return item&&item->ready;}};
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity item,IEntity){return item&&item->stored;}};
|
||||
struct Def{int Kind=3;bool RevealOnEscape=false;};struct Stock{string TargetId,Prefab;};
|
||||
struct Responders{bool Group=true;};struct Site{Def* Definition=nullptr;IEntity Container=nullptr;struct Responders* Responders=nullptr;Array<IEntity>DepotMagazines,DepotMines;};
|
||||
struct Sites{bool m_Stopped=false;int m_State=0;Array<Site*>m_Sites;Array<IEntity>m_Entities;bool Owns(IEntity x){return m_Entities.Contains(x);}
|
||||
''' + adapt(access)+ '\nvoid Capture(Def* spec,Stock* stock,Site* site,IEntity item){'+adapt(capture)+r'''}
|
||||
};
|
||||
''' + translated_reservation()+r'''
|
||||
struct Service;
|
||||
struct Proof{bool done=true,delivery=true,mine=false;bool MineCargo(){return mine;}bool Confirmed(){return done;}bool Delivery(){return delivery;}};
|
||||
struct Loading{bool m_Imported=false,valid=true,m_MineCargo=false;int m_State=5;Service* m_Service=nullptr;IEntity m_Item=nullptr;Proof* m_Move=nullptr;ERR_FiniteMagazineReservation* m_Reservation=nullptr;bool Valid(){return valid;}bool DeliveredTo(Service*,IEntity,bool=false);};
|
||||
struct Mounted{bool busy=false;bool Busy(){return busy;}};
|
||||
struct Truck{IEntity Entity=nullptr;};
|
||||
struct Batch{bool complete=true;Array<IEntity>items;bool Complete(){return complete;}int Count(){return items.Count();}IEntity At(int index){return items[index];}};
|
||||
struct Supply{Batch*MineStock=nullptr;};
|
||||
struct Service{Supply*m_Convoy=nullptr;Batch*m_MineBatch=nullptr;bool m_MineStockCaptured=false;Array<IEntity>m_MineStock;int m_DepotMineImports=0;bool current=true,truckValid=true,unresolved=false,m_Move=false,m_MineMove=false;int m_State=1,audits=0,m_DepotImports=0;Array<IEntity>m_Stock,m_Spent,cargo;Mounted* m_Mounted=nullptr;Truck* m_Truck=nullptr;bool Current(){return current;}bool Unresolved(){return unresolved;}bool TruckValid(bool endpoint){assert(endpoint);return truckValid;}bool Contains(IEntity,IEntity item){return cargo.Contains(item);}void Audit(string){audits++;}
|
||||
''' + adapt(admit)+r'''};
|
||||
''' + adapt(delivered).replace('bool DeliveredTo(', 'bool Loading::DeliveredTo(').replace('bool mineCargo = false','bool mineCargo')+r'''
|
||||
struct F{Entity cache,item,foreign,truck;Def def;Stock stock;Responders responders;Site site;Sites sites;Array<IEntity>original,spent;ERR_FiniteMagazineReservation reservation;Service service;Loading job;Proof proof;Truck vehicle;Mounted mounted;
|
||||
F():reservation(&original,&spent,&item){site.Definition=&def;site.Container=&cache;site.Responders=&responders;sites.m_Sites={&site};sites.m_Entities={&cache};sites.Capture(&def,&stock,&site,&item);original={&item};assert(reservation.Reserve()&&reservation.Commit());job.m_Reservation=&reservation;job.m_Move=&proof;job.m_Item=&item;job.m_Service=&service;vehicle.Entity=&truck;service.m_Truck=&vehicle;service.m_Mounted=&mounted;service.cargo={&item};}
|
||||
};
|
||||
struct M:F{Entity initial;Batch batch;Supply supply;
|
||||
M(){item.magazine=false;item.ready=true;initial.magazine=false;initial.ready=true;batch.items={&initial};supply.MineStock=&batch;service.m_Convoy=&supply;service.m_MineBatch=&batch;service.m_Spent={&initial};job.m_MineCargo=true;proof.mine=true;}
|
||||
};
|
||||
int main(){
|
||||
// Authored inert mines join detached startup provenance, without replacing magazine APIs.
|
||||
{F f;f.sites.m_State=1;f.stock.Prefab="{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et";Entity mine;mine.magazine=false;mine.ready=true;f.sites.Capture(&f.def,&f.stock,&f.site,&mine);assert(f.sites.DepotMagazineCount(&f.site)==1&&f.sites.DepotMineCount(&f.site)==1&&f.sites.DepotItemCount(&f.site)==2);assert(f.sites.DepotItem(&f.site,1)==&mine&&f.sites.DepotOriginal(&f.site,&mine));Array<IEntity>out;f.sites.DepotStock(&f.site,out);out.clear();assert(f.sites.DepotItemCount(&f.site)==2);Entity other;other.magazine=false;other.ready=true;assert(!f.sites.DepotOriginal(&f.site,&other));f.sites.Capture(&f.def,&f.stock,&f.site,&other);Entity third;third.magazine=false;third.ready=true;f.sites.Capture(&f.def,&f.stock,&f.site,&third);assert(f.sites.DepotMineCount(&f.site)==2&&!f.sites.DepotOriginal(&f.site,&third));}
|
||||
for(int bad=0;bad<4;bad++){F f;f.item.magazine=false;f.item.ready=true;f.stock.Prefab="{B05A816C0BF50802}Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et";f.site.DepotMagazines.clear();if(bad==0)f.def.RevealOnEscape=true;if(bad==1)f.def.Kind=4;if(bad==2)f.stock.TargetId="radio";if(bad==3)f.stock.Prefab="foreign";f.sites.Capture(&f.def,&f.stock,&f.site,&f.item);assert(f.site.DepotMines.empty());}
|
||||
{M f;assert(f.service.DepotMineNeeded()&&!f.service.DepotNeeded());assert(f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==2&&f.service.m_DepotMineImports==1&&f.service.m_Stock.empty());assert(!f.service.DepotMineNeeded()&&!f.service.AdmitDepotMine(&f.job,&f.item));assert(f.spent.Count()==1&&f.service.m_Spent.Count()==1);ERR_FiniteMagazineReservation next(&f.service.m_MineStock,&f.service.m_Spent,&f.item);assert(next.Reserve()&&next.Commit());assert(f.service.DepotMineNeeded());}
|
||||
// Known mine expenditure only; missing/deleted/magazine identities never become mine demand.
|
||||
{M f;f.service.m_Spent.clear();assert(!f.service.DepotMineNeeded());f.service.m_Spent={nullptr,&f.foreign};f.service.m_Stock={&f.foreign};assert(f.service.DepotNeeded()&&!f.service.DepotMineNeeded());f.service.m_MineStock={nullptr};assert(!f.service.DepotMineNeeded());}
|
||||
for(int bad=0;bad<21;bad++){M f;assert(f.service.DepotMineNeeded());if(bad==0)f.service.current=false;if(bad==1)f.service.m_State=7;if(bad==2)f.batch.complete=false;if(bad==3)f.supply.MineStock=nullptr;if(bad==4)f.service.m_MineBatch=nullptr;if(bad==5)f.service.m_MineStock.resize(96,&f.initial);if(bad==6)f.service.m_Spent.resize(96,&f.initial);if(bad==7)f.item.ready=false;if(bad==8)f.service.m_Stock.Insert(&f.item);if(bad==9)f.service.m_Spent.Insert(&f.item);if(bad==10)f.service.cargo.clear();if(bad==11)f.item.stored=false;if(bad==12)f.item.inventoryItem=nullptr;if(bad==13)f.item.inventory.slot=nullptr;if(bad==14)f.item.slot.attached=&f.foreign;if(bad==15)f.job.m_MineCargo=false;if(bad==16)f.proof.mine=false;if(bad==17)f.job.m_State=7;if(bad==18)f.job.valid=false;if(bad==19)f.proof.done=false;if(bad==20)f.service.m_Spent.clear();int before=f.service.m_MineStock.Count();assert(!f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==before&&f.service.m_DepotMineImports==0);}
|
||||
{M f;f.batch.items.clear();f.service.m_Spent.clear();assert(!f.service.DepotMineNeeded()&&!f.service.AdmitDepotMine(&f.job,&f.item));}
|
||||
{M f;assert(f.service.DepotMineNeeded());f.service.m_MineStock.resize(95,&f.initial);assert(f.service.AdmitDepotMine(&f.job,&f.item));assert(f.service.m_MineStock.Count()==96&&f.service.DepotCurrent()&&!f.service.DepotMineAvailable());}
|
||||
|
||||
{F f;Array<IEntity>out;f.sites.DepotStock(&f.site,out);assert(out.empty());f.sites.m_State=1;f.sites.DepotStock(&f.site,out);assert(out.Count()==1&&out[0]==&f.item);out[0]=&f.foreign;out.clear();assert(f.sites.DepotOriginal(&f.site,&f.item)&&!f.sites.DepotOriginal(&f.site,&f.foreign));assert(f.sites.DepotMagazine(&f.site,-1)==nullptr&&f.sites.DepotMagazine(&f.site,1)==nullptr);f.sites.m_Stopped=true;assert(!f.sites.DepotOriginal(&f.site,&f.item));}
|
||||
for(int kind=0;kind<6;kind++){F f;f.site.DepotMagazines.clear();if(kind==0)f.def.RevealOnEscape=true;if(kind==1)f.def.Kind=4;if(kind==2)f.stock.TargetId="radio";if(kind==3)f.item.magazine=false;if(kind==4)f.site.DepotMagazines.resize(96,&f.foreign);f.sites.Capture(&f.def,&f.stock,&f.site,&f.item);assert(f.site.DepotMagazines.Contains(&f.item)==(kind==5));}
|
||||
for(int bad=0;bad<7;bad++){F f;f.sites.m_State=1;if(bad==0)server=false;if(bad==1)f.sites.m_Sites.clear();if(bad==2)f.site.Container=nullptr;if(bad==3)f.sites.m_Entities.clear();if(bad==4)f.site.Responders=nullptr;if(bad==5)f.responders.Group=false;if(bad==6)f.site.DepotMagazines.resize(97,&f.item);assert(f.sites.DepotMagazineCount(&f.site)==0);server=true;}
|
||||
{F f;assert(f.service.AdmitDepot(&f.job,&f.item));assert(f.service.m_Stock.Count()==1&&f.service.m_Stock[0]==&f.item&&f.service.audits==1);assert(!f.service.AdmitDepot(&f.job,&f.item));ERR_FiniteMagazineReservation outgoing(&f.service.m_Stock,&f.service.m_Spent,&f.item);assert(outgoing.Reserve()&&outgoing.Commit());assert(f.spent.Count()==1&&f.service.m_Spent.Count()==1);assert(!f.service.AdmitDepot(&f.job,&f.item));}
|
||||
// Deleted identities and mine-only spent entries cannot create magazine demand.
|
||||
{F f;f.service.m_Stock={nullptr};f.service.m_Spent={nullptr,&f.foreign};assert(!f.service.DepotNeeded());f.service.m_Stock.Insert(&f.foreign);assert(f.service.DepotNeeded());f.service.m_DepotImports=1;assert(!f.service.DepotNeeded());Entity another;f.service.m_Stock.Insert(&another);f.service.m_Spent.Insert(&another);assert(f.service.DepotNeeded());}
|
||||
// Final lifetime slot can complete delivery and departure; admission then closes.
|
||||
{F f;f.service.m_Stock.resize(95,&f.foreign);f.service.m_Spent={&f.foreign};assert(f.service.DepotNeeded());assert(f.service.AdmitDepot(&f.job,&f.item));assert(f.service.m_Stock.Count()==96&&f.service.m_DepotImports==1);assert(f.service.DepotCurrent()&&!f.service.DepotAvailable()&&!f.service.DepotNeeded());}
|
||||
for(int bad=0;bad<21;bad++){F f;
|
||||
if(bad==0)f.service.current=false;
|
||||
if(bad==1)f.service.m_State=7;
|
||||
if(bad==2)f.service.m_Move=true;
|
||||
if(bad==3)f.service.m_MineMove=true;
|
||||
if(bad==4)f.service.unresolved=true;
|
||||
if(bad==5)f.mounted.busy=true;
|
||||
if(bad==6)f.service.truckValid=false;
|
||||
if(bad==7)f.service.m_Stock.resize(96,&f.foreign);
|
||||
if(bad==8)f.service.m_Spent.resize(96,&f.foreign);
|
||||
if(bad==9)f.service.m_Spent={&f.item};
|
||||
if(bad==10)f.service.cargo.clear();
|
||||
if(bad==11)f.job.m_Imported=true;
|
||||
if(bad==12)f.job.m_State=7;
|
||||
if(bad==13)f.job.m_Service=nullptr;
|
||||
if(bad==14)f.job.m_Item=&f.foreign;
|
||||
if(bad==15)f.proof.done=false;
|
||||
if(bad==16)f.proof.delivery=false;
|
||||
if(bad==17)f.job.m_Move=nullptr;
|
||||
if(bad==18)f.job.m_Reservation=nullptr;
|
||||
if(bad==19)f.job.valid=false;
|
||||
if(bad==20)f.spent.clear();
|
||||
int before=f.service.m_Stock.Count();assert(!f.service.AdmitDepot(&f.job,&f.item));assert(f.service.m_Stock.Count()==before&&f.service.audits==0);}
|
||||
{F f;f.job.m_State=7;f.proof.done=true;assert(!f.service.AdmitDepot(&f.job,&f.item));f.job.m_State=5;f.job.valid=false;assert(!f.service.AdmitDepot(&f.job,&f.item));}
|
||||
}
|
||||
''')
|
||||
print('PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption')
|
||||
@@ -0,0 +1,105 @@
|
||||
"""Execute complete actual finite two-leg transfer with native inventory boundaries."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,run
|
||||
from test_finite_magazine_reservation import translated_reservation
|
||||
p=Path(os.environ.get('ERR_GROUND_DEPOT_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c'))
|
||||
s=p.read_text();code=s[s.index('class ERR_GroundDepotTransfer\n'):]
|
||||
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('ref ','').replace('class ','struct ').replace('void ERR_GroundDepotTransfer(','ERR_GroundDepotTransfer(').replace('array<','Array<').replace('null','nullptr')
|
||||
for kind,field in {'InventoryStorageManagerComponent':'inventory','InventoryItemComponent':'item','BaseMagazineComponent':'magazine','DamageManagerComponent':'damage'}.items():
|
||||
code=re.sub(kind+r'\.Cast\(([^;\n]*?)\.FindComponent\('+kind+r'\)\)',lambda m:m[1]+'.'+field,code)
|
||||
code=code.replace('.FindComponent('+kind+')','.'+field)
|
||||
for name in ('EStoragePurpose','ERR_ForceRules','ERR_InfantryAmmoTransfer','ERR_InfantryMineTransfer'):code=code.replace(name+'.',name+'::')
|
||||
for name in ('m_Owner','m_From','m_To','m_Item','m_Source','m_Destination','m_FromSlot','m_FromStorage','m_ToStorage','m_Reservation','m_Callback','source','destination','item','inventoryItem','magazine','damage','inventory','storage','slot'):
|
||||
code=re.sub(r'\b'+name+r'\.',name+'->',code)
|
||||
code=code.replace(').',')->').replace('ERR_FiniteMagazineReservation ', 'ERR_FiniteMagazineReservation* ').replace('ERR_GroundDepotCallback ', 'ERR_GroundDepotCallback* ')
|
||||
code=re.sub(r'\b(bool|int|IEntity|ERR_GroundDepotLoading|InventoryStorageManagerComponent|InventoryStorageSlot|BaseInventoryStorageComponent|ERR_FiniteMagazineReservation\*|ERR_GroundDepotCallback\*) (\w+);',r'\1 \2{};',code)
|
||||
code=code.replace('\n}\n','\n};\n')
|
||||
callbacks=[]
|
||||
for n in ('OnComplete','OnAllComplete','OnFailed','OnAllFailed'):
|
||||
b=re.search('protected override void '+n+r'\(\) (\{[^\n]+\})',s)[1]
|
||||
callbacks.append('void ERR_GroundDepotCallback::'+n+'() '+b.replace('Transfer.','Transfer->'))
|
||||
pre=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}void Insert(T x){this->push_back(x);}void RemoveItem(T x){this->erase(std::remove(this->begin(),this->end(),x),this->end());}};
|
||||
struct Entity;struct Inventory;struct Slot;struct Storage;struct Magazine;struct Owner;
|
||||
using IEntity=Entity*;using InventoryStorageManagerComponent=Inventory*;using InventoryStorageSlot=Slot*;using BaseInventoryStorageComponent=Storage*;using BaseMagazineComponent=Magazine*;using ERR_GroundDepotLoading=Owner*;
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};using InventoryItemComponent=Item*;
|
||||
struct Damage{bool destroyed=false;bool IsDestroyed(){return destroyed;}};using DamageManagerComponent=Damage*;
|
||||
struct Entity{Entity*parent=nullptr;Item*item=nullptr;Magazine*magazine=nullptr;Damage*damage=nullptr;Inventory*inventory=nullptr;bool mine=false,armed=false,defaultArmed=false,collision=true;};
|
||||
struct Slot{Storage*storage=nullptr;IEntity attached=nullptr;Storage*GetStorage(){return storage;}IEntity GetAttachedEntity(){return attached;}};
|
||||
struct Storage{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
|
||||
struct Magazine{bool used=false,well=true;int rounds=30,capacity=30;bool IsUsed(){return used;}bool GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}};
|
||||
struct ERR_ForceRules{static bool Finite(float x){return std::isfinite(x);}};
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity e,IEntity root){for(int i=0;e&&i<16;i++,e=e->parent)if(e==root)return true;return false;}};
|
||||
// ReadyMine is an explicit native-component boundary; its complete implementation
|
||||
// is covered by infantry mine transfer tests. This models exact inert PMN4 state.
|
||||
struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity e){return e&&e->mine&&e->damage&&!e->damage->destroyed&&!e->armed&&!e->defaultArmed&&e->collision;}};
|
||||
struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
|
||||
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnAllComplete(){}virtual void OnFailed(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
|
||||
struct ERR_GroundDepotTransfer;
|
||||
struct ERR_GroundDepotCallback:ScriptedInventoryOperationCallback{ERR_GroundDepotTransfer*Transfer=nullptr;void OnComplete()override;void OnAllComplete()override;void OnFailed()override;void OnAllFailed()override;};
|
||||
struct Owner{bool valid=true,claimed=false;int claims=0;bool TransferValid(ERR_GroundDepotTransfer*){return valid;}bool ClaimDelivery(ERR_GroundDepotTransfer*){claims++;if(claimed)return false;claimed=true;return true;}};
|
||||
struct Inventory{IEntity owner=nullptr;Array<IEntity>items;Array<Storage*>storages;Storage*selected=nullptr;bool allow=true,accept=true;int calls=0,ack=0;ScriptedInventoryOperationCallback*last=nullptr;std::function<void()>effect;
|
||||
IEntity GetOwner(){return owner;}void GetItems(Array<IEntity>&a,int){a=items;}void GetStorages(Array<Storage*>&a,int){a=storages;}Storage*FindStorageForItem(IEntity,int){return selected;}
|
||||
bool CanMoveItemToStorage(IEntity,Storage*,int){return allow;}
|
||||
bool TryMoveItemToStorage(IEntity,Storage*,int,ScriptedInventoryOperationCallback*cb){calls++;last=cb;if(effect)effect();if(ack==1)cb->OnComplete();if(ack==-1)cb->OnFailed();return accept;}};
|
||||
'''
|
||||
main=r'''
|
||||
struct Fixture{bool mine=false;Owner owner;Entity cache,porter,truck,mag,foreign;Inventory source,carry,cargo;Storage cs,ps,ts;Slot cslot,pslot,tslot;Item item;Magazine magazine;Damage damage;Array<IEntity>original,spent;ERR_FiniteMagazineReservation reservation;
|
||||
Fixture():reservation(&original,&spent,&mag){cache.inventory=&source;porter.inventory=&carry;truck.inventory=&cargo;source.owner=&cache;carry.owner=&porter;cargo.owner=&truck;cs.owner=&cache;ps.owner=&porter;ts.owner=&truck;source.storages={&cs};carry.storages={&ps};cargo.storages={&ts};carry.selected=&ps;cargo.selected=&ts;cslot.storage=&cs;pslot.storage=&ps;tslot.storage=&ts;cslot.attached=&mag;item.slot=&cslot;mag.item=&item;mag.magazine=&magazine;mag.damage=&damage;source.items={&mag};original={&mag};assert(reservation.Reserve());}
|
||||
ERR_GroundDepotTransfer Pickup(){return {&owner,&cache,&porter,&mag ,&reservation,false,mine};}
|
||||
ERR_GroundDepotTransfer Delivery(){return {&owner,&porter,&truck,&mag ,&reservation,true,mine};}
|
||||
void Pick(){source.items.clear();carry.items={&mag};cslot.attached=nullptr;pslot.attached=&mag;item.slot=&pslot;}
|
||||
void Deliver(){carry.items.clear();cargo.items={&mag};pslot.attached=nullptr;tslot.attached=&mag;item.slot=&tslot;}
|
||||
};
|
||||
int main(){
|
||||
// Ready inert PMN4 uses the same exact native two-leg custody protocol,
|
||||
// shared reservation and isolated callbacks, without a magazine component.
|
||||
{Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto a=f.Pickup();assert(a.MineCargo()&&a.Tick(0)==0&&a.Unresolved());f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==1&&a.Confirmed());auto b=f.Delivery();assert(b.MineCargo()&&b.Tick(2)==0&&f.owner.claims==1);f.Deliver();f.carry.last->OnComplete();assert(b.Tick(3)==1&&b.Confirmed()&&!b.Unresolved()&&f.spent.Count()==1);}
|
||||
// Every phase refuses changed/armed/default-armed/non-PMN4/destroyed identity.
|
||||
for(int phase=0;phase<3;phase++)for(int kind=0;kind<5;kind++){Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto a=f.Pickup();
|
||||
if(phase==1)assert(a.Tick(0)==0);
|
||||
if(phase==2){assert(a.Tick(0)==0);f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==1);}
|
||||
if(kind==0)f.mag.armed=true;
|
||||
if(kind==1)f.mag.defaultArmed=true;
|
||||
if(kind==2)f.mag.mine=false;
|
||||
if(kind==3)f.damage.destroyed=true;
|
||||
if(kind==4)f.mag.collision=false;
|
||||
if(phase==2){auto b=f.Delivery();assert(b.Tick(2)==-1&&!b.Submitted()&&f.carry.calls==0&&!a.Confirmed());}
|
||||
else{assert(a.Tick(1)==-1);assert(f.source.calls==(phase==1?1:0));if(phase==1)assert(a.Unresolved());}
|
||||
}
|
||||
// Inline native mutation after initial ready check cannot promote success.
|
||||
{Fixture f;f.mine=f.mag.mine=true;auto a=f.Pickup();f.source.ack=1;f.source.effect=[&]{f.Pick();f.mag.armed=true;};assert(a.Tick(0)==-1&&!a.Confirmed()&&!a.Unresolved());}
|
||||
{Fixture f;f.mine=f.mag.mine=true;auto a=f.Pickup();assert(a.Tick(0)==0);a.Stop();f.Pick();f.source.last->OnComplete();assert(a.Tick(1)==-1&&!a.Confirmed()&&!a.Unresolved()&&f.source.calls==1&&f.spent.Count()==1);}
|
||||
{Fixture f;f.mine=f.mag.mine=true;f.source.accept=false;auto a=f.Pickup();assert(a.Tick(0)==-1&&a.Unresolved());f.damage.destroyed=true;assert(a.Unresolved());a.m_Item=nullptr;assert(!a.Unresolved()&&f.spent.Count()==1);}
|
||||
{Fixture f;f.mine=f.mag.mine=true;f.mag.magazine=nullptr;auto wrong=ERR_GroundDepotTransfer(&f.owner,&f.cache,&f.porter,&f.mag,&f.reservation,false,false);assert(wrong.Tick(0)==-1&&!wrong.Submitted()&&f.source.calls==0);}
|
||||
|
||||
{Fixture f;auto a=f.Pickup();a.Acknowledge(true);assert(a.m_Ack==0);assert(a.Tick(0)==0&&a.Submitted()&&a.Unresolved());assert(f.reservation.CommittedFor(&f.mag));f.source.last->OnComplete();assert(a.Tick(1)==0);f.Pick();assert(a.Tick(2)==1&&a.Confirmed()&&!a.Unresolved());auto b=f.Delivery();assert(b.Tick(3)==0&&f.owner.claims==1);f.source.last->OnAllComplete();assert(b.Tick(4)==0);f.Deliver();assert(b.Tick(5)==0);f.carry.last->OnAllComplete();assert(b.Tick(6)==1&&b.Confirmed()&&!b.Unresolved());assert(f.source.calls==1&&f.carry.calls==1&&f.spent.Count()==1);}
|
||||
{Fixture f;f.source.ack=1;f.source.accept=false;f.source.effect=[&]{assert(f.reservation.CommittedFor(&f.mag));assert(!f.reservation.ReleaseUnsubmitted());f.Pick();};auto a=f.Pickup();assert(a.Tick(0)==1&&!a.Unresolved());}
|
||||
{Fixture f;f.source.accept=false;auto a=f.Pickup();assert(a.Tick(0)==-1&&a.Unresolved());a.Stop();f.Pick();f.source.last->OnComplete();assert(!a.Unresolved()&&!a.Confirmed()&&a.Tick(1)==-1);}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);a.Stop();f.Pick();f.source.last->OnComplete();assert(!a.Unresolved()&&!a.Confirmed()&&a.Tick(1)==-1);}
|
||||
{Fixture f;auto a=f.Pickup();f.source.ack=1;f.source.effect=[&]{a.Stop();f.Pick();};assert(a.Tick(0)==-1&&!a.Confirmed()&&!a.Unresolved());}
|
||||
{Fixture f;auto a=f.Pickup();f.source.ack=1;f.source.effect=[&]{f.owner.valid=false;f.Pick();};assert(a.Tick(0)==-1&&!a.Confirmed()&&!a.Unresolved());}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);f.source.last->OnComplete();f.source.last->OnFailed();assert(a.Tick(1)==-1&&!a.Unresolved());f.source.last->OnAllComplete();assert(a.Tick(2)==-1);}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);f.item.slot=nullptr;f.source.last->OnFailed();assert(a.Tick(1)==-1&&a.Unresolved());}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);assert(a.Tick(8000)==-1&&a.Unresolved());assert(f.source.calls==1&&!f.reservation.ReleaseUnsubmitted());}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(10);assert(a.Tick(9)==-1&&a.Unresolved());}
|
||||
{Fixture f;auto a=f.Pickup();a.Stop();assert(a.Tick(0)==-1&&!a.Submitted()&&f.reservation.ReleaseUnsubmitted());}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);a.m_Item=nullptr;assert(a.Tick(1)==-1&&!a.Unresolved()&&f.spent.Count()==1);}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);f.damage.destroyed=true;assert(a.Tick(1)==-1&&a.Unresolved());}
|
||||
for(int bad=0;bad<15;bad++){Fixture f;auto a=f.Pickup();switch(bad){case0:break;}
|
||||
if(bad==0)f.magazine.used=true;if(bad==1)f.magazine.rounds=0;if(bad==2)f.magazine.capacity=100001;if(bad==3)f.damage.destroyed=true;if(bad==4)f.owner.valid=false;if(bad==5)f.source.allow=false;if(bad==6)f.carry.selected=nullptr;if(bad==7)f.cslot.attached=&f.foreign;if(bad==8)f.item.slot=&f.pslot;if(bad==9)f.source.items.clear();if(bad==10)f.carry.items={&f.mag};if(bad==11)f.carry.storages.clear();if(bad==12)f.carry.owner=&f.foreign;if(bad==13)f.source.items.resize(129,&f.mag);if(bad==14)f.source.storages.resize(65,&f.cs);
|
||||
assert(a.Tick(0)==-1&&!a.Submitted()&&f.source.calls==0&&f.reservation.ReleaseUnsubmitted());}
|
||||
{Fixture f;auto a=f.Pickup();a.Tick(0);f.magazine.rounds--;assert(a.Tick(1)==-1&&a.Unresolved());}
|
||||
{Fixture f;f.Pick();assert(f.reservation.Commit());auto a=f.Delivery();a.Tick(0);auto b=f.Delivery();assert(b.Tick(1)==-1&&!b.Submitted()&&f.carry.calls==1);}
|
||||
}
|
||||
'''.replace('switch(bad){case0:break;}','')
|
||||
main=main.replace(';if(bad', ';\n if(bad')
|
||||
run(pre+translated_reservation()+code+'\n'.join(callbacks)+main)
|
||||
print('PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified')
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user