From aca90fb1879fa5435709af4335498777deb11efb Mon Sep 17 00:00:00 2001 From: Salluci Date: Sat, 1 Jul 2023 18:39:42 +0300 Subject: [PATCH] this took way too long --- addons/csw/functions/fnc_ai_handleFired.sqf | 2 +- addons/csw/functions/fnc_ai_handleGetIn.sqf | 7 ++- addons/csw/functions/fnc_ai_reload.sqf | 46 +++++++++++-------- .../functions/fnc_reload_canLoadMagazine.sqf | 22 ++++----- .../fnc_reload_getLoadableMagazines.sqf | 45 ++++++++++-------- .../fnc_reload_handleAddTurretMag.sqf | 9 ++-- .../functions/fnc_reload_handleReturnAmmo.sqf | 4 +- .../csw/functions/fnc_reload_loadMagazine.sqf | 22 ++++----- .../fnc_staticWeaponInit_unloadExtraMags.sqf | 2 +- 9 files changed, 87 insertions(+), 72 deletions(-) diff --git a/addons/csw/functions/fnc_ai_handleFired.sqf b/addons/csw/functions/fnc_ai_handleFired.sqf index 668a425b50..da7258e76c 100644 --- a/addons/csw/functions/fnc_ai_handleFired.sqf +++ b/addons/csw/functions/fnc_ai_handleFired.sqf @@ -20,4 +20,4 @@ if (someAmmo _staticWeapon) exitWith {}; TRACE_2("need ammo",someAmmo _staticWeapon,magazinesAllTurrets _staticWeapon); -[_staticWeapon, _gunner, _weapon, _magazine] call FUNC(ai_reload); +[_staticWeapon, _gunner, _weapon] call FUNC(ai_reload); diff --git a/addons/csw/functions/fnc_ai_handleGetIn.sqf b/addons/csw/functions/fnc_ai_handleGetIn.sqf index 2906a01d1e..c45fff5364 100644 --- a/addons/csw/functions/fnc_ai_handleGetIn.sqf +++ b/addons/csw/functions/fnc_ai_handleGetIn.sqf @@ -11,7 +11,7 @@ * * Public: No */ -params ["_staticWeapon", "_role", "_gunner"]; +params ["_staticWeapon", "_role", "_gunner", "_turret"]; TRACE_3("getInEH:",_staticWeapon,_role,_gunner); 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); -[_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); diff --git a/addons/csw/functions/fnc_ai_reload.sqf b/addons/csw/functions/fnc_ai_reload.sqf index 47e5d1ee6f..7b7dec6e46 100644 --- a/addons/csw/functions/fnc_ai_reload.sqf +++ b/addons/csw/functions/fnc_ai_reload.sqf @@ -7,14 +7,14 @@ * 0: Static Weapon * 1: Gunner * 2: Weapon - * 3: Magazine (default: "") * * Return Value: * None * * 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 _reloadSource = objNull; @@ -23,27 +23,29 @@ private _reloadNeededAmmo = -1; 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) || {!([_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 +// see fnc_reload_getLoadableMagazines, though we don't care about AI pulling from the best ammo possible { 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 _cswMagazines = []; - { - _cswMagazines pushBackUnique _x; - } forEach ((magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)}); + private _cswMagazines = (magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)}; TRACE_2("",_xSource,_cswMagazines); - private _compatibleMags = [_weapon] call CBA_fnc_compatibleMagazines; - if (_magazine != "") then { - _compatibleMags insert [0, [_magazine]]; - }; - { private _xWeaponMag = _x; { @@ -58,7 +60,7 @@ private _nearSupplies = [_gunner] + ((_staticWeapon nearSupplies 10) select { }; }; } forEach _cswMagazines; - } forEach _compatibleMags; + } forEach (compatibleMagazines _weapon); } forEach _nearSupplies; 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 [_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; -if (!isNull(configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime")) then { - _timeToLoad = getNumber(configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime"); +if !(isNull (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime")) then { + _timeToLoad = getNumber (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime"); }; TRACE_1("Reloading in progress",_timeToLoad); [{ - params ["_staticWeapon", "_turretPath", "_gunner", "_reloadMag", "_bestAmmoToSend"]; - if ((!alive _staticWeapon) || {!alive _gunner} || {(_staticWeapon distance _gunner) > 10}) exitWith {TRACE_1("invalid state",_this);}; + params ["_staticWeapon", "", "", "", "", "_gunner"]; + if !(alive _staticWeapon && {alive _gunner}) exitWith {TRACE_2("invalid state",alive _staticWeapon,alive _gunner);}; // 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; -}, [_staticWeapon, _turretPath, _gunner, _reloadMag, _bestAmmoToSend], _timeToLoad] call CBA_fnc_waitAndExecute; +}, _eventParams, _timeToLoad] call CBA_fnc_waitAndExecute; diff --git a/addons/csw/functions/fnc_reload_canLoadMagazine.sqf b/addons/csw/functions/fnc_reload_canLoadMagazine.sqf index 1fbd2e4708..4a189e5e98 100644 --- a/addons/csw/functions/fnc_reload_canLoadMagazine.sqf +++ b/addons/csw/functions/fnc_reload_canLoadMagazine.sqf @@ -7,7 +7,7 @@ * 0: Static Weapon * 1: Turret Path * 2: Carryable Magazine - * 3: Supplier + * 3: Supplier (default: objNull) * * Return Value: * [CanLoad, LoadedMag, AmmoNeeded, IsBeltLinking] @@ -24,16 +24,16 @@ params ["_vehicle", "_turret", "_carryMag", ["_magSource", objNull]]; private _return = [false, "", -2, false]; // Handle disassembled or deleted -if (!alive _vehicle) exitWith { _return }; -// Verify holder has carry magazine -if ( - (!isNull _magSource) && - {!((_magSource isKindOf "Bag_Base") || {_magSource isKindOf "ContainerSupply"})} && // hacky workaround for magazines within dropped backpacks - { - ((_vehicle distance _magSource) > 10) || - {((magazineCargo _magSource) findIf {_x == _carryMag}) == -1} - } -) 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 + if !(_carryMag in (magazineCargo _magSource)) exitWith {TRACE_3("no carry mag",_magSource,_carryMag,magazineCargo _magSource);_return}; + + // 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}; +}; // solve config lookups private _cfgMagazines = configFile >> "CfgMagazines"; diff --git a/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf b/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf index 1419e7b16e..2906c33b79 100644 --- a/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf +++ b/addons/csw/functions/fnc_reload_getLoadableMagazines.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" /* - * Author: PabstMirror - * Gets magazines that the player is carrying that can be loaded into the static weapon + * Author: PabstMirror, LinkIsGrim + * Gets nearby magazines that can be loaded in the static weapon * * Arguments: * 0: Vehicle @@ -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 // 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) || {!([_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"]; _nearSupplies pushBack _container; } forEach (everyContainer _x); -} forEach ((+_nearSupplies) select {(everyContainer _x) isNotEqualTo []}); - -// add caller to list of sources -_nearSupplies = [_player] + _nearSupplies; - -{ - private _xSource = _x; - private _mags = magazineCargo _xSource; { - _availableMagazines set [_x, _xSource]; - } forEach (_mags select {isClass (_magGroupsConfig >> _x)}); + _x params ["_classname", "_ammo"]; + if (_ammo > (_bestMagAmmo getOrDefault [_classname, 0])) then { + _bestMagAmmo set [_classname, _ammo]; + _availableMagazines set [_classname, _xSource]; + }; + } forEach _cswMags; } forEach _nearSupplies; if (_availableMagazines isEqualTo createHashMap) exitWith { [] }; // fast exit if no available mags @@ -68,9 +77,9 @@ private _return = []; ((getNumber (_carryGroup >> _x)) == 1) && {_loadInfo = [_vehicle, _turretPath, _carryMag, _magSource] call FUNC(reload_canLoadMagazine); _loadInfo select 0} ) 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 (_vehicle weaponsTurret _turretPath); } forEach (allTurrets _vehicle); diff --git a/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf b/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf index dbdf3c6d8b..781d4d1c52 100644 --- a/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf +++ b/addons/csw/functions/fnc_reload_handleAddTurretMag.sqf @@ -10,7 +10,8 @@ * 2: Source of magazine * 3: Vehicle Magazine * 4: Ammo in magazine - * 5: Unit or object to return ammo to (default: Source of magazine) + * 5: Unit that added the magazine + * 6: Object to return extra ammo (default: Unit that added the magazine) * * Return Value: * None @@ -21,9 +22,9 @@ * Public: No */ -params ["_vehicle", "_turret", "_magSource", "_carryMag", "_ammoReceived"]; -private _returnTo = param [5, _magSource]; -TRACE_6("reload_handleAddTurretMag",_vehicle,_turret,_magSource,_carryMag,_ammoReceived,_returnTo); +params ["_vehicle", "_turret", "_magSource", "_carryMag", "_ammoReceived", "_unit"]; +private _returnTo = param [6, _unit]; +TRACE_7("reload_handleAddTurretMag",_vehicle,_turret,_magSource,_carryMag,_ammoReceived,_unit,_returnTo); TRACE_2("",local _vehicle, _vehicle turretLocal _turret); if (!(_vehicle turretLocal _turret)) exitWith {}; diff --git a/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf b/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf index 136e70e0f4..46b0000fdc 100644 --- a/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf +++ b/addons/csw/functions/fnc_reload_handleReturnAmmo.sqf @@ -43,9 +43,9 @@ if ((_fullMagazines == 0) && {_bulletsRemaining == 0}) exitWith {}; private _container = [_unloadTo, objNull] select _unloadToUnit; if ((maxLoad _container) isEqualTo 0) then { _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 { - _container = (nearestObjects [_unloadTo, [QGVAR(ammo_holder), "GroundWeaponHolder"], 10]) param [0, objNull]; + _container = (nearestObjects [_unloadTo, [QGVAR(ammo_holder), "GroundWeaponHolder"], 5]) param [0, objNull]; }; }; diff --git a/addons/csw/functions/fnc_reload_loadMagazine.sqf b/addons/csw/functions/fnc_reload_loadMagazine.sqf index 1444a985dc..411c8717b4 100644 --- a/addons/csw/functions/fnc_reload_loadMagazine.sqf +++ b/addons/csw/functions/fnc_reload_loadMagazine.sqf @@ -51,25 +51,21 @@ private _onFinish = { [_magSource, _carryMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine); 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 _magSourcePos = getPosATL _magSource; - private _magSourceType = typeOf _magSource; - private _eventParams = [_vehicle, _turret, objNull, _carryMag, _bestAmmoToSend]; - [{ - params ["_args", "_magSourcePos", "_magSourceType"]; - _args params ["_vehicle", "_turret", "_magSource", "_carryMag", "_bestAmmoToSend"]; - _magSource = _magSourcePos nearestObject _magSourceType; + private _returnTo = _magSource; + // if we're pulling from a weaponHolder, return the ammo to the unit doing the action + // workaround for weaponHolders being recreated with removeSpecificMagazine, magazines will still get dropped if inventory is full + if (_magSource isKindOf "WeaponHolder") then { + _returnTo = _unit; + }; - TRACE_6("calling addTurretMag event",_vehicle,_turret,_magSource,_carryMag,_bestAmmoToSend, _unit); - [QGVAR(addTurretMag), [_vehicle, _turret, _magSource, _carryMag, _bestAmmoToSend, _unit]] call CBA_fnc_globalEvent; - - }, [_eventParams, _magSourcePos, _magSourceType]] call CBA_fnc_execNextFrame; + TRACE_6("calling addTurretMag event",_vehicle,_turret,_magSource,_carryMag,_bestAmmoToSend, _unit); + [QGVAR(addTurretMag), [_vehicle, _turret, _magSource, _carryMag, _bestAmmoToSend, _unit, _returnTo]] call CBA_fnc_globalEvent; }; [ TIME_PROGRESSBAR(_timeToLoad), - [_vehicle, _turret, _carryMag, _magSource], + [_vehicle, _turret, _carryMag, _magSource, _unit], _onFinish, {TRACE_1("load progressBar fail",_this);}, _displayName, diff --git a/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf b/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf index 41845c0eb3..78f06e72fc 100644 --- a/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf +++ b/addons/csw/functions/fnc_staticWeaponInit_unloadExtraMags.sqf @@ -35,6 +35,7 @@ private _containerMagazineCount = []; { _x params ["_xMag", "_xTurret", "_xAmmo"]; + _magsToRemove pushBackUnique [_xMag, _xTurret]; private _carryMag = _xMag call FUNC(getCarryMagazine); if (_carryMag != "") then { @@ -45,7 +46,6 @@ private _containerMagazineCount = []; TRACE_1("",_loadedMagAmmo); }; if (_xAmmo > 0) then { - _magsToRemove pushBackUnique [_xMag, _xTurret]; private _index = _containerMagazineClassnames find _carryMag; if (_index < 0) then { _index = _containerMagazineClassnames pushBack _carryMag;