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);
|
||||
|
||||
Reference in New Issue
Block a user