this took way too long

This commit is contained in:
Salluci 2023-07-01 18:39:42 +03:00
parent 01dffca9c1
commit aca90fb187
9 changed files with 87 additions and 72 deletions

View File

@ -20,4 +20,4 @@ if (someAmmo _staticWeapon) exitWith {};
TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon); TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon);
[_staticWeapon, _gunner, _weapon, _magazine] call FUNC(ai_reload); [_staticWeapon, _gunner, _weapon] call FUNC(ai_reload);

View File

@ -11,7 +11,7 @@
* *
* Public: No * Public: No
*/ */
params ["_staticWeapon", "_role", "_gunner"]; params ["_staticWeapon", "_role", "_gunner", "_turret"];
TRACE_3("getInEH:",_staticWeapon,_role,_gunner); TRACE_3("getInEH:",_staticWeapon,_role,_gunner);
if ((!local _gunner) || {[_gunner] call EFUNC(common,isPlayer)}) exitWith {}; if ((!local _gunner) || {[_gunner] call EFUNC(common,isPlayer)}) exitWith {};
@ -19,4 +19,7 @@ if (someAmmo _staticWeapon) exitWith {};
TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon); TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon);
[_staticWeapon, _gunner, currentWeapon _staticWeapon] call FUNC(ai_reload); // this doesn't handle multi-weapon turrets, need a "turretWeapon" event or a PFH to do that
private _weapon = (_staticWeapon weaponsTurret _turret) select 0;
[_staticWeapon, _gunner, weapon] call FUNC(ai_reload);

View File

@ -7,14 +7,14 @@
* 0: Static Weapon <OBJECT> * 0: Static Weapon <OBJECT>
* 1: Gunner <OBJECT> * 1: Gunner <OBJECT>
* 2: Weapon <STRING> * 2: Weapon <STRING>
* 3: Magazine <STRING> (default: "")
* *
* Return Value: * Return Value:
* None * None
* *
* Public: No * Public: No
*/ */
params ["_staticWeapon", "_gunner", "_weapon", ["_magazine", ""]]; params ["_staticWeapon", "_gunner", "_weapon"];
TRACE_4("AI reload",_staticWeapon,_gunner,_weapon);
private _turretPath = [_gunner] call EFUNC(common,getTurretIndex); private _turretPath = [_gunner] call EFUNC(common,getTurretIndex);
private _reloadSource = objNull; private _reloadSource = objNull;
@ -23,27 +23,29 @@ private _reloadNeededAmmo = -1;
private _cfgMagGroups = configFile >> QGVAR(groups); private _cfgMagGroups = configFile >> QGVAR(groups);
private _nearSupplies = [_gunner] + ((_staticWeapon nearSupplies 10) select { // see fnc_reload_getLoadableMagazines, but AI doesn't get filtered out
private _nearSupplies = (_staticWeapon nearSupplies 5) select {
isNull (group _x) || isNull (group _x) ||
{!([_x] call EFUNC(common,isPlayer)) && {[side group _gunner, side group _x] call BIS_fnc_sideIsFriendly}} {!([_x] call EFUNC(common,isPlayer)) && {[side group _gunner, side group _x] call BIS_fnc_sideIsFriendly}}
}); };
// add gunner since it won't show up in nearSupplies
_nearSupplies pushBack _gunner;
// Find if there is anything we can reload with // Find if there is anything we can reload with
// see fnc_reload_getLoadableMagazines, though we don't care about AI pulling from the best ammo possible
{ {
scopeName "findSource"; scopeName "findSource";
if (_x isKindOf "CAManBase") then {
// unit inventory needs to be added manually
_nearSupplies append [uniformContainer _x, vestContainer _x, backpackContainer _x];
continue
};
private _xSource = _x; private _xSource = _x;
private _cswMagazines = []; private _cswMagazines = (magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)};
{
_cswMagazines pushBackUnique _x;
} forEach ((magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)});
TRACE_2("",_xSource,_cswMagazines); TRACE_2("",_xSource,_cswMagazines);
private _compatibleMags = [_weapon] call CBA_fnc_compatibleMagazines;
if (_magazine != "") then {
_compatibleMags insert [0, [_magazine]];
};
{ {
private _xWeaponMag = _x; private _xWeaponMag = _x;
{ {
@ -58,7 +60,7 @@ private _nearSupplies = [_gunner] + ((_staticWeapon nearSupplies 10) select {
}; };
}; };
} forEach _cswMagazines; } forEach _cswMagazines;
} forEach _compatibleMags; } forEach (compatibleMagazines _weapon);
} forEach _nearSupplies; } forEach _nearSupplies;
if (_reloadMag == "") exitWith {TRACE_1("could not find mag",_reloadMag);}; if (_reloadMag == "") exitWith {TRACE_1("could not find mag",_reloadMag);};
@ -79,17 +81,21 @@ if (_bestAmmoToSend == -1) exitWith {ERROR("No ammo");};
// Remove the mag from the source // Remove the mag from the source
[_reloadSource, _reloadMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine); [_reloadSource, _reloadMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine);
// see fnc_reload_loadMagazine #L54
// AI never returns ammo and removes the magazine before reloading, so we can skip distance and weaponHolder checks
private _eventParams = [_staticWeapon, _turretPath, objNull, _reloadMag, _bestAmmoToSend, _gunner];
private _timeToLoad = 1; private _timeToLoad = 1;
if (!isNull(configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime")) then { if !(isNull (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime")) then {
_timeToLoad = getNumber (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime"); _timeToLoad = getNumber (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime");
}; };
TRACE_1("Reloading in progress",_timeToLoad); TRACE_1("Reloading in progress",_timeToLoad);
[{ [{
params ["_staticWeapon", "_turretPath", "_gunner", "_reloadMag", "_bestAmmoToSend"]; params ["_staticWeapon", "", "", "", "", "_gunner"];
if ((!alive _staticWeapon) || {!alive _gunner} || {(_staticWeapon distance _gunner) > 10}) exitWith {TRACE_1("invalid state",_this);}; if !(alive _staticWeapon && {alive _gunner}) exitWith {TRACE_2("invalid state",alive _staticWeapon,alive _gunner);};
// Reload the static weapon // Reload the static weapon
TRACE_5("calling addTurretMag event",_staticWeapon,_turretPath,_gunner,_reloadMag,_bestAmmoToSend); TRACE_5("calling addTurretMag event: AI reload",_staticWeapon,_turretPath,_gunner,_reloadMag,_bestAmmoToSend);
[QGVAR(addTurretMag), _this] call CBA_fnc_globalEvent; [QGVAR(addTurretMag), _this] call CBA_fnc_globalEvent;
}, [_staticWeapon, _turretPath, _gunner, _reloadMag, _bestAmmoToSend], _timeToLoad] call CBA_fnc_waitAndExecute; }, _eventParams, _timeToLoad] call CBA_fnc_waitAndExecute;

View File

@ -7,7 +7,7 @@
* 0: Static Weapon <OBJECT> * 0: Static Weapon <OBJECT>
* 1: Turret Path <ARRAY> * 1: Turret Path <ARRAY>
* 2: Carryable Magazine <STRING> * 2: Carryable Magazine <STRING>
* 3: Supplier <OBJECT> * 3: Supplier <OBJECT> (default: objNull)
* *
* Return Value: * Return Value:
* [CanLoad<BOOL>, LoadedMag<STRING>, AmmoNeeded<NUMBER>, IsBeltLinking<BOOL>]<ARRAY> * [CanLoad<BOOL>, LoadedMag<STRING>, AmmoNeeded<NUMBER>, IsBeltLinking<BOOL>]<ARRAY>
@ -24,16 +24,16 @@ params ["_vehicle", "_turret", "_carryMag", ["_magSource", objNull]];
private _return = [false, "", -2, false]; private _return = [false, "", -2, false];
// Handle disassembled or deleted // Handle disassembled or deleted
if (!alive _vehicle) exitWith { _return }; if !(alive _vehicle) exitWith {TRACE_1("not alive",_vehicle);_return};
// objNull as mag source means we can skip these checks: used to just get magazine info to load in turret
if !(isNull _magSource) then {
// Verify holder has carry magazine // Verify holder has carry magazine
if ( if !(_carryMag in (magazineCargo _magSource)) exitWith {TRACE_3("no carry mag",_magSource,_carryMag,magazineCargo _magSource);_return};
(!isNull _magSource) &&
{!((_magSource isKindOf "Bag_Base") || {_magSource isKindOf "ContainerSupply"})} && // hacky workaround for magazines within dropped backpacks // Verify holder has not moved away from vehicle, with workaround for containers within containers
{ if ((_vehicle distance _magSource) > 5 && {(_vehicle distance (objectParent _magSource)) > 5}) exitWith {TRACE_1("too far","");_return};
((_vehicle distance _magSource) > 10) || };
{((magazineCargo _magSource) findIf {_x == _carryMag}) == -1}
}
) exitWith { _return };
// solve config lookups // solve config lookups
private _cfgMagazines = configFile >> "CfgMagazines"; private _cfgMagazines = configFile >> "CfgMagazines";

View File

@ -1,7 +1,7 @@
#include "script_component.hpp" #include "script_component.hpp"
/* /*
* Author: PabstMirror * Author: PabstMirror, LinkIsGrim
* Gets magazines that the player is carrying that can be loaded into the static weapon * Gets nearby magazines that can be loaded in the static weapon
* *
* Arguments: * Arguments:
* 0: Vehicle <OBJECT> * 0: Vehicle <OBJECT>
@ -23,30 +23,39 @@ private _magGroupsConfig = configFile >> QGVAR(groups); // so we don't solve in
private _availableMagazines = createHashMap; // slower than array, still needed for setting source of magazine private _availableMagazines = createHashMap; // slower than array, still needed for setting source of magazine
// filter enemy & player units while allowing pulling from friendly AI, crates, etc // filter enemy & player units while allowing pulling from friendly AI, crates, etc
private _nearSupplies = ((_vehicle nearSupplies 10) select { private _nearSupplies = (_vehicle nearSupplies 5) select {
isNull (group _x) || isNull (group _x) ||
{!([_x] call EFUNC(common,isPlayer)) && {[side group _player, side group _x] call BIS_fnc_sideIsFriendly}} {!([_x] call EFUNC(common,isPlayer)) && {[side group _player, side group _x] call BIS_fnc_sideIsFriendly}}
}); };
// add caller to nearSupplies since players will get filtered out
_nearSupplies pushBack _player;
// send the mag source with the highest ammo
private _bestMagAmmo = createHashMap;
// backpacks/uniforms/etc need to be added manually.
// array can't be modified while iterating, use copy
{ {
if (_x isKindOf "CAManBase") then {
// unit inventory needs to be added manually
_nearSupplies append [uniformContainer _x, vestContainer _x, backpackContainer _x];
continue;
};
private _xSource = _x;
private _cswMags = (magazinesAmmoCargo _xSource) select {isClass (_magGroupsConfig >> _x select 0)};
// add containers inside containers
{ {
_x params ["_classname", "_container"]; _x params ["_classname", "_container"];
_nearSupplies pushBack _container; _nearSupplies pushBack _container;
} forEach (everyContainer _x); } forEach (everyContainer _x);
} forEach ((+_nearSupplies) select {(everyContainer _x) isNotEqualTo []});
// add caller to list of sources
_nearSupplies = [_player] + _nearSupplies;
{ {
private _xSource = _x; _x params ["_classname", "_ammo"];
private _mags = magazineCargo _xSource; if (_ammo > (_bestMagAmmo getOrDefault [_classname, 0])) then {
_bestMagAmmo set [_classname, _ammo];
{ _availableMagazines set [_classname, _xSource];
_availableMagazines set [_x, _xSource]; };
} forEach (_mags select {isClass (_magGroupsConfig >> _x)}); } forEach _cswMags;
} forEach _nearSupplies; } forEach _nearSupplies;
if (_availableMagazines isEqualTo createHashMap) exitWith { [] }; // fast exit if no available mags if (_availableMagazines isEqualTo createHashMap) exitWith { [] }; // fast exit if no available mags
@ -68,9 +77,9 @@ private _return = [];
((getNumber (_carryGroup >> _x)) == 1) && ((getNumber (_carryGroup >> _x)) == 1) &&
{_loadInfo = [_vehicle, _turretPath, _carryMag, _magSource] call FUNC(reload_canLoadMagazine); _loadInfo select 0} {_loadInfo = [_vehicle, _turretPath, _carryMag, _magSource] call FUNC(reload_canLoadMagazine); _loadInfo select 0}
) exitWith { ) exitWith {
_return pushBack [_carryMag, _turretPath, _loadInfo, _magSource]; _return pushBack [_carryMag, _turretPath, _loadInfo, _magSource, _player];
}; };
} forEach ([_weapon] call CBA_fnc_compatibleMagazines); } forEach (compatibleMagazines _weapon);
} forEach _availableMagazines; } forEach _availableMagazines;
} forEach (_vehicle weaponsTurret _turretPath); } forEach (_vehicle weaponsTurret _turretPath);
} forEach (allTurrets _vehicle); } forEach (allTurrets _vehicle);

View File

@ -10,7 +10,8 @@
* 2: Source of magazine <OBJECT> * 2: Source of magazine <OBJECT>
* 3: Vehicle Magazine <STRING> * 3: Vehicle Magazine <STRING>
* 4: Ammo in magazine <NUMBER> * 4: Ammo in magazine <NUMBER>
* 5: Unit or object to return ammo to <OBJECT> (default: Source of magazine) * 5: Unit that added the magazine <OBJECT>
* 6: Object to return extra ammo <OBJECT> (default: Unit that added the magazine)
* *
* Return Value: * Return Value:
* None * None
@ -21,9 +22,9 @@
* Public: No * Public: No
*/ */
params ["_vehicle", "_turret", "_magSource", "_carryMag", "_ammoReceived"]; params ["_vehicle", "_turret", "_magSource", "_carryMag", "_ammoReceived", "_unit"];
private _returnTo = param [5, _magSource]; private _returnTo = param [6, _unit];
TRACE_6("reload_handleAddTurretMag",_vehicle,_turret,_magSource,_carryMag,_ammoReceived,_returnTo); TRACE_7("reload_handleAddTurretMag",_vehicle,_turret,_magSource,_carryMag,_ammoReceived,_unit,_returnTo);
TRACE_2("",local _vehicle, _vehicle turretLocal _turret); TRACE_2("",local _vehicle, _vehicle turretLocal _turret);
if (!(_vehicle turretLocal _turret)) exitWith {}; if (!(_vehicle turretLocal _turret)) exitWith {};

View File

@ -43,9 +43,9 @@ if ((_fullMagazines == 0) && {_bulletsRemaining == 0}) exitWith {};
private _container = [_unloadTo, objNull] select _unloadToUnit; private _container = [_unloadTo, objNull] select _unloadToUnit;
if ((maxLoad _container) isEqualTo 0) then { if ((maxLoad _container) isEqualTo 0) then {
_container = _unloadTo getVariable [QGVAR(container), objNull]; _container = _unloadTo getVariable [QGVAR(container), objNull];
if ((_container distance _unloadTo) > 10) then { _container = objNull; }; if ((_container distance _unloadTo) > 5) then { _container = objNull; };
if (isNull _container) then { if (isNull _container) then {
_container = (nearestObjects [_unloadTo, [QGVAR(ammo_holder), "GroundWeaponHolder"], 10]) param [0, objNull]; _container = (nearestObjects [_unloadTo, [QGVAR(ammo_holder), "GroundWeaponHolder"], 5]) param [0, objNull];
}; };
}; };

View File

@ -51,25 +51,21 @@ private _onFinish = {
[_magSource, _carryMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine); [_magSource, _carryMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine);
if (_bestAmmoToSend == 0) exitWith {}; if (_bestAmmoToSend == 0) exitWith {};
// workaround for removeSpecificMagazine and WeaponHolders being deleted when empty, get the closest object of same type on the next frame private _returnTo = _magSource;
private _magSourcePos = getPosATL _magSource; // if we're pulling from a weaponHolder, return the ammo to the unit doing the action
private _magSourceType = typeOf _magSource; // workaround for weaponHolders being recreated with removeSpecificMagazine, magazines will still get dropped if inventory is full
private _eventParams = [_vehicle, _turret, objNull, _carryMag, _bestAmmoToSend]; if (_magSource isKindOf "WeaponHolder") then {
[{ _returnTo = _unit;
params ["_args", "_magSourcePos", "_magSourceType"]; };
_args params ["_vehicle", "_turret", "_magSource", "_carryMag", "_bestAmmoToSend"];
_magSource = _magSourcePos nearestObject _magSourceType;
TRACE_6("calling addTurretMag event",_vehicle,_turret,_magSource,_carryMag,_bestAmmoToSend, _unit); TRACE_6("calling addTurretMag event",_vehicle,_turret,_magSource,_carryMag,_bestAmmoToSend, _unit);
[QGVAR(addTurretMag), [_vehicle, _turret, _magSource, _carryMag, _bestAmmoToSend, _unit]] call CBA_fnc_globalEvent; [QGVAR(addTurretMag), [_vehicle, _turret, _magSource, _carryMag, _bestAmmoToSend, _unit, _returnTo]] call CBA_fnc_globalEvent;
}, [_eventParams, _magSourcePos, _magSourceType]] call CBA_fnc_execNextFrame;
}; };
[ [
TIME_PROGRESSBAR(_timeToLoad), TIME_PROGRESSBAR(_timeToLoad),
[_vehicle, _turret, _carryMag, _magSource], [_vehicle, _turret, _carryMag, _magSource, _unit],
_onFinish, _onFinish,
{TRACE_1("load progressBar fail",_this);}, {TRACE_1("load progressBar fail",_this);},
_displayName, _displayName,

View File

@ -35,6 +35,7 @@ private _containerMagazineCount = [];
{ {
_x params ["_xMag", "_xTurret", "_xAmmo"]; _x params ["_xMag", "_xTurret", "_xAmmo"];
_magsToRemove pushBackUnique [_xMag, _xTurret];
private _carryMag = _xMag call FUNC(getCarryMagazine); private _carryMag = _xMag call FUNC(getCarryMagazine);
if (_carryMag != "") then { if (_carryMag != "") then {
@ -45,7 +46,6 @@ private _containerMagazineCount = [];
TRACE_1("",_loadedMagAmmo); TRACE_1("",_loadedMagAmmo);
}; };
if (_xAmmo > 0) then { if (_xAmmo > 0) then {
_magsToRemove pushBackUnique [_xMag, _xTurret];
private _index = _containerMagazineClassnames find _carryMag; private _index = _containerMagazineClassnames find _carryMag;
if (_index < 0) then { if (_index < 0) then {
_index = _containerMagazineClassnames pushBack _carryMag; _index = _containerMagazineClassnames pushBack _carryMag;