Skip to content

Commit f482937

Browse files
mharis001Kexanone
andauthored
Add fire mode option to Suppressive Fire module (#677)
* Add fire mode option to Suppressive Fire module * Add German translations Co-authored-by: Kex <[email protected]>
1 parent ce592fc commit f482937

File tree

6 files changed

+168
-75
lines changed

6 files changed

+168
-75
lines changed

addons/ai/functions/fnc_suppressiveFire.sqf

+99-49
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@
99
* 1: Target <OBJECT|ARRAY>
1010
* - Position must be in ATL format.
1111
* 2: Duration <NUMBER> (default: 20)
12-
* 3: Stance <STRING> (default: "AUTO")
12+
* 3: Fire Mode <NUMBER> (default: 4)
13+
* - 0: Single shots (slow).
14+
* - 1: Single shots (fast).
15+
* - 2: Three round bursts (slow).
16+
* - 3: Three round bursts (fast).
17+
* - 4: Fully automatic (with pauses).
18+
* - 5: Fully automatic (uninterrupted).
19+
* - May not apply to weapons limited by long ammo reloading times.
20+
* 4: Stance <STRING> (default: "AUTO")
21+
* - Must be one of the modes used by the setUnitPos command.
1322
*
1423
* Return Value:
1524
* None
@@ -27,6 +36,7 @@ params [
2736
["_unit", objNull, [objNull, grpNull]],
2837
["_target", [0, 0, 0], [[], objNull], 3],
2938
["_duration", 20, [0]],
39+
["_fireMode", 4, [0]],
3040
["_stance", "AUTO", [""]]
3141
];
3242

@@ -36,7 +46,7 @@ if (!local _unit) exitWith {
3646

3747
if (_unit isEqualType grpNull) exitWith {
3848
{
39-
[_x, _target, _duration, _stance] call FUNC(suppressiveFire);
49+
[_x, _target, _duration, _fireMode, _stance] call FUNC(suppressiveFire);
4050
} forEach units _unit;
4151
};
4252

@@ -101,6 +111,16 @@ _unit lookAt _target;
101111
_unit doWatch _target;
102112
_unit doTarget _target;
103113

114+
// Get the rounds per burst and time between bursts based on the given fire mode
115+
[
116+
[1, [2, 3, 4]],
117+
[1, [1, 1.5, 2]],
118+
[3, [2, 3, 4]],
119+
[3, [1, 1.5, 2]],
120+
[10, [1.25, 1.5, 1.75]],
121+
[10, [0, 0, 0]]
122+
] select (0 max _fireMode min 5) params ["_roundsPerBurst", "_burstDelay"];
123+
104124
// Force the unit to fire their weapon for the specified duration. Works better than using the doSuppressiveFire
105125
// command which does not make units realiably fire at the target, especially at longer distances. Small initial
106126
// delay to give units time to aim at the target. We ignore reloading and give units infinite ammo to create a
@@ -109,7 +129,21 @@ private _endTime = CBA_missionTime + _duration + TARGETING_DELAY;
109129

110130
[{
111131
[{
112-
params ["_unit", "_target", "_isTempTarget", "_abilities", "_skills", "_behaviour", "_combatMode", "_unitPos", "_shotTime", "_endTime"];
132+
params [
133+
"_unit",
134+
"_target",
135+
"_isTempTarget",
136+
"_abilities",
137+
"_skills",
138+
"_behaviour",
139+
"_combatMode",
140+
"_unitPos",
141+
"_roundsPerBurst",
142+
"_burstDelay",
143+
"_currentBurstRounds",
144+
"_shotTime",
145+
"_endTime"
146+
];
113147

114148
if (
115149
!alive _unit
@@ -144,63 +178,79 @@ private _endTime = CBA_missionTime + _duration + TARGETING_DELAY;
144178

145179
if (CBA_missionTime >= _shotTime) then {
146180
private _vehicle = vehicle _unit;
181+
private _turretPath = _vehicle unitTurret _unit;
147182

148-
if (_vehicle == _unit) exitWith {
149-
weaponState _unit params ["_weapon", "_muzzle", "_fireMode"];
150-
151-
_unit setAmmo [_weapon, 1e6];
152-
_unit forceWeaponFire [_muzzle, _fireMode];
153-
_this set [8, CBA_missionTime + 0.1];
154-
};
155-
156-
if (_unit call EFUNC(common,isUnitFFV)) exitWith {
157-
// Using UseMagazine action since forceWeaponFire command does not work for FFV units
158-
// UseMagazine action doesn't seem to work with currently loaded magazine (currentMagazineDetail)
159-
// Therefore, this relies on the unit having an extra magazine in their inventory
160-
// but should be fine in most situations
161-
private _weapon = currentWeapon _unit;
162-
private _compatibleMagazines = _weapon call CBA_fnc_compatibleMagazines;
163-
private _index = magazines _unit findIf {_x in _compatibleMagazines};
164-
if (_index == -1) exitWith {};
165-
166-
private _magazine = magazinesDetail _unit select _index;
167-
_magazine call EFUNC(common,parseMagazineDetail) params ["_id", "_owner"];
168-
169-
_unit setAmmo [_weapon, 1e6];
170-
CBA_logic action ["UseMagazine", _unit, _unit, _owner, _id];
171-
_this set [8, CBA_missionTime + 0.1];
172-
};
183+
switch (true) do {
184+
// On foot
185+
case (_vehicle == _unit): {
186+
weaponState _unit params ["_weapon", "_muzzle", "_fireMode"];
173187

174-
private _turretPath = _vehicle unitTurret _unit;
175-
private _muzzle = weaponState [_vehicle, _turretPath] select 1;
176-
_unit setAmmo [_muzzle, 1e6];
188+
_unit setAmmo [_weapon, 1e6];
189+
_unit forceWeaponFire [_muzzle, _fireMode];
190+
};
177191

178-
// Get the reload time for the current weapon state
179-
weaponState [_vehicle, _turretPath] params ["_weapon", "_muzzle", "_fireMode", "_magazine", "_ammo"];
192+
// FFV
193+
case (_unit call EFUNC(common,isUnitFFV)): {
194+
// Using UseMagazine action since forceWeaponFire command does not work for FFV units
195+
// UseMagazine action doesn't seem to work with currently loaded magazine (currentMagazineDetail)
196+
// Therefore, this relies on the unit having an extra magazine in their inventory
197+
// but should be fine in most situations
198+
private _weapon = currentWeapon _unit;
199+
private _compatibleMagazines = _weapon call CBA_fnc_compatibleMagazines;
200+
private _index = magazines _unit findAny _compatibleMagazines;
201+
if (_index == -1) exitWith {};
202+
203+
private _magazine = magazinesDetail _unit select _index;
204+
_magazine call EFUNC(common,parseMagazineDetail) params ["_id", "_owner"];
205+
206+
_unit setAmmo [_weapon, 1e6];
207+
CBA_logic action ["UseMagazine", _unit, _unit, _owner, _id];
208+
};
180209

181-
private _config = configFile >> "CfgWeapons" >> _weapon;
210+
// Vehicle gunner
211+
default {
212+
private _muzzle = weaponState [_vehicle, _turretPath] select 1;
213+
_unit setAmmo [_muzzle, 1e6];
182214

183-
if (_muzzle != _weapon) then {
184-
_config = _config >> _muzzle;
215+
private _magazine = _vehicle currentMagazineDetailTurret _turretPath;
216+
_magazine call EFUNC(common,parseMagazineDetail) params ["_id", "_owner"];
217+
_vehicle action ["UseMagazine", _vehicle, _unit, _owner, _id];
218+
};
185219
};
186220

187-
if (_muzzle != _fireMode) then {
188-
_config = _config >> _fireMode;
189-
};
221+
// Set time until the next shot based on the weapon's ammo reloading time and whether the current burst is finished
222+
private _reloadTime = [_vehicle, _turretPath] call EFUNC(common,getWeaponReloadTime);
223+
_currentBurstRounds = _currentBurstRounds + 1;
190224

191-
private _reloadTime = getNumber (_config >> "reloadTime");
225+
if (_currentBurstRounds >= _roundsPerBurst) then {
226+
_currentBurstRounds = 0;
192227

193-
// Find the correct magazine id and owner and force the weapon to fire
194-
{
195-
_x params ["_xMagazine", "_xTurretPath", "_xAmmo", "_id", "_owner"];
228+
// Calculate the delay until the next burst
229+
// Use ammo reloading time if it is longer to prevent firing before the weapon is ready
230+
private _nextBurstDelay = random _burstDelay max _reloadTime;
231+
_shotTime = CBA_missionTime + _nextBurstDelay;
232+
} else {
233+
_shotTime = CBA_missionTime + _reloadTime;
234+
};
196235

197-
if (_xTurretPath isEqualTo _turretPath && {_xMagazine == _magazine && {_xAmmo == _ammo && {_xAmmo != 0}}}) exitWith {
198-
_vehicle action ["UseMagazine", _vehicle, _unit, _owner, _id];
199-
_this set [8, CBA_missionTime + _reloadTime];
200-
};
201-
} forEach magazinesAllTurrets _vehicle;
236+
_this set [10, _currentBurstRounds];
237+
_this set [11, _shotTime];
202238
};
203239

204240
false // Continue
205241
}, {}, _this] call CBA_fnc_waitUntilAndExecute;
206-
}, [_unit, _target, _isTempTarget, _abilities, _skills, _behaviour, _combatMode, _unitPos, 0, _endTime], TARGETING_DELAY] call CBA_fnc_waitAndExecute;
242+
}, [
243+
_unit,
244+
_target,
245+
_isTempTarget,
246+
_abilities,
247+
_skills,
248+
_behaviour,
249+
_combatMode,
250+
_unitPos,
251+
_roundsPerBurst,
252+
_burstDelay,
253+
0, // _currentBurstRounds
254+
0, // _shotTime
255+
_endTime
256+
], TARGETING_DELAY] call CBA_fnc_waitAndExecute;

addons/common/functions/fnc_fireVLS.sqf

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ if (_position isEqualType "") then {
3636
};
3737

3838
private _muzzle = (_unit weaponsTurret GUNNER_TURRET) param [0, ""];
39-
private _reloadTime = [_unit, _muzzle, GUNNER_TURRET] call FUNC(getWeaponReloadTime);
39+
private _reloadTime = [_unit, GUNNER_TURRET, _muzzle] call FUNC(getWeaponReloadTime);
4040

4141
// Load magazine even if it is the right one in order to ignore a possible reload occurring at the same time
4242
[_unit, GUNNER_TURRET, _muzzle, _magazine] call FUNC(loadMagazineInstantly);
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,48 @@
11
#include "script_component.hpp"
22
/*
33
* Author: Kex
4-
* Returns the ammo reloading time of the given weapon.
4+
* Returns the ammo reloading time of the given weapon or muzzle.
55
*
66
* Arguments:
77
* 0: Unit or Vehicle <OBJECT>
8-
* 1: Muzzle <STRING>
9-
* 2: Turret Path <ARRAY>
8+
* 1: Turret Path <ARRAY> (default: [0])
9+
* - Only used if the given entity is a vehicle.
10+
* 2: Weapon or Muzzle <STRING> (default: "")
11+
* - Use "" for current weapon.
1012
*
1113
* Return Value:
1214
* Reload Time <NUMBER>
1315
*
1416
* Example:
15-
* [_unit, "arifle_MX_ACO_pointer_F"] call zen_common_fnc_getWeaponReloadTime
17+
* [_unit, "arifle_MX_F"] call zen_common_fnc_getWeaponReloadTime
1618
*
1719
* Public: No
1820
*/
1921

20-
params [["_entity", objNull, [objNull]], ["_muzzle", "", [""]], ["_turretPath", [], [[]]]];
22+
params [
23+
["_entity", objNull, [objNull]],
24+
["_turretPath", [0], [[]]],
25+
["_weaponOrMuzzle", "", [""]]
26+
];
2127

22-
// Get the weapon mode
23-
private "_state";
24-
25-
if (_entity isKindOf "CAManBase") then {
26-
// Need to set the desired muzzle in order to get the correct fire mode
27-
private _currentMuzzle = weaponState _entity select 1;
28-
_entity selectWeapon _muzzle;
29-
_state = weaponState _entity;
30-
31-
// Restore the original muzzle
32-
_entity selectWeapon _currentMuzzle;
28+
// Get given weapon or muzzle's current state
29+
private _state = if (_entity isKindOf "CAManBase") then {
30+
_entity weaponState _weaponOrMuzzle
3331
} else {
34-
_state = weaponState [_entity, _turretPath, _muzzle];
32+
weaponState [_entity, _turretPath, _weaponOrMuzzle]
3533
};
3634

37-
_state params ["_weapon", "", "_mode"];
35+
_state params ["_weapon", "_muzzle", "_fireMode"];
3836

37+
// Get ammo reloading time
3938
private _config = configFile >> "CfgWeapons" >> _weapon;
4039

4140
if (_muzzle != _weapon) then {
4241
_config = _config >> _muzzle;
4342
};
4443

45-
if (_mode != "this") then {
46-
_config = _config >> _mode;
44+
if (_muzzle != _fireMode) then {
45+
_config = _config >> _fireMode;
4746
};
4847

4948
getNumber (_config >> "reloadTime")

addons/main/script_mod.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD
1111

1212
// MINIMAL required version for the Mod. Components can specify others..
13-
#define REQUIRED_VERSION 2.08
13+
#define REQUIRED_VERSION 2.10
1414
#define REQUIRED_CBA_VERSION {3,15,5}
1515

1616
#ifdef COMPONENT_BEAUTIFIED

addons/modules/functions/fnc_moduleSuppressiveFire.sqf

+20-4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ if !(side group _unit in [west, east, independent, civilian]) exitWith {
4242
[ELSTRING(common,Duration_Units), LSTRING(SuppressiveFire_Duration_Tooltip)],
4343
[10, 180, 20, 0]
4444
],
45+
[
46+
"COMBO",
47+
LSTRING(SuppressiveFire_FireMode_SingleShotSlow),
48+
[
49+
[],
50+
[
51+
LSTRING(SuppressiveFire_FireMode_SingleShotsSlow),
52+
LSTRING(SuppressiveFire_FireMode_SingleShotsFast),
53+
LSTRING(SuppressiveFire_FireMode_ThreeRoundBurstsSlow),
54+
LSTRING(SuppressiveFire_FireMode_ThreeRoundBurstsFast),
55+
LSTRING(SuppressiveFire_FireMode_FullyAutomaticWithPauses),
56+
LSTRING(SuppressiveFire_FireMode_FullyAutomaticUninterrupted)
57+
],
58+
4
59+
]
60+
],
4561
[
4662
"COMBO",
4763
["STR_A3_RscAttributeUnitPos_Title", LSTRING(SuppressiveFire_Stance_Tooltip)],
@@ -66,23 +82,23 @@ if !(side group _unit in [west, east, independent, civilian]) exitWith {
6682
]
6783
], {
6884
params ["_values", "_unit"];
69-
_values params ["_duration", "_stance", "_entireGroup"];
85+
_values params ["_duration", "_fireMode", "_stance", "_entireGroup"];
7086

7187
private _units = if (_entireGroup) then {units _unit} else {[_unit]};
7288
_units = _units apply {vehicle _x};
7389
_units = _units arrayIntersect _units;
7490

7591
[_units, {
7692
params ["_successful", "_units", "_position", "_args"];
77-
_args params ["_duration", "_stance"];
93+
_args params ["_duration", "_fireMode", "_stance"];
7894

7995
if (_successful) then {
8096
curatorMouseOver params ["_type", "_entity"];
8197

8298
private _target = [ASLtoATL _position, _entity] select (_type == "OBJECT");
8399
{
84-
[_x, _target, _duration, _stance] call EFUNC(ai,suppressiveFire);
100+
[_x, _target, _duration, _fireMode, _stance] call EFUNC(ai,suppressiveFire);
85101
} forEach _units;
86102
};
87-
}, [_duration, _stance], ELSTRING(ai,SuppressiveFire)] call EFUNC(common,selectPosition);
103+
}, [_duration, _fireMode, _stance], ELSTRING(ai,SuppressiveFire)] call EFUNC(common,selectPosition);
88104
}, {}, _unit] call EFUNC(dialog,create);

addons/modules/stringtable.xml

+28
Original file line numberDiff line numberDiff line change
@@ -3237,6 +3237,34 @@
32373237
<German>Kontrolliert die Zeit in Sekunden, in der die Einheit unterdrückt.</German>
32383238
<Italian>Controlla la quantità di tempo, in secondi, per la quale le unità sopprimeranno.</Italian>
32393239
</Key>
3240+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode">
3241+
<English>Fire Mode</English>
3242+
<German>Feuermodus</German>
3243+
</Key>
3244+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_SingleShotsSlow">
3245+
<English>Single Shots (Slow)</English>
3246+
<German>Einzelfeuer (Langsam)</German>
3247+
</Key>
3248+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_SingleShotsFast">
3249+
<English>Single Shots (Fast)</English>
3250+
<German>Einzelfeuer (Schnell)</German>
3251+
</Key>
3252+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_ThreeRoundBurstsSlow">
3253+
<English>Three Round Bursts (Slow)</English>
3254+
<German>Feuerstoß (Langsam)</German>
3255+
</Key>
3256+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_ThreeRoundBurstsFast">
3257+
<English>Three Round Bursts (Fast)</English>
3258+
<German>Feuerstoß (Schnell)</German>
3259+
</Key>
3260+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_FullyAutomaticWithPauses">
3261+
<English>Fully Automatic (With Pauses)</English>
3262+
<German>Dauerfeuer (Mit Pausen)</German>
3263+
</Key>
3264+
<Key ID="STR_ZEN_Modules_SuppressiveFire_FireMode_FullyAutomaticUninterrupted">
3265+
<English>Fully Automatic (Uninterrupted)</English>
3266+
<German>Dauerfeuer (Ununterbrochen)</German>
3267+
</Key>
32403268
<Key ID="STR_ZEN_Modules_SuppressiveFire_Stance_Tooltip">
32413269
<English>Controls the stance units on foot will employ while suppressing.</English>
32423270
<Japanese>ユニットは指定された体勢で、制圧射撃を行います。</Japanese>

0 commit comments

Comments
 (0)