Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSW - Fix and Improve reloading #9234

Draft
wants to merge 62 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
39f200b
fix belt linking issues
LinkIsGrim Jun 30, 2023
78800be
fix unloading to units with full inventory
LinkIsGrim Jun 30, 2023
01dffca
progress bar text changes
LinkIsGrim Jun 30, 2023
aca90fb
this took way too long
LinkIsGrim Jul 1, 2023
f3c393f
fix TRACE
LinkIsGrim Jul 1, 2023
76a2076
cache nearby ammo sources
LinkIsGrim Jul 1, 2023
5d62ab4
fix undefined variable
LinkIsGrim Jul 2, 2023
3b42998
Merge remote-tracking branch 'upstream' into csw-fix-belt-linking
LinkIsGrim Jul 12, 2023
d00c9ca
all the things
LinkIsGrim Jul 13, 2023
c96a9da
remove unnecessary change
LinkIsGrim Jul 13, 2023
c46dc33
_staticWeapon > _vehicle, StaticWeapon > CSW
LinkIsGrim Jul 13, 2023
6c2a8a2
add container property
LinkIsGrim Jul 13, 2023
ed44c0d
more headers
LinkIsGrim Jul 13, 2023
aa8fff3
fix case sensitivy, move container creation
LinkIsGrim Jul 13, 2023
4b92ef2
remove systemChat
LinkIsGrim Jul 13, 2023
e5a9fad
add check for invalid proxyWeapon
LinkIsGrim Jul 13, 2023
17156d5
missing semicolon
LinkIsGrim Jul 13, 2023
078857b
add getAvailableAmmo
LinkIsGrim Jul 13, 2023
73bc331
function header
LinkIsGrim Jul 13, 2023
cafe1f4
compile cache
LinkIsGrim Jul 13, 2023
7647123
add forcedMag and ai_unloadMagazines
LinkIsGrim Jul 13, 2023
4e8c69e
make public
LinkIsGrim Jul 13, 2023
8758645
fix stupid, add turretPath bool
LinkIsGrim Jul 13, 2023
ef93a61
fix derp
LinkIsGrim Jul 13, 2023
bb9ac71
fix derp part 2
LinkIsGrim Jul 13, 2023
1818762
i should squash these
LinkIsGrim Jul 13, 2023
22d45be
function header
LinkIsGrim Jul 14, 2023
b7abfea
add ai_switchMagazine
LinkIsGrim Jul 14, 2023
fac2e61
add example to header
LinkIsGrim Jul 14, 2023
2b52fee
fix container creation
LinkIsGrim Jul 14, 2023
1cf254a
fix condition
LinkIsGrim Jul 14, 2023
3c767c6
skip magazines with no ammo
LinkIsGrim Jul 16, 2023
b51efb1
add support for getting vehicle magazine from magwells
LinkIsGrim Jul 23, 2023
f5f14b7
Merge remote-tracking branch 'upstream/master' into csw-fix-belt-linking
LinkIsGrim Aug 12, 2023
1a876af
Merge branch 'master' into pr/9234
johnb432 Dec 17, 2023
5e2ffb9
Update addons/csw/functions/fnc_assemble_canPickupWeapon.sqf
johnb432 Dec 18, 2023
a5b0490
Various fixes
johnb432 Dec 18, 2023
301489b
Update fnc_canGetIn.sqf
johnb432 Dec 18, 2023
da21089
Small cleanup and tweaks
johnb432 Dec 22, 2023
a4661f3
Minor cleanup
johnb432 Dec 23, 2023
c94d29c
Merge branch 'master' into pr/9234
johnb432 Feb 7, 2024
ee6a953
Update addons/csw/functions/fnc_compatibleMagazines.sqf
johnb432 Feb 7, 2024
179d713
Merge branch 'master' into pr/9234
johnb432 Jul 26, 2024
757710b
Minor fixes
johnb432 Jul 26, 2024
7fc4c42
Update fnc_ai_reload.sqf
johnb432 Jul 26, 2024
a5d4a51
Merge branch 'master' into pr/9234
johnb432 Jul 27, 2024
76628c1
Remove space in macro
johnb432 Jul 27, 2024
3c3790e
Use macro for radius, minor code cleanup & optimisation
johnb432 Jul 27, 2024
1388f44
Update fnc_unloadMagazines.sqf
johnb432 Jul 27, 2024
b0504d7
Use getOrDefaultCall
johnb432 Jul 28, 2024
89491c1
drop redundant null check
LinkIsGrim Jul 28, 2024
66e417b
Update addons/csw/functions/fnc_getAvailableAmmo.sqf
LinkIsGrim Jul 28, 2024
18948e4
Update addons/csw/functions/fnc_unloadMagazines.sqf
johnb432 Aug 10, 2024
46c484e
Update addons/csw/functions/fnc_reload_handleReturnAmmo.sqf
johnb432 Aug 10, 2024
dc52f7a
Update addons/csw/functions/fnc_getAvailableAmmo.sqf
johnb432 Aug 10, 2024
6656aa6
Added some suggestions
johnb432 Aug 10, 2024
71dcfb5
Reverted changes for hostile crew (now in a separate PR)
johnb432 Aug 10, 2024
9a52511
Use turret events, fixed invalid param
johnb432 Aug 10, 2024
cf89aad
Merge branch 'master' into pr/9234
johnb432 Aug 28, 2024
aae708a
Check for dead & minor cleanup
johnb432 Aug 29, 2024
040709e
Merge branch 'master' into pr/9234
johnb432 Aug 30, 2024
e877c44
Merge branch 'master' into pr/9234
johnb432 Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions addons/csw/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ PREP(aceRearmGetCarryMagazines);

PREP(ai_handleFired);
PREP(ai_handleGetIn);
PREP(ai_switchMagazine);
PREP(ai_reload);

PREP(canDeployTripod);
Expand All @@ -18,7 +19,11 @@ PREP(assemble_pickupWeapon);

PREP(canGetIn);

PREP(compatibleMagazines);
PREP(getAvailableAmmo);
PREP(getCarryMagazine);
PREP(getNearbySources);
PREP(getSourceCompatibleMagazines);
PREP(proxyWeapon);

PREP(getLoadActions);
Expand All @@ -31,6 +36,7 @@ PREP(reload_handleAddTurretMag);
PREP(reload_handleRemoveTurretMag);
PREP(reload_handleReturnAmmo);
PREP(reload_loadMagazine);
PREP(unloadMagazines);

PREP(initVehicle);
PREP(staticWeaponInit_unloadExtraMags);
3 changes: 1 addition & 2 deletions addons/csw/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "script_component.hpp"

GVAR(vehicleMagCache) = createHashMap;

["CBA_settingsInitialized", {
TRACE_3("settingsInit",GVAR(defaultAssemblyMode),GVAR(handleExtraMagazines),GVAR(ammoHandling));
["StaticWeapon", "Init", {
Expand All @@ -26,6 +24,7 @@ GVAR(vehicleMagCache) = createHashMap;
[QGVAR(addTurretMag), LINKFUNC(reload_handleAddTurretMag)] call CBA_fnc_addEventHandler;
[QGVAR(removeTurretMag), LINKFUNC(reload_handleRemoveTurretMag)] call CBA_fnc_addEventHandler;
[QGVAR(returnAmmo), LINKFUNC(reload_handleReturnAmmo)] call CBA_fnc_addEventHandler;
[QGVAR(ai_reload), LINKFUNC(ai_reload)] call CBA_fnc_addEventHandler;

#ifdef DEBUG_MODE_FULL
call compile preprocessFileLineNumbers QPATHTOF(dev\checkStaticWeapons.sqf);
Expand Down
4 changes: 3 additions & 1 deletion addons/csw/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ PREP_RECOMPILE_END;
#include "initSettings.inc.sqf"

GVAR(initializedStaticTypes) = [];
GVAR(vehicleMagCache) = createHashMap;
GVAR(compatibleMagsCache) = createHashMap;
GVAR(compatibleVehicleMagsCache) = createHashMap;

ADDON = true;

8 changes: 4 additions & 4 deletions addons/csw/functions/fnc_ai_handleFired.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
* Public: No
*/

params ["_vehicle", "_weapon", "", "", "", "_magazine", "", "_gunner"];
TRACE_4("firedEH:",_vehicle,_weapon,_magazine,_gunner);
params ["_vehicle", "", "", "", "", "", "", "_gunner"];
TRACE_1("firedEH:",_this);

if (someAmmo _vehicle) exitWith {};
if ((!local _gunner) || {[_gunner] call EFUNC(common,isPlayer)}) exitWith {};

TRACE_1("need ammo",magazinesAllTurrets _vehicle);
TRACE_2("need ammo",someAmmo _vehicle,magazinesAllTurrets _vehicle);

[_vehicle, _gunner, _weapon, _magazine] call FUNC(ai_reload);
[_vehicle, _gunner] call FUNC(ai_reload);
4 changes: 1 addition & 3 deletions addons/csw/functions/fnc_ai_handleGetIn.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,4 @@ TRACE_2("getInEH:",_vehicle,_gunner);
if (someAmmo _vehicle) exitWith {};
if ((!local _gunner) || {[_gunner] call EFUNC(common,isPlayer)}) exitWith {};

TRACE_1("need ammo",magazinesAllTurrets _vehicle);

[_vehicle, _gunner, currentWeapon _vehicle] call FUNC(ai_reload);
[_vehicle, _gunner] call FUNC(ai_reload);
103 changes: 40 additions & 63 deletions addons/csw/functions/fnc_ai_reload.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,68 @@
* Arguments:
* 0: CSW <OBJECT>
* 1: Gunner <OBJECT>
* 2: Weapon <STRING>
* 3: Magazine <STRING> (default: "")
* 2: Skip reload time <BOOL> (default: false)
* 3: Clear forced magazine after reloading (default: false)
*
* Return Value:
* None
*
* Public: No
*/

params ["_vehicle", "_gunner", "_weapon", ["_magazine", ""]];
params ["_vehicle", "_gunner", ["_instantReload", false], ["_clearForcedMag", false]];
TRACE_3("AI reload",_vehicle,_gunner,_instantReload);

private _turretPath = [_gunner] call EFUNC(common,getTurretIndex);
private _reloadSource = objNull;
private _reloadMag = "";
private _reloadNeededAmmo = -1;
// API, used for ai_switchMagazine
private _forcedMag = _vehicle getVariable [QGVAR(forcedMag), ""];
private _turretPath = _vehicle unitTurret _gunner;
if (_turretPath isEqualTo []) then {
_turretPath = [0];
};
Comment on lines +24 to +26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?
FUNC(reload_getLoadableMagazines) doesn't follow the same logic, which could lead to a desync of information.


private _cfgMagGroups = configFile >> QGVAR(groups);
// If this is called while CSW has ammo, unload mags in gunner's turret
if (someAmmo _vehicle) then {[_vehicle, _turretPath] call FUNC(unloadMagazines)};
johnb432 marked this conversation as resolved.
Show resolved Hide resolved

private _nearSupplies = [_gunner] + ((_vehicle nearSupplies 10) select {
isNull (group _x) ||
{!([_x] call EFUNC(common,isPlayer)) && {[side group _gunner, side group _x] call BIS_fnc_sideIsFriendly}}
});
private _loadableMagazines = [_vehicle, _gunner, true] call FUNC(reload_getLoadableMagazines);
if (_loadableMagazines isEqualTo []) exitWith {TRACE_1("could not find reloadable mag",_vehicle)};

// Find if there is anything we can reload with
private _bestAmmo = 0;
private _magazineInfo = [];
{
scopeName "findSource";
private _xSource = _x;

private _cswMagazines = [];
{
_cswMagazines pushBackUnique _x;
} forEach ((magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)});
TRACE_2("",_xSource,_cswMagazines);

private _compatibleMags = compatibleMagazines _weapon;
if (_magazine != "") then {
_compatibleMags insert [0, [_magazine]];
_x params ["_xMag", "", "", "", "", "_ammo"];
if (_forcedMag != "" && {_xMag != _forcedMag}) then {continue};
if (_ammo > _bestAmmo) then {
_bestAmmo = _ammo;
_magazineInfo = _x;
};
} forEach _loadableMagazines;

{
private _xWeaponMag = _x;
{
if ((getNumber (_cfgMagGroups >> _x >> _xWeaponMag)) == 1) then {
private _loadInfo = [_vehicle, _turretPath, _x, _xSource] call FUNC(reload_canLoadMagazine);
if (_loadInfo select 0) then {
_reloadMag = _x;
_reloadSource = _xSource;
_reloadNeededAmmo = _loadInfo select 2;
TRACE_3("found mag",_reloadMag,_reloadSource,_x);
breakOut "findSource";
};
};
} forEach _cswMagazines;
} forEach _compatibleMags;
} forEach _nearSupplies;
if (_reloadMag == "") exitWith {TRACE_1("could not find mag",_reloadMag);};
if (_clearForcedMag) then {
_vehicle setVariable [QGVAR(forcedMag), nil, true];
};
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Description of _clearForcedMag is Clear forced magazine after reloading. However, in line 46 it can still fail. Furthermore, this variable technically reset before reload. Do we need to absolutely reset it after the reload has finished (so when the turret events are called) or can it be called just after line 53?


// Figure out what we can add from the magazines we have
private _bestAmmoToSend = -1;
{
_x params ["_xMag", "_xAmmo"];
TRACE_2("",_xMag,_xAmmo);
if (_xMag == _reloadMag) then {
if ((_bestAmmoToSend == -1) || {(_xAmmo > _bestAmmoToSend) && {_xAmmo <= _reloadNeededAmmo}}) then {
_bestAmmoToSend = _xAmmo;
};
};
} forEach (if (_reloadSource isKindOf "CAManBase") then {magazinesAmmo _reloadSource} else {magazinesAmmoCargo _reloadSource});
TRACE_4("",_reloadSource,_reloadMag,_reloadNeededAmmo,_bestAmmoToSend);
if (_bestAmmoToSend == -1) exitWith {ERROR("No ammo");};
if (_magazineInfo isEqualTo []) exitWith {};
_magazineInfo params ["_carryMag", "_turretPath", "_loadInfo", "_magSource", "", "_ammo"];

// Remove the mag from the source
[_reloadSource, _reloadMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine);
[_magSource, _carryMag, _ammo] call EFUNC(common,removeSpecificMagazine);

private _timeToLoad = 1;
if (!isNull(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime")) then {
_timeToLoad = getNumber(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime");
// AI never returns ammo and removes the magazine before reloading, so we can skip distance and weaponHolder checks
private _eventParams = [_vehicle, _turretPath, objNull, _carryMag, _ammo, _gunner];

if (_instantReload) exitWith {
TRACE_1("calling addTurretMag event: instant AI reload",_this);
[QGVAR(addTurretMag), _eventParams] call CBA_fnc_globalEvent;
};

private _timeToLoad = GET_NUMBER(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime",1);

TRACE_1("Reloading in progress",_timeToLoad);
[{
params ["_vehicle", "_turretPath", "_gunner", "_reloadMag", "_bestAmmoToSend"];
if ((!alive _vehicle) || {!alive _gunner} || {(_vehicle distance _gunner) > 10}) exitWith {TRACE_1("invalid state",_this);};
params ["_vehicle", "", "", "", "", "_gunner"];
if !(alive _vehicle && {alive _gunner}) exitWith {TRACE_2("invalid state",alive _vehicle,alive _gunner);};

// Reload the static weapon
TRACE_5("calling addTurretMag event",_vehicle,_turretPath,_gunner,_reloadMag,_bestAmmoToSend);
TRACE_1("calling addTurretMag event: AI reload",_this);
[QGVAR(addTurretMag), _this] call CBA_fnc_globalEvent;
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
}, [_vehicle, _turretPath, _gunner, _reloadMag, _bestAmmoToSend], _timeToLoad] call CBA_fnc_waitAndExecute;
}, _eventParams, _timeToLoad] call CBA_fnc_waitAndExecute;
40 changes: 40 additions & 0 deletions addons/csw/functions/fnc_ai_switchMagazine.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Handles AI magazine switching.
* Magazine must be compatible and available, use ace_csw_fnc_getAvailableAmmo.
*
* Arguments:
* 0: CSW <OBJECT>
* 1: Carry Magazine <STRING>
* 2: Turret Path <ARRAY> (default: [0])
* 3: Skip reload time <BOOL> (default: false)
* 4: Clear forced magazine after reloading <BOOL> (default: true)
*
* Return Value:
* Successful <BOOL>
*
* Example:
* [cursorTarget, "ACE_csw_100Rnd_127x99_mag_red", [0]] call ace_csw_fnc_ai_switchMagazine
*
* Public: Yes
*/

params [["_vehicle", objNull, [objNull]], ["_carryMag", "", [""]], ["_turretPath", [0], [[0]]], ["_instantReload", false, [false]], ["_clearForcedMag", true, [true]]];

if !(alive _vehicle && {!isNull (_vehicle turretUnit _turretPath)} && {!(isNull _vehicle)}) exitWith {false};
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved

// must be config case
_carryMag = configName (configFile >> "CfgMagazines" >> _carryMag);
if (_carryMag isEqualTo "") exitWith {false};

private _availableMags = [_vehicle] call FUNC(getAvailableAmmo);
if !(_carryMag in _availableMags) exitWith {false};

_vehicle setVariable [QGVAR(forcedMag), _carryMag, true];

private _gunner = _vehicle turretUnit _turretPath;

[QGVAR(ai_reload), [_vehicle, _gunner, _instantReload, _clearForcedMag], _gunner] call CBA_fnc_targetEvent;

true
47 changes: 47 additions & 0 deletions addons/csw/functions/fnc_compatibleMagazines.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Gets all carry magazines that can be loaded into a CSW, includes weapons added by script.
*
* Arguments:
* 0: CSW <OBJECT>
*
* Return Value:
* Compatible Magazines <HASHMAP>
* Magazine classname <STRING>
* Nothing
*
* Example:
* [cursorObject] call ace_csw_fnc_compatibleMagazines
*
* Public: Yes
*/

params [["_csw", objNull, [objNull]]];

if !((typeOf _csw) in GVAR(initializedStaticTypes)) exitWith {createHashMap};

// fast exit for csw with single weapon, most common scenario
if (count allTurrets _csw isEqualTo 1 && {count weapons _csw isEqualTo 1}) exitWith {
+(GVAR(compatibleMagsCache) getOrDefault [(weapons _csw) select 0, createHashMap]) // return
};

private _weapons = [];

{
private _turret = _x;
{
_weapons pushBackUnique _x;
} forEach (_csw weaponsTurret _turret);
} forEach (allTurrets _csw);

if (_weapons isEqualTo []) exitWith {[]};

private _carryMagazines = createHashMap; // hashmap for constant lookup
{
private _weapon = _x;
if !(_weapon in GVAR(compatibleMagsCache)) then {continue};
_carryMagazines merge [GVAR(compatibleMagsCache) get _weapon, true];
} forEach _weapons;
Comment on lines +40 to +45
Copy link
Contributor

@johnb432 johnb432 Jul 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. Add comment describing that this is handling proxy weapons. That's some bullshit I wrote, it handles carry magazines.
2. GVAR(compatibleMagsCache) is not a good name for this imo, should be renamed to something that includes "proxyWeapon" (e.g. GVAR(compatibleCarryMags)).


+_carryMagazines // return
62 changes: 62 additions & 0 deletions addons/csw/functions/fnc_getAvailableAmmo.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "..\script_component.hpp"
/*
* Author: LinkIsGrim
* Gets available ammo for a CSW.
*
* Arguments:
* 0: CSW <OBJECT>
* 1: Only loaded magazines <BOOL> (default: false)
* 2: Skip ammo from vehicles <BOOL> (default: true)
* 3: Include CSW crew <BOOL> (default: true)
*
* Return Value:
* Available Ammo <HASHMAP>
* Magazine classname <STRING>
* Total Ammo <NUMBER>
*
* Example:
* [cursorObject] call ace_csw_fnc_getAvailableAmmo
*
* Public: Yes
*/

params [["_vehicle", objNull, [objNull]], ["_onlyLoaded", false, [false]], ["_skipVehicles", true, [true]], ["_includeCrew", true, [true]]];

if (isNull _vehicle) exitWith {createHashMap};
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved

private _availableMagazines = createHashMap;

private _fnc_addAmmo = {
params ["_magazine", "_ammo"];
if !(_magazine in _availableMagazines) then {
_availableMagazines set [_magazine, _ammo];
} else {
_availableMagazines set [_magazine, (_availableMagazines get _magazine) + _ammo];
};
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
};

{
_x params ["_xMag", "", "_xAmmo"];

if (_xAmmo <= 0) then {continue};

private _carryMag = _xMag call FUNC(getCarryMagazine);
if (_carryMag isEqualTo "") then {continue};

[_carryMag, _xAmmo] call _fnc_addAmmo
} forEach (magazinesAllTurrets _vehicle);

if (_onlyLoaded) exitWith {_availableMagazines};

[QGVAR(clearNearbySourcesCache), []] call CBA_fnc_localEvent;
private _sources = [_vehicle, _skipVehicles, _includeCrew] call FUNC(getNearbySources);
if (_sources isEqualTo []) exitWith {_availableMagazines};

{
private _source = _x;
{
_x call _fnc_addAmmo
} forEach ([_source, _vehicle] call FUNC(getSourceCompatibleMagazines));
} forEach _sources;

_availableMagazines // return
4 changes: 2 additions & 2 deletions addons/csw/functions/fnc_getCarryMagazine.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
* Example:
* "1Rnd_GAT_missiles" call ace_csw_fnc_getCarryMagazine
*
* Public: No
* Public: Yes
*/

params ["_vehicleMag"];
params [["_vehicleMag", "", [""]]];
johnb432 marked this conversation as resolved.
Show resolved Hide resolved

private _carryMag = GVAR(vehicleMagCache) get _vehicleMag;
if (isNil "_carryMag") then {
Expand Down
Loading