Require physical ammo access and prove finite native infantry transfer
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
// Physical reach to authored donor storage contexts; no inventory mutation here.
|
||||
class ERR_InfantryAmmoAccess
|
||||
{
|
||||
protected IEntity m_Donor;
|
||||
protected IEntity m_Recipient;
|
||||
// Exact hierarchy exclusion prevents the truck's own cargo shell or recipient
|
||||
// equipment from occluding an interior-authored anchor. Other entities collide.
|
||||
protected bool Filter(notnull IEntity entity)
|
||||
{
|
||||
return !ERR_ConvoyRules.PartOf(entity, m_Donor) && !ERR_ConvoyRules.PartOf(entity, m_Recipient);
|
||||
}
|
||||
static bool Points(Vehicle donor, out array<vector> points)
|
||||
{
|
||||
points = {};
|
||||
if (!donor) return false;
|
||||
ActionsManagerComponent manager = ActionsManagerComponent.Cast(donor.FindComponent(ActionsManagerComponent));
|
||||
if (!manager || !manager.IsEnabled()) return false;
|
||||
array<UserActionContext> contexts = {}; manager.GetContextList(contexts);
|
||||
if (contexts.IsEmpty() || contexts.Count() > 64) return false;
|
||||
foreach (UserActionContext context : contexts)
|
||||
{
|
||||
if (!context) return false;
|
||||
array<BaseUserAction> actions = {}; context.GetActionsList(actions);
|
||||
if (actions.Count() > 16) return false;
|
||||
bool storage;
|
||||
foreach (BaseUserAction action : actions)
|
||||
if (action && action.GetOwner() == donor && SCR_OpenVehicleStorageAction.Cast(action)) storage = true;
|
||||
if (!storage) continue;
|
||||
vector matrix[4];
|
||||
if (!context.GetTransformationWorld(matrix) || !ERR_ForceRules.FiniteVector(matrix[3])) return false;
|
||||
points.Insert(matrix[3]);
|
||||
}
|
||||
return !points.IsEmpty();
|
||||
}
|
||||
bool Check(Vehicle donor, IEntity recipient)
|
||||
{
|
||||
ChimeraCharacter character = ChimeraCharacter.Cast(recipient);
|
||||
if (!donor || !character || !GetGame() || !GetGame().GetWorld()) return false;
|
||||
array<vector> points;
|
||||
if (!Points(donor, points)) return false;
|
||||
vector start = character.AimingPosition();
|
||||
if (!ERR_ForceRules.FiniteVector(start)) return false;
|
||||
m_Donor = donor; m_Recipient = recipient;
|
||||
foreach (vector point : points)
|
||||
{
|
||||
float distance = vector.Distance(start, point);
|
||||
if (!(distance >= 0.05 && distance <= 4)) continue;
|
||||
TraceParam trace = new TraceParam();
|
||||
trace.Start = start; trace.End = point;
|
||||
trace.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
|
||||
trace.LayerMask = TRACE_LAYER_CAMERA;
|
||||
float fraction = GetGame().GetWorld().TraceMove(trace, Filter);
|
||||
if (fraction == 1) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool Clear(Vehicle donor, IEntity recipient)
|
||||
{
|
||||
ERR_InfantryAmmoAccess access = new ERR_InfantryAmmoAccess();
|
||||
return access.Check(donor, recipient);
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,7 @@ class ERR_InfantryAmmoTransfer
|
||||
if (!item || !item.GetParentSlot() || !ManagedStorage(m_Source, item.GetParentSlot().GetStorage(), m_Donor)) return Fail("exact source magazine storage does not belong to original donor");
|
||||
m_Storage = m_Destination.FindStorageForItem(m_Magazine, EStoragePurpose.PURPOSE_DEPOSIT);
|
||||
if (!ManagedStorage(m_Destination, m_Storage, m_Recipient) || !m_Source.CanMoveItemToStorage(m_Magazine, m_Storage, -1)) return Fail("recipient has no native compatible available storage");
|
||||
if (!ERR_InfantryAmmoAccess.Clear(m_Donor, m_Recipient)) return Fail("no unobstructed physical reach to an authored donor storage access point");
|
||||
m_Callback = new ERR_InfantryAmmoCallback(); m_Callback.Transfer = this;
|
||||
m_Submitted = true;
|
||||
m_Accepted = m_Source.TryMoveItemToStorage(m_Magazine, m_Storage, -1, m_Callback);
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#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<IEntity> 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<IEntity> 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<UserActionContext> 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<BaseUserAction> 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<vector> access;
|
||||
if (!ERR_InfantryAmmoAccess.Points(m_Truck.Entity, access)) { AccessDiagnostic(); return -1; }
|
||||
vector transform[4]; m_Truck.Entity.GetTransform(transform);
|
||||
array<vector> 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<IEntity> 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<IEntity> 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
|
||||
@@ -19,6 +19,8 @@ modded class ERR_GameMode
|
||||
protected bool m_ERRTestHQMemory;
|
||||
protected bool m_ERRTestHQBody;
|
||||
protected ref ERR_NativeHQBodyProbe m_ERRHQBodyProbe;
|
||||
protected bool m_ERRTestInfantryTransfer;
|
||||
protected ref ERR_NativeInfantryTransferProbe m_ERRInfantryTransfer;
|
||||
protected bool m_ERRTestConvoy;
|
||||
protected ref ERR_NativeConvoyProbe m_ERRConvoyProbe;
|
||||
protected ref ERR_NativeHQMemoryProbe m_ERRHQMemoryProbe;
|
||||
@@ -62,6 +64,7 @@ modded class ERR_GameMode
|
||||
m_ERRTestHQResponse = outcome == "hq-response";
|
||||
m_ERRTestHQMemory = outcome == "hq-memory";
|
||||
m_ERRTestHQBody = outcome == "hq-body";
|
||||
m_ERRTestInfantryTransfer = outcome == "infantry-transfer";
|
||||
m_ERRTestConvoy = outcome == "convoy";
|
||||
m_ERRTestMortar = outcome == "mortar-inventory";
|
||||
m_ERRTestMapOwnership = outcome == "map-ownership";
|
||||
@@ -75,11 +78,12 @@ modded class ERR_GameMode
|
||||
m_ERRTestMortarSalvo = outcome == "mortar-salvo" || outcome == "mortar-refresh";
|
||||
m_ERRTestMortarTransfer = outcome == "mortar-transfer";
|
||||
m_ERRTestPatrolHQ = outcome == "patrol-hq";
|
||||
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar || m_ERRTestHQMemory || m_ERRTestHQBody || m_ERRTestConvoy;
|
||||
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar || m_ERRTestHQMemory || m_ERRTestHQBody || m_ERRTestConvoy || m_ERRTestInfantryTransfer;
|
||||
m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000;
|
||||
if (m_ERRTestConvoy) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 540000;
|
||||
if (ERR_NativeConvoyCoverProbe.Enabled()) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 840000;
|
||||
if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 360000;
|
||||
if (m_ERRTestInfantryTransfer) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 300000;
|
||||
if (m_ERRTestHQBody) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;
|
||||
if (m_ERRTestAircraftControl || m_ERRTestAircraftRoute || m_ERRTestAircraftField) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 330000;
|
||||
if (m_ERRTestMortarCourier) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 450000;
|
||||
@@ -513,6 +517,13 @@ modded class ERR_GameMode
|
||||
m_ERRSmokeStep = 110;
|
||||
return;
|
||||
}
|
||||
if (m_ERRTestInfantryTransfer)
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
m_ERRInfantryTransfer = new ERR_NativeInfantryTransferProbe(this);
|
||||
OnStop().Insert(m_ERRInfantryTransfer.Stop);
|
||||
m_ERRSmokeStep = 108; return;
|
||||
}
|
||||
if (m_ERRTestConvoy)
|
||||
{
|
||||
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
|
||||
@@ -707,6 +718,18 @@ modded class ERR_GameMode
|
||||
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
|
||||
m_ERRSmokeWait = now + 4000;
|
||||
}
|
||||
else if (m_ERRSmokeStep == 108)
|
||||
{
|
||||
int result = m_ERRInfantryTransfer.Tick(ERR_HQ.Cast(Command()), now);
|
||||
if (result == 0) return;
|
||||
m_ERRInfantryTransfer.Stop();
|
||||
if (!ERR_Check(result == 1, "native exact infantry magazine transfer; controlled positioning only")) return;
|
||||
m_ERRSmokeStep = 9;
|
||||
SCR_CharacterDamageManagerComponent damage;
|
||||
damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
|
||||
damage.EnableDamageHandling(true); damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
|
||||
m_ERRSmokeWait = now + 4000;
|
||||
}
|
||||
else if (m_ERRSmokeStep == 107)
|
||||
{
|
||||
int result = m_ERRHQBodyProbe.Tick(ERR_HQ.Cast(Command()), now);
|
||||
|
||||
Reference in New Issue
Block a user