Skip to content

Commit bd5c438

Browse files
ampersand38neilzarCreepPorkmharis001
authored
Add Switch Weapon context menu actions for vehicles (#537)
* Add Vehicle Logistics > Switch Weapons context actions * Actions labelled Turret - Muzzle - Magazine * Switch is instant and does not require gunner unit to be present Co-authored-by: Neil Evers <[email protected]> Co-authored-by: Ralfs Garkaklis <[email protected]> Co-authored-by: mharis001 <[email protected]> Co-authored-by: mharis001 <[email protected]>
1 parent 1679273 commit bd5c438

9 files changed

+224
-31
lines changed

addons/common/XEH_PREP.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ PREP(getCargoPositionsCount);
2525
PREP(getDefaultInventory);
2626
PREP(getDLC);
2727
PREP(getEffectiveGunner);
28+
PREP(getGunnerName);
2829
PREP(getLightingSelections);
2930
PREP(getPhoneticName);
3031
PREP(getPlayers);

addons/common/XEH_postInit.sqf

+6
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@
178178
_unit selectWeapon _muzzle;
179179
}] call CBA_fnc_addEventHandler;
180180

181+
[QGVAR(selectWeaponTurret), {
182+
params ["_vehicle", "_weapon", "_turretPath", ["_muzzle", ""], ["_fireMode", ""]];
183+
_vehicle selectWeaponTurret [_weapon, _turretPath, _muzzle, _fireMode];
184+
}] call CBA_fnc_addEventHandler;
185+
181186
[QGVAR(setPilotLight), {
182187
params ["_vehicle", "_lights"];
183188
_vehicle setPilotLight _lights;
@@ -321,6 +326,7 @@
321326
[QGVAR(fireArtillery), LINKFUNC(fireArtillery)] call CBA_fnc_addEventHandler;
322327
[QGVAR(fireWeapon), LINKFUNC(fireWeapon)] call CBA_fnc_addEventHandler;
323328
[QGVAR(forceFire), LINKFUNC(forceFire)] call CBA_fnc_addEventHandler;
329+
[QGVAR(loadMagazineInstantly), LINKFUNC(loadMagazineInstantly)] call CBA_fnc_addEventHandler;
324330
[QGVAR(setLampState), LINKFUNC(setLampState)] call CBA_fnc_addEventHandler;
325331
[QGVAR(setMagazineAmmo), LINKFUNC(setMagazineAmmo)] call CBA_fnc_addEventHandler;
326332
[QGVAR(setTurretAmmo), LINKFUNC(setTurretAmmo)] call CBA_fnc_addEventHandler;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "script_component.hpp"
2+
/*
3+
* Author: NeilZar
4+
* Returns the (gunner) name of the given vehicle's specified turret.
5+
*
6+
* Arguments:
7+
* 0: Vehicle <STRING|OBJECT|CONFIG>
8+
* 1: Turret Path <ARRAY>
9+
*
10+
* Return Value:
11+
* Gunner Name <STRING>
12+
*
13+
* Example:
14+
* ["B_MRAP_01_hmg_F", [0]] call zen_common_fnc_getGunnerName
15+
*
16+
* Public: No
17+
*/
18+
19+
params [["_vehicle", "", ["", objNull, configNull]], ["_turretPath", [], [[]]]];
20+
21+
private _name = getText ([_vehicle, _turretPath] call CBA_fnc_getTurret >> "gunnerName");
22+
23+
if (_name == "") then {
24+
_name = localize (["str_driver", "str_pilot"] select (_vehicle isKindOf "Air"));
25+
};
26+
27+
_name
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,69 @@
11
#include "script_component.hpp"
22
/*
33
* Author: Kex
4-
* Instantly loads the given magazine into the specified weapon.
4+
* Instantly loads the given magazine into the specified vehicle's turret weapon.
55
*
66
* Arguments:
77
* 0: Vehicle <OBJECT>
8-
* 1: Turret path <ARRAY>
9-
* 2: Muzzle class <STRING>
10-
* 3: Magazine class <STRING>
8+
* 1: Turret Path <ARRAY>
9+
* 2: Weapon <STRING>
10+
* 3: Magazine <STRING>
1111
*
1212
* Return Value:
1313
* None
1414
*
1515
* Example:
16-
* [_vehicle, [0], "HE", "60Rnd_40mm_GPR_Tracer_Red_shells"] call zen_common_fnc_loadMagazineInstantly
16+
* [_vehicle, [0, 0], "HMG_127_MBT", "200Rnd_127x99_mag_Tracer_Red"] call zen_common_fnc_loadMagazineInstantly
1717
*
1818
* Public: No
1919
*/
2020

21-
params [["_vehicle", objNull, [objNull]], ["_turretPath", [], [[]]], ["_muzzle", "", [""]], ["_magazine", "", [""]]];
21+
params [["_vehicle", objNull, [objNull]], ["_turretPath", [], [[]]], ["_weapon", "", [""]], ["_magazine", "", [""]]];
22+
23+
if !(_vehicle turretLocal _turretPath) exitWith {
24+
[QGVAR(loadMagazineInstantly), _this, _vehicle, _turretPath] call CBA_fnc_turretEvent;
25+
};
26+
27+
// Get all magazines compatible with the given weapon on the given turret
28+
private _magazines = createHashMap;
29+
private _compatibleMagazines = [_weapon, true] call CBA_fnc_compatibleMagazines;
2230

23-
private _magazines = [];
24-
private _ammoCounts = [];
2531
{
26-
_x params ["_currentMagazine", "_currentTurretPath", "_currentAmmoCount"];
27-
if (_turretPath isEqualTo _currentTurretPath) then {
28-
_magazines pushBack _currentMagazine;
29-
_ammoCounts pushBack _currentAmmoCount;
32+
_x params ["_xMagazine", "_xTurretPath", "_xAmmoCount"];
33+
34+
if (_turretPath isEqualTo _xTurretPath && {_xMagazine in _compatibleMagazines}) then {
35+
_magazines getOrDefault [_xMagazine, [], true] pushBack _xAmmoCount;
3036
};
31-
} forEach (magazinesAllTurrets _vehicle);
37+
} forEach magazinesAllTurrets _vehicle;
38+
39+
// Ensure that the vehicle has the desired magazine to load
40+
if (_magazine in _magazines) then {
41+
// Remove given weapon and all compatible magazines
42+
_vehicle removeWeaponTurret [_weapon, _turretPath];
3243

33-
private _magIdx = _magazines findIf {_x == _magazine};
34-
if (_magIdx != -1) then {
35-
// Remove weapon and magazines
3644
{
37-
_vehicle removeMagazineTurret [_x, _turretPath];
45+
_vehicle removeMagazinesTurret [_x, _turretPath];
3846
} forEach _magazines;
39-
_vehicle removeWeaponTurret [_muzzle, _turretPath];
4047

41-
// Add desired magazine first
42-
_vehicle addMagazineTurret [_magazine, _turretPath, _ammoCounts select _magIdx];
43-
_magazines deleteAt _magIdx;
44-
_ammoCounts deleteAt _magIdx;
48+
// Add magazines of selected type back first (load magazine with most ammo)
49+
private _selectedMagazine = _magazines deleteAt _magazine;
50+
_selectedMagazine sort false;
4551

46-
// Restore weapon and magazines
47-
_vehicle addWeaponTurret [_muzzle, _turretPath];
4852
{
49-
_vehicle addMagazineTurret [_x, _turretPath, _ammoCounts select _forEachIndex];
53+
_vehicle addMagazineTurret [_magazine, _turretPath, _x];
54+
} forEach _selectedMagazine;
55+
56+
// Restore weapon and other magazines (will load desired magazine since it was added first)
57+
_vehicle addWeaponTurret [_weapon, _turretPath];
58+
59+
{
60+
private _magazine = _x;
61+
62+
{
63+
_vehicle addMagazineTurret [_magazine, _turretPath, _x];
64+
} forEach _y;
5065
} forEach _magazines;
66+
67+
// Select the weapon that the magazine was loaded into
68+
_vehicle selectWeaponTurret [_weapon, _turretPath];
5169
};

addons/context_actions/CfgContext.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,11 @@ class EGVAR(context_menu,actions) {
343343
statement = QUOTE(_objects call FUNC(refuelVehicles));
344344
icon = "\a3\ui_f\data\igui\cfg\simpleTasks\types\refuel_ca.paa";
345345
};
346+
class SwitchWeapon {
347+
displayName = "$STR_A3_Switch1";
348+
icon = "\a3\ui_f\data\GUI\Cfg\Hints\VehicleAmmo_CA.paa";
349+
insertChildren = QUOTE(_hoveredEntity call FUNC(getVehicleWeaponActions));
350+
};
346351
class UnloadViV {
347352
displayName = "$STR_A3_ModuleDepot_Unload";
348353
condition = QUOTE(_objects call FUNC(canUnloadViV));

addons/context_actions/XEH_PREP.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ PREP(canUnloadViV);
1212
PREP(copyVehicleAppearance);
1313
PREP(compileGrenades);
1414
PREP(getArtilleryActions);
15+
PREP(getVehicleWeaponActions);
1516
PREP(getGrenadeActions);
1617
PREP(healUnits);
1718
PREP(openEditableObjectsDialog);
@@ -26,6 +27,7 @@ PREP(setCombatMode);
2627
PREP(setFormation);
2728
PREP(setSpeedMode);
2829
PREP(setStance);
30+
PREP(switchVehicleWeapon);
2931
PREP(switchWeaponModifier);
3032
PREP(switchWeapon);
3133
PREP(teleportPlayers);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include "script_component.hpp"
2+
/*
3+
* Author: Ampersand
4+
* Returns children actions for switching between the given vehicle's weapons, muzzles, and magazines.
5+
*
6+
* Arguments:
7+
* 0: Vehicle <OBJECT>
8+
*
9+
* Return Value:
10+
* Actions <ARRAY>
11+
*
12+
* Example:
13+
* [_vehicle] call zen_context_actions_fnc_getVehicleWeaponActions
14+
*
15+
* Public: No
16+
*/
17+
18+
#define AMMO_SIMULATION_BLACKLIST ["shotcm", "laserdesignate"]
19+
20+
params ["_vehicle"];
21+
22+
if !(_vehicle isEqualType objNull && {alive _vehicle}) exitWith {[]};
23+
24+
private _actions = [];
25+
private _cfgAmmo = configFile >> "CfgAmmo";
26+
private _cfgMagazines = configFile >> "CfgMagazines";
27+
private _cfgWeapons = configFile >> "CfgWeapons";
28+
29+
{
30+
private _turretPath = _x;
31+
private _turretMagazines = _vehicle magazinesTurret _turretPath;
32+
33+
weaponState [_vehicle, _turretPath] params ["_currentWeapon", "_currentMuzzle", "", "_currentMagazine"];
34+
35+
{
36+
private _weapon = _x;
37+
private _weaponConfig = _cfgWeapons >> _weapon;
38+
39+
{
40+
private _muzzle = _x;
41+
private _muzzleConfig = _weaponConfig;
42+
43+
if (_muzzle == "this") then {
44+
_muzzle = _weapon;
45+
} else {
46+
_muzzleConfig = _muzzleConfig >> _muzzle;
47+
};
48+
49+
private _compatibleMagazines = [_muzzleConfig] call CBA_fnc_compatibleMagazines;
50+
private _magazines = _turretMagazines arrayIntersect _compatibleMagazines;
51+
52+
{
53+
private _magazine = _x;
54+
private _magazineConfig = _cfgMagazines >> _magazine;
55+
56+
// Skip current weapon, muzzle, and magazine combination
57+
if (
58+
_weapon == _currentWeapon
59+
&& {_muzzle == _currentMuzzle}
60+
&& {_magazine == _currentMagazine}
61+
) then {continue};
62+
63+
// Skip blacklisted ammo simulation types
64+
private _ammoConfig = _cfgAmmo >> getText (_magazineConfig >> "ammo");
65+
private _ammoSimulation = toLower getText (_ammoConfig >> "simulation");
66+
if (_ammoSimulation in AMMO_SIMULATION_BLACKLIST) then {continue};
67+
68+
private _name = format [
69+
"%1 - %2 %3- %4",
70+
[_vehicle, _turretPath] call EFUNC(common,getGunnerName),
71+
getText (_weaponConfig >> "displayName"),
72+
[format ["%1 ", _muzzle], ""] select (_muzzle == _weapon),
73+
getText (_magazineConfig >> "displayName")
74+
];
75+
76+
private _icon = switch (_ammoSimulation) do {
77+
case "shotbullet": {
78+
"\a3\ui_f_jets\data\gui\cfg\hints\weaponsguns_ca.paa"
79+
};
80+
case "shotmissile": {
81+
"\a3\ui_f_jets\data\gui\cfg\hints\weaponsmissiles_ca.paa"
82+
};
83+
case "shotilluminating": {
84+
"\a3\ui_f\data\gui\cfg\hints\flares_ca.paa"
85+
};
86+
default {
87+
QPATHTOF(ui\ammo_ca.paa)
88+
};
89+
};
90+
91+
private _action = [
92+
[_weapon, _muzzle, _magazine] joinString "",
93+
_name,
94+
_icon,
95+
{
96+
_args call FUNC(switchVehicleWeapon)
97+
},
98+
{true},
99+
[_vehicle, _turretPath, _weapon, _muzzle, _magazine]
100+
] call EFUNC(context_menu,createAction);
101+
102+
_actions pushBack [_action, [], 0];
103+
} forEach _magazines;
104+
} forEach getArray (_weaponConfig >> "muzzles");
105+
} forEach (_vehicle weaponsTurret _turretPath);
106+
} forEach (_vehicle call EFUNC(common,getAllTurrets));
107+
108+
_actions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "script_component.hpp"
2+
/*
3+
* Author: Ampersand
4+
* Switches the given vehicle turret's weapon, muzzle, and magazine.
5+
*
6+
* Arguments:
7+
* 0: Vehicle <OBJECT>
8+
* 1: Turret Path <ARRAY>
9+
* 2: Weapon <STRING>
10+
* 3: Muzzle <STRING>
11+
* 4: Magazine <STRING>
12+
*
13+
* Return Value:
14+
* None
15+
*
16+
* Example:
17+
* [_vehicle, _turretPath, _weapon, _muzzle, _magazine] call zen_context_actions_fnc_switchVehicleWeapon
18+
*
19+
* Public: No
20+
*/
21+
22+
params ["_vehicle", "_turretPath", "_weapon", "_muzzle", "_magazine"];
23+
24+
// For regular (non-pylon) magazines, load the magazine instantly into the selected weapon
25+
// Pylon magazines work differently and only need to have the corresponding pylon weapon selected
26+
if !(_magazine in getPylonMagazines _vehicle) then {
27+
[_vehicle, _turretPath, _weapon, _magazine] call EFUNC(common,loadMagazineInstantly);
28+
};
29+
30+
// Select the given weapon and muzzle on the vehicle's turret
31+
[QEGVAR(common,selectWeaponTurret), [_vehicle, _weapon, _turretPath, _muzzle], _vehicle, _turretPath] call CBA_fnc_turretEvent;

addons/loadout/functions/fnc_getWeaponName.sqf

+1-6
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,5 @@
2020
params ["_vehicle", "_weapon", "_turretPath"];
2121

2222
private _weaponName = getText (configFile >> "CfgWeapons" >> _weapon >> "displayName");
23-
private _gunnerName = getText ([_vehicle, _turretPath] call CBA_fnc_getTurret >> "gunnerName");
24-
25-
if (_gunnerName == "") then {
26-
_gunnerName = localize (["str_driver", "str_pilot"] select (_vehicle isKindOf "Air"));
27-
};
28-
23+
private _gunnerName = [_vehicle, _turretPath] call EFUNC(common,getGunnerName);
2924
format ["%1 (%2)", _weaponName, _gunnerName]

0 commit comments

Comments
 (0)