mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
all the things
This commit is contained in:
parent
3b42998f7b
commit
d00c9ca2a0
@ -19,8 +19,10 @@ PREP(assemble_pickupWeapon);
|
||||
PREP(canGetIn);
|
||||
PREP(getIn);
|
||||
|
||||
PREP(compatibleMagazines);
|
||||
PREP(getCarryMagazine);
|
||||
PREP(getNearbySources);
|
||||
PREP(getSourceCompatibleMagazines);
|
||||
PREP(proxyWeapon);
|
||||
|
||||
PREP(reload_actionsLoad);
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
GVAR(vehicleMagCache) = createHashMap;
|
||||
|
||||
["CBA_settingsInitialized", {
|
||||
TRACE_3("settingsInit",GVAR(defaultAssemblyMode),GVAR(handleExtraMagazines),GVAR(ammoHandling));
|
||||
["StaticWeapon", "init", LINKFUNC(staticWeaponInit), true, [], true] call CBA_fnc_addClassEventHandler;
|
||||
|
@ -9,6 +9,8 @@ PREP_RECOMPILE_END;
|
||||
#include "initSettings.sqf"
|
||||
|
||||
GVAR(initializedStaticTypes) = [];
|
||||
GVAR(vehicleMagCache) = createHashMap;
|
||||
GVAR(compatibleMagsCache) = createHashMap;
|
||||
GVAR(compatibleVehicleMagsCache) = createHashMap;
|
||||
|
||||
ADDON = true;
|
||||
|
||||
|
@ -16,67 +16,29 @@
|
||||
params ["_staticWeapon", "_gunner", "_weapon"];
|
||||
TRACE_3("AI reload",_staticWeapon,_gunner,_weapon);
|
||||
|
||||
private _turretPath = [_gunner] call EFUNC(common,getTurretIndex);
|
||||
private _reloadSource = objNull;
|
||||
private _reloadMag = "";
|
||||
private _reloadNeededAmmo = -1;
|
||||
private _loadableMagazines = [_staticWeapon, _gunner, true] call FUNC(reload_getLoadableMagazines);
|
||||
if (_loadableMagazines isEqualTo []) exitWith {TRACE_1("could not find reloadable mag",_staticWeapon)};
|
||||
|
||||
private _cfgMagGroups = configFile >> QGVAR(groups);
|
||||
|
||||
private _sources = [_gunner] call FUNC(getNearbySources);
|
||||
|
||||
// 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
|
||||
private _bestAmmo = 0;
|
||||
private _magazineInfo = [];
|
||||
{
|
||||
scopeName "findSource";
|
||||
private _xSource = _x;
|
||||
_x params ["", "", "", "", "", "_ammo"];
|
||||
if (_ammo > _bestAmmo) then {
|
||||
_bestAmmo = _ammo;
|
||||
_magazineInfo = _x;
|
||||
};
|
||||
} forEach _loadableMagazines;
|
||||
|
||||
private _cswMagazines = (magazineCargo _xSource) select {isClass (_cfgMagGroups >> _x)};
|
||||
TRACE_2("",_xSource,_cswMagazines);
|
||||
|
||||
{
|
||||
private _xWeaponMag = _x;
|
||||
{
|
||||
if ((getNumber (_cfgMagGroups >> _x >> _xWeaponMag)) == 1) then {
|
||||
private _loadInfo = [_staticWeapon, _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 (compatibleMagazines _weapon);
|
||||
} forEach _sources;
|
||||
if (_reloadMag == "") exitWith {TRACE_1("could not find mag",_reloadMag);};
|
||||
|
||||
// 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");};
|
||||
_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);
|
||||
|
||||
// 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 _eventParams = [_staticWeapon, _turretPath, objNull, _carryMag, _ammo, _gunner];
|
||||
|
||||
private _timeToLoad = 1;
|
||||
if !(isNull (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime")) then {
|
||||
_timeToLoad = getNumber (configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime");
|
||||
};
|
||||
private _timeToLoad = GET_NUMBER(configOf _staticWeapon >> QUOTE(ADDON) >> "ammoLoadTime", 1);
|
||||
|
||||
TRACE_1("Reloading in progress",_timeToLoad);
|
||||
[{
|
||||
@ -84,6 +46,6 @@ TRACE_1("Reloading in progress",_timeToLoad);
|
||||
if !(alive _staticWeapon && {alive _gunner}) exitWith {TRACE_2("invalid state",alive _staticWeapon,alive _gunner);};
|
||||
|
||||
// Reload the static weapon
|
||||
TRACE_5("calling addTurretMag event: AI reload",_staticWeapon,_turretPath,_gunner,_reloadMag,_bestAmmoToSend);
|
||||
TRACE_1("calling addTurretMag event: AI reload",_this);
|
||||
[QGVAR(addTurretMag), _this] call CBA_fnc_globalEvent;
|
||||
}, _eventParams, _timeToLoad] call CBA_fnc_waitAndExecute;
|
||||
|
39
addons/csw/functions/fnc_compatibleMagazines.sqf
Normal file
39
addons/csw/functions/fnc_compatibleMagazines.sqf
Normal file
@ -0,0 +1,39 @@
|
||||
#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]]];
|
||||
|
||||
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(compatibleVehicleMagsCache)) then {continue};
|
||||
_carryMagazines merge [GVAR(compatibleMagsCache) get _weapon, true];
|
||||
} forEach _weapons;
|
||||
|
||||
_carryMagazines // return
|
@ -12,10 +12,10 @@
|
||||
* Example:
|
||||
* "1Rnd_GAT_missiles" call ace_csw_fnc_getCarryMagazine
|
||||
*
|
||||
* Public: No
|
||||
* Public: Yes
|
||||
*/
|
||||
|
||||
params ["_vehicleMag"];
|
||||
params [["_vehicleMag", "", [""]]];
|
||||
|
||||
private _carryMag = GVAR(vehicleMagCache) get _vehicleMag;
|
||||
if (isNil "_carryMag") then {
|
||||
|
35
addons/csw/functions/fnc_getSourceCompatibleMagazines.sqf
Normal file
35
addons/csw/functions/fnc_getSourceCompatibleMagazines.sqf
Normal file
@ -0,0 +1,35 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: LinkIsGrim
|
||||
* Gets compatible magazines to load a CSW from a magazine source
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Magazine Source <OBJECT>
|
||||
* 1: CSW <OBJECT> (default: objNull)
|
||||
*
|
||||
* Return Value:
|
||||
* Magazines <ARRAY>
|
||||
* Magazine classname <STRING>
|
||||
* Magazine ammo <NUMBER>
|
||||
*
|
||||
* Example:
|
||||
* [player, cursorObject] call ace_csw_fnc_getSourceCompatibleMagazines
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
params [["_source", objNull, [objNull]], ["_csw", objNull, [objNull]]];
|
||||
|
||||
if (isNull _source || {isNull _csw}) exitWith {[]};
|
||||
|
||||
private _magazines = magazinesAmmoCargo _source;
|
||||
|
||||
if (_magazines isEqualTo []) exitWith {[]};
|
||||
|
||||
private _compatibleMagazines = [_csw] call FUNC(compatibleMagazines);
|
||||
|
||||
private _return = _magazines select {(_x select 0) in _compatibleMagazines};
|
||||
|
||||
// sort by ammo count, highest to lowest
|
||||
_return sort false;
|
||||
|
||||
_return
|
@ -37,6 +37,15 @@ if ((missionNamespace getVariable [_proxyWeapon, objNull]) isEqualType {}) then
|
||||
};
|
||||
if (!_needed) exitWith { TRACE_2("not needed",_needed,_proxyWeapon); };
|
||||
|
||||
// Cache compatible magazines
|
||||
if !(_proxyWeapon in GVAR(compatibleVehicleMagsCache)) then {
|
||||
private _compatibleMagazines = compatibleMagazines _proxyWeapon;
|
||||
GVAR(compatibleVehicleMagsCache) set [_proxyWeapon, _compatibleMagazines];
|
||||
GVAR(compatibleCarryMagsCache) set [_proxyWeapon,
|
||||
_compatibleMagazines apply {_x call FUNC(getCarryMagazine)} createHashMapFromArray []
|
||||
];
|
||||
};
|
||||
|
||||
TRACE_2("swapping to proxy weapon",_currentWeapon,_proxyWeapon);
|
||||
_staticWeapon removeWeaponTurret [_currentWeapon, _turret];
|
||||
_staticWeapon addWeaponTurret [_proxyWeapon, _turret];
|
||||
|
@ -23,9 +23,9 @@ private _loadableMagazines = [_vehicle, _player] call FUNC(reload_getLoadableMag
|
||||
|
||||
private _statement = {
|
||||
params ["_target", "_player", "_params"];
|
||||
_params params ["_carryMag", "_turretPath", "", "_magSource"];
|
||||
_params params ["_carryMag", "_turretPath", "", "_magSource", "", "_ammo"];
|
||||
|
||||
[_target, _turretPath, _carryMag, _magSource, _player] call FUNC(reload_loadMagazine);
|
||||
[_target, _turretPath, _carryMag, _magSource, _player, _ammo] call FUNC(reload_loadMagazine);
|
||||
};
|
||||
|
||||
private _condition = {
|
||||
|
@ -5,7 +5,8 @@
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
* 1: Player <OBJECT>
|
||||
* 1: Unit <OBJECT>
|
||||
* 2: AI reloading, skip turret checks <BOOL> (default: false)
|
||||
*
|
||||
* Return Value:
|
||||
* Mags <ARRAY>
|
||||
@ -17,55 +18,48 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_player"];
|
||||
params ["_vehicle", "_unit", ["_aiReload", false]];
|
||||
|
||||
private _magGroupsConfig = configFile >> QGVAR(groups); // so we don't solve in loop every time
|
||||
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 _sources = [_player] call FUNC(getNearbySources);
|
||||
|
||||
// send the mag source with the highest ammo
|
||||
private _bestMagAmmo = createHashMap;
|
||||
private _sources = [_unit] call FUNC(getNearbySources);
|
||||
|
||||
{
|
||||
// minor optimization: since mags are sorted by ammo count in FUNC(getSourceCompatibleMagazines), we only need to check the first mag of this type in this source
|
||||
private _handledSourceMags = [];
|
||||
private _xSource = _x;
|
||||
private _cswMags = (magazinesAmmoCargo _xSource) select {isClass (_magGroupsConfig >> _x select 0)};
|
||||
|
||||
{
|
||||
_x params ["_classname", "_ammo"];
|
||||
if (_ammo > (_bestMagAmmo getOrDefault [_classname, 0])) then {
|
||||
_bestMagAmmo set [_classname, _ammo];
|
||||
_availableMagazines set [_classname, _xSource];
|
||||
if (_classname in _handledSourceMags) then {continue};
|
||||
_handledSourceMags pushBack _classname;
|
||||
|
||||
// select mag source with the highest ammo
|
||||
if (_ammo > (_availableMagazines getOrDefault [_classname, [objNull, 0]]) select 1) then {
|
||||
_availableMagazines set [_classname, [_xSource, _ammo]];
|
||||
};
|
||||
} forEach _cswMags;
|
||||
} forEach ([_x, _vehicle] call FUNC(getSourceCompatibleMagazines));
|
||||
} forEach _sources;
|
||||
|
||||
if (_availableMagazines isEqualTo createHashMap) exitWith {[]}; // fast exit if no available mags
|
||||
|
||||
private _loadInfo = [];
|
||||
private _return = [];
|
||||
private _turretPath = [_unit] call EFUNC(common,getTurretIndex);
|
||||
|
||||
// Go through turrets and find weapons that we could reload
|
||||
// We can skip checking all turrets if we're doing AI reloading
|
||||
{
|
||||
private _turretPath = _x;
|
||||
{
|
||||
private _weapon = _x;
|
||||
{
|
||||
//IGNORE_PRIVATE_WARNING ["_x", "_y"];
|
||||
private _carryMag = _x;
|
||||
private _magSource = _y;
|
||||
private _carryGroup = _magGroupsConfig >> _carryMag;
|
||||
{
|
||||
if (
|
||||
((getNumber (_carryGroup >> _x)) == 1) &&
|
||||
{_loadInfo = [_vehicle, _turretPath, _carryMag, _magSource] call FUNC(reload_canLoadMagazine); _loadInfo select 0}
|
||||
) exitWith {
|
||||
_return pushBack [_carryMag, _turretPath, _loadInfo, _magSource, _player];
|
||||
_y params ["_magSource", "_ammo"];
|
||||
_loadInfo = [_vehicle, _turretPath, _carryMag] call FUNC(reload_canLoadMagazine);
|
||||
if (_loadInfo select 0) then {
|
||||
_return pushBack [_carryMag, _turretPath, _loadInfo, _magSource, _unit, _ammo];
|
||||
};
|
||||
} forEach (compatibleMagazines _weapon);
|
||||
} forEach _availableMagazines;
|
||||
} forEach (_vehicle weaponsTurret _turretPath);
|
||||
} forEach (allTurrets _vehicle);
|
||||
// Note: these nested forEach's looks terrible, but most only have one element
|
||||
} forEach ([(allTurrets _vehicle), [_turretPath]] select _aiReload);
|
||||
|
||||
_return
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
params ["_vehicle", "_turret", "_magSource", "_carryMag", "_ammoReceived", "_unit"];
|
||||
private _returnTo = param [6, _unit];
|
||||
if (isNull _returnTo) then {
|
||||
_returnTo = _vehicle;
|
||||
};
|
||||
TRACE_7("reload_handleAddTurretMag",_vehicle,_turret,_magSource,_carryMag,_ammoReceived,_unit,_returnTo);
|
||||
|
||||
TRACE_2("",local _vehicle, _vehicle turretLocal _turret);
|
||||
|
@ -19,57 +19,41 @@
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_turret", "_carryMag", "_magSource", "_unit"];
|
||||
TRACE_5("loadMagazine",_vehicle,_turret,_carryMag,_magSource,_unit);
|
||||
params ["_vehicle", "_turret", "_carryMag", "_magSource", "_unit", "_ammo"];
|
||||
TRACE_6("loadMagazine",_vehicle,_turret,_carryMag,_magSource,_unit,_ammo);
|
||||
|
||||
private _timeToLoad = 1;
|
||||
if (!isNull(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime")) then {
|
||||
_timeToLoad = getNumber(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime");
|
||||
};
|
||||
private _timeToLoad = GET_NUMBER(configOf _vehicle >> QUOTE(ADDON) >> "ammoLoadTime", 1);
|
||||
|
||||
private _displayName = format [localize LSTRING(loadX), getText (configFile >> "CfgMagazines" >> _carryMag >> "displayName")];
|
||||
|
||||
private _onFinish = {
|
||||
(_this select 0) params ["_vehicle", "_turret", "_carryMag", "_magSource", "_unit"];
|
||||
TRACE_5("load progressBar finish",_vehicle,_turret,_carryMag,_magSource,_unit);
|
||||
(_this select 0) params ["_vehicle", "_turret", "_carryMag", "_magSource", "_unit", "_ammo"];
|
||||
TRACE_6("load progressBar finish",_vehicle,_turret,_carryMag,_magSource,_unit,_ammo);
|
||||
|
||||
([_vehicle, _turret, _carryMag, _magSource] call FUNC(reload_canLoadMagazine)) params ["", "", "_neededAmmo", ""];
|
||||
if (_neededAmmo <= 0) exitWith { ERROR_1("Can't load ammo - %1",_this); };
|
||||
|
||||
// Figure out what we can add from the magazines we have
|
||||
private _bestAmmoToSend = -1;
|
||||
{
|
||||
_x params ["_xMag", "_xAmmo"];
|
||||
if (_xMag == _carryMag) then {
|
||||
if ((_bestAmmoToSend == -1) || {(_xAmmo > _bestAmmoToSend) && {_xAmmo <= _neededAmmo}}) then {
|
||||
_bestAmmoToSend = _xAmmo;
|
||||
};
|
||||
};
|
||||
} forEach (if (_magSource isKindOf "CAManBase") then {magazinesAmmo _magSource} else {magazinesAmmoCargo _magSource});
|
||||
|
||||
if (_bestAmmoToSend == -1) exitWith {ERROR_2("No ammo [%1 - %2]?",_xMag,_bestAmmoToSend);};
|
||||
[_magSource, _carryMag, _bestAmmoToSend] call EFUNC(common,removeSpecificMagazine);
|
||||
[_magSource, _carryMag, _ammo] call EFUNC(common,removeSpecificMagazine);
|
||||
|
||||
private _nearUnits = _vehicle nearEntities ["CAManBase", 5];
|
||||
[QGVAR(clearNearbySourcesCache), [], _nearUnits] call CBA_fnc_targetEvent;
|
||||
|
||||
if (_bestAmmoToSend == 0) exitWith {};
|
||||
|
||||
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
|
||||
// TODO: remove after 2.14
|
||||
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, _returnTo]] call CBA_fnc_globalEvent;
|
||||
TRACE_6("calling addTurretMag event",_vehicle,_turret,_magSource,_carryMag,_ammo, _unit);
|
||||
[QGVAR(addTurretMag), [_vehicle, _turret, _magSource, _carryMag, _ammo, _unit, _returnTo]] call CBA_fnc_globalEvent;
|
||||
};
|
||||
|
||||
|
||||
[
|
||||
TIME_PROGRESSBAR(_timeToLoad),
|
||||
[_vehicle, _turret, _carryMag, _magSource, _unit],
|
||||
[_vehicle, _turret, _carryMag, _magSource, _unit, _ammo],
|
||||
_onFinish,
|
||||
{TRACE_1("load progressBar fail",_this);},
|
||||
_displayName,
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
||||
|
||||
#define GET_NUMBER(config,default) (if (isNumber (config)) then {getNumber (config)} else {default})
|
||||
|
||||
#define DISTANCE_FROM_GUN 1.5
|
||||
#define RELATIVE_DIRECTION(direction) [DISTANCE_FROM_GUN, direction]
|
||||
|
Loading…
Reference in New Issue
Block a user