#ifdef WORKBENCH // Controlled native inventory boundary only: one existing actor is positioned // beside the existing convoy truck. This does not prove HQ rendezvous/navigation. modded class ERR_HQ { ERR_HQUnit ERR_InfantryFixtureRecipient(IEntity magazine) { if (!ERR_NativeInfantryTransferProbe.Enabled()) return null; foreach (ERR_HQUnit unit : m_Units) { if (!unit.Eligible(m_Mode) || unit.HomeGuard || !unit.StatusSampler.OwnsRoster(unit.Group)) continue; for (int slot = 0; slot < unit.StatusSampler.InitialStrength(); slot++) { IEntity actor = unit.StatusSampler.InitialMember(slot); if (!actor || !unit.StatusSampler.CanAttribute(slot, actor) || !ERR_Actors.CanFight(actor)) continue; if (!ERR_InfantryAmmoTransfer.Compatible(actor, magazine)) continue; InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent)); if (!inventory || !inventory.FindStorageForItem(magazine, EStoragePurpose.PURPOSE_DEPOSIT)) continue; if (ReserveLogistics(unit.Group, ERR_NativeInfantryTransferProbe.TOKEN)) return unit; } } return null; } } class ERR_NativeInfantryTransferProbe { static const int TOKEN = 200001; protected ERR_GameMode m_Mode; protected ERR_HQ m_HQ; protected ERR_ConvoyVehicle m_Truck; protected ERR_HQUnit m_Unit; protected IEntity m_Actor; protected IEntity m_Magazine; protected ref ERR_InfantryAmmoTransfer m_Move; protected vector m_OriginalPosition; protected int m_OriginalLedger; protected int m_DonorBefore; protected int m_RecipientBefore; protected int m_Rounds; protected float m_Deadline; protected int m_State; protected bool m_Positioned; protected bool m_PlacementStarted; protected bool m_PlacementPending; protected int m_PlacementIndex; protected float m_PlacementReadyAt; protected bool m_Stopped; protected bool m_Failed; static bool Enabled() { string smoke, outcome; return Replication.IsServer() && System.GetCLIParam("errSmoke", smoke) && smoke == "1" && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "infantry-transfer"; } void ERR_NativeInfantryTransferProbe(ERR_GameMode mode) { m_Mode = mode; } protected bool Check(bool condition, string detail) { if (condition) { Print("ERR SMOKE PASS: infantry transfer " + detail); return true; } m_Failed = true; Print("ERR SMOKE FAIL: infantry transfer " + detail, LogLevel.ERROR); Stop(); return false; } protected int MagazineCount(IEntity owner) { InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent)); if (!inventory) return -1; array items = {}; ERR_Inventory.Items(inventory, items); if (items.Count() > 128) return -1; int count; foreach (IEntity item : items) if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == ERR_ConvoyResources.Magazine()) count++; return count; } protected bool Has(IEntity owner, IEntity item) { InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent)); if (!inventory) return false; array items = {}; ERR_Inventory.Items(inventory, items); return items.Count() <= 128 && items.Contains(item); } protected bool RecipientOwned() { if (!m_Mode || !m_Unit || !m_Actor) return false; if (!m_Unit.StatusSampler || !m_Unit.StatusSampler.OwnsRoster(m_Unit.Group)) return false; if (!ERR_EnemyEquipmentRules.Eligible(m_Mode, m_Unit.Group, m_Actor) || CompartmentAccessComponent.GetVehicleIn(m_Actor)) return false; int strength = m_Unit.StatusSampler.InitialStrength(); if (strength < 1 || strength > 32) return false; for (int slot = 0; slot < strength; slot++) if (m_Unit.StatusSampler.InitialMember(slot) == m_Actor) return m_Unit.StatusSampler.CanAttribute(slot, m_Actor); return false; } protected void AccessDiagnostic() { ActionsManagerComponent manager = ActionsManagerComponent.Cast(m_Truck.Entity.FindComponent(ActionsManagerComponent)); PrintFormat("ERR INFANTRY ACCESS: root manager=%1", manager != null); if (!manager) return; array contexts = {}; manager.GetContextList(contexts); PrintFormat("ERR INFANTRY ACCESS: enabled=%1 contexts=%2", manager.IsEnabled(), contexts.Count()); for (int i = 0; i < contexts.Count() && i < 32; i++) { UserActionContext context = contexts[i]; if (!context) { Print("ERR INFANTRY ACCESS: null context"); continue; } vector matrix[4]; bool transformed = context.GetTransformationWorld(matrix); array actions = {}; context.GetActionsList(actions); PrintFormat("ERR INFANTRY ACCESS: context=%1 transform=%2 point=%3 actions=%4", i, transformed, matrix[3], actions.Count()); for (int j = 0; j < actions.Count() && j < 16; j++) { BaseUserAction action = actions[j]; if (action) PrintFormat("ERR INFANTRY ACCESS: action=%1 owner=%2 rootOwned=%3 storage=%4", action.Type().ToString(), action.GetOwner(), action.GetOwner() == m_Truck.Entity, SCR_OpenVehicleStorageAction.Cast(action) != null); } } } // -1: exhausted/refused; 0: awaiting one native character update; 1: observed clear access. protected int Place(float now) { if (!RecipientOwned()) return -1; if (!m_PlacementStarted) { m_PlacementStarted = true; m_OriginalPosition = m_Actor.GetOrigin(); } if (m_PlacementPending) { if (now < m_PlacementReadyAt) return 0; m_PlacementPending = false; ChimeraCharacter character = ChimeraCharacter.Cast(m_Actor); if (!character) return -1; PrintFormat("ERR INFANTRY TRANSFER: settledOrigin=%1 aiming=%2", m_Actor.GetOrigin(), character.AimingPosition()); if (ERR_InfantryAmmoAccess.Clear(m_Truck.Entity, m_Actor)) return 1; m_Actor.SetOrigin(m_OriginalPosition); } array access; if (!ERR_InfantryAmmoAccess.Points(m_Truck.Entity, access)) { AccessDiagnostic(); return -1; } vector transform[4]; m_Truck.Entity.GetTransform(transform); array offsets = {"2.5 0 -1.5", "-2.5 0 -1.5", "2.5 0 1.5", "-2.5 0 1.5"}; while (m_PlacementIndex < offsets.Count()) { vector offset = offsets[m_PlacementIndex++]; vector point = ERR_Actors.Ground(m_Truck.Entity.GetOrigin() + transform[0] * offset[0] + transform[2] * offset[2]); TraceBox body = new TraceBox(); body.Start = point + "0 0.95 0"; body.End = body.Start + "0 0.01 0"; body.Mins = "-0.3 -0.9 -0.3"; body.Maxs = "0.3 0.9 0.3"; body.Flags = TraceFlags.ENTS; array exclude = {m_Actor}; body.ExcludeArray = exclude; float fraction = GetGame().GetWorld().TraceMove(body, null); PrintFormat("ERR INFANTRY TRANSFER: candidate=%1 bodyFraction=%2", point, fraction); if (fraction != 1) continue; m_Actor.SetOrigin(point); // Mark any controlled move for Stop restoration, including an unsettled or // subsequently rejected placement. Never replace the saved original position. m_Positioned = true; m_PlacementPending = true; m_PlacementReadyAt = now + 250; return 0; } return -1; } int Tick(ERR_HQ hq, float now) { if (!Enabled() || m_Stopped || m_Failed || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return -1; m_HQ = hq; if (!hq) return -1; if (m_Deadline == 0) m_Deadline = now + 180000; if (now >= m_Deadline) { Check(false, "bounded fixture deadline"); return -1; } if (m_State == 0) { ERR_ConvoyTask task = hq.ConvoyTask(); if (!task || !task.Ready) return 0; if (!Check(!task.Stopped && task.Vehicles.Count() == 6 && task.CargoIssued && task.Cargo.Count() == 56, "existing automatic convoy and finite startup cargo are ready")) return -1; foreach (ERR_ConvoyCargoCallback operation : task.Cargo) if (!operation || !operation.Finished) return 0; m_Truck = task.Vehicles[1]; if (!Check(m_Truck.CrewValid(m_Mode) && m_Truck.SupplyToken == 0 && !m_Truck.Combat.Held, "original ammo truck is available for isolated inventory fixture")) return -1; InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(m_Truck.Entity.FindComponent(InventoryStorageManagerComponent)); array stock = {}; ERR_Inventory.Items(inventory, stock); foreach (IEntity candidate : stock) { if (!candidate || !candidate.GetPrefabData() || candidate.GetPrefabData().GetPrefabName() != ERR_ConvoyResources.Magazine()) continue; m_Unit = hq.ERR_InfantryFixtureRecipient(candidate); if (!m_Unit) break; m_Magazine = candidate; for (int slot = 0; slot < m_Unit.StatusSampler.InitialStrength(); slot++) { IEntity actor = m_Unit.StatusSampler.InitialMember(slot); if (!actor || !m_Unit.StatusSampler.CanAttribute(slot, actor) || !ERR_Actors.CanFight(actor) || !ERR_InfantryAmmoTransfer.Compatible(actor, candidate)) continue; InventoryStorageManagerComponent recipient = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent)); if (!recipient || !recipient.FindStorageForItem(candidate, EStoragePurpose.PURPOSE_DEPOSIT)) continue; m_Actor = actor; break; } break; } if (!Check(m_Unit && m_Actor && m_Magazine, "existing original patrol actor and compatible original truck magazine selected")) return -1; m_OriginalLedger = m_Mode.Forces().Count(); m_Truck.SupplyToken = TOKEN; m_Truck.SupplyHeld = true; m_Truck.ClearOrder(); m_State = 1; return 0; } if (!Check(m_Truck && m_Truck.CrewValid(m_Mode) && m_Truck.SupplyToken == TOKEN && RecipientOwned() && hq.LogisticsToken(m_Unit.Group) == TOKEN, "fixture retains original physical ownership")) return -1; if (m_State == 1) { Physics physics = m_Truck.Entity.GetPhysics(); if (!physics) return 0; float speed = physics.GetVelocity().Length(), angular = physics.GetAngularVelocity().Length(); if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1)) return 0; int placed = Place(now); if (placed == 0) return 0; if (!Check(placed == 1, "controlled existing actor placed at clear authored truck storage access after native pose update")) return -1; m_DonorBefore = MagazineCount(m_Truck.Entity); m_RecipientBefore = MagazineCount(m_Actor); BaseMagazineComponent magazine = BaseMagazineComponent.Cast(m_Magazine.FindComponent(BaseMagazineComponent)); if (!Check(magazine && m_DonorBefore > 0 && m_RecipientBefore >= 0 && Has(m_Truck.Entity, m_Magazine) && !Has(m_Actor, m_Magazine), "exact original magazine starts exclusively in original truck")) return -1; m_Rounds = magazine.GetAmmoCount(); m_Move = new ERR_InfantryAmmoTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, m_Actor, m_Unit.Group, m_Magazine); m_State = 2; } int result = m_Move.Tick(now); if (result == 0) return 0; if (!Check(result == 1, "production native move: " + m_Move.Reason())) return -1; if (!Check(m_Move.Submitted() && !m_Move.Unresolved() && !Has(m_Truck.Entity, m_Magazine) && Has(m_Actor, m_Magazine), "native callback and exact destination ownership agree")) return -1; BaseMagazineComponent moved = BaseMagazineComponent.Cast(m_Magazine.FindComponent(BaseMagazineComponent)); if (!Check(moved && moved.GetAmmoCount() == m_Rounds && MagazineCount(m_Truck.Entity) == m_DonorBefore - 1 && MagazineCount(m_Actor) == m_RecipientBefore + 1 && m_Mode.Forces().Count() == m_OriginalLedger, "one physical magazine moved without refill, duplicate or new forces")) return -1; Stop(); return 1; } void Stop() { if (m_Stopped) return; m_Stopped = true; if (m_Move) m_Move.Stop(); bool restore = false; if (m_HQ && m_Unit && m_HQ.LogisticsToken(m_Unit.Group) == TOKEN) restore = m_Positioned && (!m_Move || !m_Move.Unresolved()) && RecipientOwned(); if (m_HQ && m_Unit) m_HQ.ReleaseLogistics(m_Unit.Group, TOKEN); if (m_Truck && m_Truck.SupplyToken == TOKEN) { m_Truck.SupplyToken = 0; m_Truck.SupplyHeld = false; } // Never race an accepted uncertain operation with a position restore. if (restore) m_Actor.SetOrigin(m_OriginalPosition); } } #endif