Grenades - Code cleanup (#9979)

* Improved various aspects of grenades

* Update addons/grenades/functions/fnc_flashbangExplosionEH.sqf

Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com>

* Update addons/grenades/functions/fnc_incendiary.sqf

Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com>

* Update addons/grenades/functions/fnc_incendiary.sqf

Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com>

* Update fnc_flashbangExplosionEH.sqf

* More cleanup

* Update fnc_incendiary.sqf

* Update fnc_incendiary.sqf

* Update fnc_flashbangThrownFuze.sqf

* Update fnc_flashbangThrownFuze.sqf

* Update addons/grenades/functions/fnc_nextMode.sqf

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Update addons/grenades/functions/fnc_flashbangExplosionEH.sqf

* Update addons/grenades/functions/fnc_incendiary.sqf

* Removed fix that is included in another PR

* Update fnc_incendiary.sqf

* Messed up merge conflict resolution

---------

Co-authored-by: Jouni Järvinen <rautamiekka@users.noreply.github.com>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
This commit is contained in:
johnb432 2024-06-18 10:05:01 +02:00 committed by GitHub
parent 95b7951919
commit 8fc093de8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 267 additions and 291 deletions

View File

@ -1,4 +1,3 @@
class CfgAmmo {
class Default;
class Grenade: Default {

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));

View File

@ -1,4 +1,3 @@
class CfgMagazines {
class HandGrenade;
class ACE_HandFlare_Base: HandGrenade {

View File

@ -1,4 +1,3 @@
class CfgVehicles {
class NATO_Box_Base;
class Box_NATO_Grenades_F: NATO_Box_Base {

View File

@ -1,4 +1,3 @@
class CfgWeapons {
class GrenadeLauncher;
class Throw: GrenadeLauncher {

View File

@ -1,4 +1,3 @@
class ACE_M84FlashbangEffect {
// empty
};

View File

@ -1,3 +1,4 @@
PREP(addChangeFuseItemContextMenuOptions);
PREP(damageEngineAndWheels);
PREP(flare);
PREP(flashbangExplosionEH);
@ -5,4 +6,3 @@ PREP(flashbangThrownFuze);
PREP(incendiary);
PREP(nextMode);
PREP(throwGrenade);
PREP(addChangeFuseItemContextMenuOptions);

View File

@ -1,6 +1,7 @@
// by commy2
#include "script_component.hpp"
#include "\a3\ui_f\hpp\defineDIKCodes.inc"
["ace_flashbangExploded", LINKFUNC(flashbangExplosionEH)] call CBA_fnc_addEventHandler;
[QGVAR(damageEngineAndWheels), LINKFUNC(damageEngineAndWheels)] call CBA_fnc_addEventHandler;
@ -16,21 +17,21 @@ GVAR(flashbangPPEffectCC) = ppEffectCreate ["ColorCorrections", 4265];
GVAR(flashbangPPEffectCC) ppEffectForceInNVG true;
// Add keybinds
["ACE3 Weapons", QGVAR(switchGrenadeMode), localize LSTRING(SwitchGrenadeMode), {
["ACE3 Weapons", QGVAR(switchGrenadeMode), LLSTRING(SwitchGrenadeMode), {
// Conditions: canInteract
if !([ACE_player, objNull, ["isNotEscorting", "isNotInside"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Conditions: specific
if (!([ACE_player] call CBA_fnc_canUseWeapon)) exitWith {false};
if !(ACE_player call CBA_fnc_canUseWeapon) exitWith {false};
// Don't change mode or show hint if advanced throwing is active
if (ACE_player getVariable [QEGVAR(advanced_throwing,inHand), false]) exitWith {false};
// Statement
[] call FUNC(nextMode);
}, {false}, [9, [false, false, false]], false] call CBA_fnc_addKeybind; //8 Key
call FUNC(nextMode) // return
}, {}, [DIK_8, [false, false, false]], false] call CBA_fnc_addKeybind; // 8 Key
["CBA_settingsInitialized", {
if (GVAR(convertExplosives)) then {
[] call FUNC(addChangeFuseItemContextMenuOptions);
call FUNC(addChangeFuseItemContextMenuOptions);
};
}] call CBA_fnc_addEventHandler;

View File

@ -1,7 +1,7 @@
#include "..\script_component.hpp"
/*
* Author: Cyruz
* Allows conversion of explosive charges in to throwable versions
* Allows conversion of explosive charges into throwable versions.
*
* Arguments:
* None
@ -14,7 +14,8 @@
*
* Public: No
*/
TRACE_1("addChangeFuseItemContextMenuOptions",_this);
LOG("addChangeFuseItemContextMenuOptions");
{
_x params ["_mag", "_throwableMag"];
@ -29,21 +30,25 @@
{true},
{
params ["", "", "_item", "", "_magArr"];
_item isEqualTo (_magArr select 0);
_item == (_magArr select 0)
}
],
{
params ["_unit", "", "", "_slot", "_magArr"];
private _container = "";
switch _slot do {
private _container = switch (_slot) do {
case "UNIFORM_CONTAINER": {
_container = "uniform";
"uniform"
};
case "VEST_CONTAINER": {
_container = "vest";
"vest"
};
case "BACKPACK_CONTAINER": {
_container = "backpack";
"backpack"
};
default {
""
};
};
@ -54,7 +59,7 @@
false
},
true,
[_mag,_throwableMag]
[_mag, _throwableMag]
] call CBA_fnc_addItemContextMenuOption;
[
@ -67,21 +72,25 @@
{true},
{
params ["", "", "_item", "", "_magArr"];
_item isEqualTo (_magArr select 1);
_item == (_magArr select 1)
}
],
{
params ["_unit", "", "", "_slot", "_magArr"];
private _container = "";
switch _slot do {
private _container = switch (_slot) do {
case "UNIFORM_CONTAINER": {
_container = "uniform";
"uniform"
};
case "VEST_CONTAINER": {
_container = "vest";
"vest"
};
case "BACKPACK_CONTAINER": {
_container = "backpack";
"backpack"
};
default {
""
};
};
@ -92,7 +101,7 @@
false
},
true,
[_mag,_throwableMag]
[_mag, _throwableMag]
] call CBA_fnc_addItemContextMenuOption;
} forEach [
["SatchelCharge_Remote_Mag", "ACE_SatchelCharge_Remote_Mag_Throwable"],

View File

@ -4,7 +4,7 @@
* Makes flare shine.
*
* Arguments:
* 0: The flare <OBJECT>
* 0: Flare <OBJECT>
* 1: Color of flare <ARRAY>
* 2: Intensity of flare <NUMBER>
* 3: Flare lifetime <OBJECT>
@ -34,6 +34,5 @@ _light setLightFlareMaxDistance 1000;
_light setLightDayLight true;
_light lightAttachObject [_projectile, [0,0,0]];
//_light attachTo [_projectile, [0,0,0]];
[{deleteVehicle _this}, _light, _timeToLive] call CBA_fnc_waitAndExecute;

View File

@ -4,7 +4,7 @@
* Creates the flashbang effect and knock out AI units.
*
* Arguments:
* 0: The flashBang position ASL <ARRAY>
* 0: Flashbang position ASL <ARRAY>
*
* Return Value:
* None
@ -18,152 +18,148 @@
params ["_grenadePosASL"];
TRACE_1("params",_grenadePosASL);
// Create flash to illuminate environment
if (hasInterface) then {
private _light = "#lightpoint" createVehicleLocal ASLtoAGL _grenadePosASL;
_light setPosASL _grenadePosASL;
_light setLightBrightness 20;
_light setLightAmbient [1,1,1];
_light setLightColor [1,1,1];
_light setLightDayLight true;
_light setLightAttenuation [0, 1, 5, 1000, 0, 20];
// Reduce the light after 0.1 seconds
[{
params ["_light"];
_light setLightBrightness 5;
// Delete the light after 0.2 more seconds
[{
params ["_light"];
deleteVehicle _light;
}, [_light], 0.2] call CBA_fnc_waitAndExecute;
}, [_light], 0.1] call CBA_fnc_waitAndExecute;
};
// Affect local AI (players are not local, except for ACE_player)
// @todo: Affect units in static weapons, turned out, etc
private _affected = (ASLtoAGL _grenadePosASL) nearEntities ["CAManBase", 20];
_affected = _affected - [ACE_player];
private _affected = ((ASLtoAGL _grenadePosASL) nearEntities ["CAManBase", 20]) - [ACE_player];
{
if (local _x && {_x call EFUNC(common,isAwake)}) then {
private _unit = _x;
private _strength = 1 - (((eyePos _unit) vectorDistance _grenadePosASL) min 20) / 20;
private _unit = _x;
private _strength = 1 - (((eyePos _unit) vectorDistance _grenadePosASL) min 20) / 20;
TRACE_3("FlashBangEffect Start",_unit,((getPosASL _unit) vectorDistance _grenadePosASL),_strength);
TRACE_3("FlashBangEffect Start",_unit,((getPosASL _unit) vectorDistance _grenadePosASL),_strength);
[_unit, true] call EFUNC(common,disableAI);
[_unit, true] call EFUNC(common,disableAI);
// Make AI try to look away
private _dirToFlash = _unit getDir _grenadePosASL;
_unit setDir (_dirToFlash + linearConversion [0.2, 1, _strength, 40, 135] * selectRandom [-1, 1]);
// Make AI try to look away
private _dirToFlash = _unit getDir _grenadePosASL;
_unit setDir (_dirToFlash + linearConversion [0.2, 1, _strength, 40, 135] * selectRandom [-1, 1]);
private _flashReactionDebounce = _unit getVariable [QGVAR(flashReactionDebounce), 0];
_unit setVariable [QGVAR(flashReactionDebounce), _flashReactionDebounce max (CBA_missionTime + (7 * _strength))];
if (_flashReactionDebounce < CBA_missionTime) then {
// Not used internally but could be useful for other mods
_unit setVariable [QGVAR(flashStrength), _strength, true];
[QGVAR(flashbangedAI), [_unit, _strength, _grenadePosASL]] call CBA_fnc_localEvent;
{
_unit setSkill [_x, (_unit skill _x) / 50];
} forEach SUBSKILLS;
[{
CBA_missiontime >= _this getVariable [QGVAR(flashReactionDebounce), 0]
}, {
params ["_unit"];
_unit setVariable [QGVAR(flashStrength), 0, true];
// Make sure we don't enable AI for unconscious units
if (_unit call EFUNC(common,isAwake)) then {
[_unit, false] call EFUNC(common,disableAI);
};
private _flashReactionDebounce = _unit getVariable [QGVAR(flashReactionDebounce), 0];
_unit setVariable [QGVAR(flashReactionDebounce), _flashReactionDebounce max (CBA_missionTime + (7 * _strength))];
if (_flashReactionDebounce < CBA_missionTime) then {
// Not used interally but could be useful for other mods
_unit setVariable [QGVAR(flashStrength), _strength, true];
[QGVAR(flashbangedAI), [_unit, _strength, _grenadePosASL]] call CBA_fnc_localEvent;
{
_unit setSkill [_x, (_unit skill _x) / 50];
_unit setSkill [_x, (_unit skill _x) * 50];
} forEach SUBSKILLS;
[{
params ["_unit"];
CBA_missiontime >= _unit getVariable [QGVAR(flashReactionDebounce), 0]
},{
params ["_unit"];
_unit setVariable [QGVAR(flashStrength), 0, true];
// Make sure we don't enable AI for unconscious units
if !(_unit getVariable ["ace_isUnconscious", false]) then {
[_unit, false] call EFUNC(common,disableAI);
};
{
_unit setSkill [_x, (_unit skill _x) * 50];
} forEach SUBSKILLS;
}, [_unit]] call CBA_fnc_waitUntilAndExecute;
};
}, _unit] call CBA_fnc_waitUntilAndExecute;
};
} forEach _affected;
} forEach (_affected select {local _x && {_x call EFUNC(common,isAwake)}});
if (!hasInterface) exitWith {};
// Create flash to illuminate environment
private _light = "#lightpoint" createVehicleLocal ASLtoAGL _grenadePosASL;
_light setPosASL _grenadePosASL;
_light setLightBrightness 20;
_light setLightAmbient [1,1,1];
_light setLightColor [1,1,1];
_light setLightDayLight true;
_light setLightAttenuation [0, 1, 5, 1000, 0, 20];
// Reduce the light after 0.1 seconds
[{
_this setLightBrightness 5;
// Delete the light after 0.2 more seconds
[{deleteVehicle _this}, _this, 0.2] call CBA_fnc_waitAndExecute;
}, _light, 0.1] call CBA_fnc_waitAndExecute;
// Ignore dead and placeable logic (zeus / spectator)
if (!alive ACE_player || {(getNumber (configOf ACE_player >> "isPlayableLogic")) == 1}) exitWith {};
// Affect local player, independently of distance
if (hasInterface && {!isNull ACE_player} && {alive ACE_player}) then {
if ((getNumber (configOf ACE_player >> "isPlayableLogic")) == 1) exitWith {
TRACE_1("skipping playable logic",typeOf ACE_player); // VirtualMan_F (placeable logic zeus / spectator)
};
// Do effects for player
// is there line of sight to the grenade?
private _eyePos = eyePos ACE_player; //PositionASL
_grenadePosASL set [2, (_grenadePosASL select 2) + 0.2]; // compensate for grenade glitching into ground
// Check for line of sight to the grenade
private _eyePos = eyePos ACE_player; // PositionASL
_grenadePosASL set [2, (_grenadePosASL select 2) + 0.2]; // compensate for grenade glitching into ground
private _strength = 1 - ((_eyePos vectorDistance _grenadePosASL) min 20) / 20;
private _strength = 1 - ((_eyePos vectorDistance _grenadePosASL) min 20) / 20;
// Check for line of sight (check 4 points in case grenade is stuck in an object or underground)
private _losCoefficient = 1;
private _losCount = {
!lineIntersects [_grenadePosASL vectorAdd _x, _eyePos, ACE_player]
} count [[0,0,0], [0,0,0.2], [0.1, 0.1, 0.1], [-0.1, -0.1, 0.1]];
TRACE_1("Line of sight count (out of 4)",_losCount);
if (_losCount <= 1) then {
_losCoefficient = 0.1;
};
_strength = _strength * _losCoefficient;
// Check for line of sight (check 4 points in case grenade is stuck in an object or underground)
private _losCount = {
!lineIntersects [_grenadePosASL vectorAdd _x, _eyePos, ACE_player]
} count [[0, 0, 0], [0, 0, 0.2], [0.1, 0.1, 0.1], [-0.1, -0.1, 0.1]];
TRACE_1("Line of sight count (out of 4)",_losCount);
// Add ace_hearing ear ringing sound effect
if (["ace_hearing"] call EFUNC(common,isModLoaded) && {_strength > 0 && {EGVAR(hearing,damageCoefficent) > 0.25}}) then {
private _earringingStrength = 40 * _strength;
[_earringingStrength] call EFUNC(hearing,earRinging);
TRACE_1("Earringing Strength",_earringingStrength);
};
private _losCoefficient = [1, 0.1] select (_losCount <= 1);
_strength = _strength * _losCoefficient;
// add ace_medical pain effect:
if (GETEGVAR(medical,enabled,false) && {_strength > 0.1} && {isDamageAllowed _unit} && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) then {
[ACE_player, _strength / 2] call EFUNC(medical,adjustPainLevel);
};
// Effect on vision has a wider range, with a higher falloff
_strength = 1 - (((_eyePos vectorDistance _grenadePosASL) min 25) / 25) ^ 0.4;
_strength = _strength * _losCoefficient;
// Account for people looking away by slightly reducing the effect for visual effects.
private _eyeDir = ((AGLtoASL positionCameraToWorld [0,0,1]) vectorDiff (AGLtoASL positionCameraToWorld [0,0,0]));
private _dirToUnitVector = _eyePos vectorFromTo _grenadePosASL;
private _angleDiff = acos (_eyeDir vectorDotProduct _dirToUnitVector);
TRACE_2("",_angleDiff,((1 - (_angleDiff - 45) / (120 - 45)) max 0));
// from 0-45deg, full effect
if (_angleDiff > 45) then {
_strength = _strength * ((1 - (_angleDiff - 45) / (120 - 45)) max 0);
};
// Blind player
if (_strength > 0.1) then {
private _blend = [[1,1,1,0], [0.3,0.3,0.3,1]] select EGVAR(common,epilepsyFriendlyMode);
GVAR(flashbangPPEffectCC) ppEffectEnable true;
GVAR(flashbangPPEffectCC) ppEffectAdjust [1, 1, (0.8 + _strength) min 1, _blend, [0,0,0,1], [0,0,0,0]];
GVAR(flashbangPPEffectCC) ppEffectCommit 0.01;
//PARTIALRECOVERY - start decreasing effect over time
[{
params ["_strength", "_blend"];
GVAR(flashbangPPEffectCC) ppEffectAdjust [1, 1, 0, _blend, [0,0,0,1], [0,0,0,0]];
GVAR(flashbangPPEffectCC) ppEffectCommit (10 * _strength);
}, [_strength, _blend], 7 * _strength] call CBA_fnc_waitAndExecute;
//FULLRECOVERY - end effect
[{
GVAR(flashbangPPEffectCC) ppEffectEnable false;
}, [], 17 * _strength] call CBA_fnc_waitAndExecute;
};
// Make player flinch
if (_strength <= 0.2) exitWith {};
private _minFlinch = linearConversion [0.2, 1, _strength, 0, 60, true];
private _maxFlinch = linearConversion [0.2, 1, _strength, 0, 95, true];
private _flinch = (_minFlinch + random (_maxFlinch - _minFlinch)) * selectRandom [-1, 1];
ACE_player setDir (getDir ACE_player + _flinch);
[QGVAR(flashbangedPlayer), [_strength, _grenadePosASL]] call CBA_fnc_localEvent;
// Add ace_hearing ear ringing sound effect
if (["ace_hearing"] call EFUNC(common,isModLoaded) && {_strength > 0} && {EGVAR(hearing,damageCoefficent) > 0.25}) then {
private _earringingStrength = 40 * _strength;
[_earringingStrength] call EFUNC(hearing,earRinging);
TRACE_1("Earringing Strength",_earringingStrength);
};
true
// Add ace_medical pain effect
if (GETEGVAR(medical,enabled,false) && {_strength > 0.1} && {isDamageAllowed _unit} && {_unit getVariable [QEGVAR(medical,allowDamage), true]}) then {
[ACE_player, _strength / 2] call EFUNC(medical,adjustPainLevel);
};
// Effect on vision has a wider range, with a higher falloff
_strength = 1 - (((_eyePos vectorDistance _grenadePosASL) min 25) / 25) ^ 0.4;
_strength = _strength * _losCoefficient;
// Account for people looking away by slightly reducing the effect for visual effects.
private _eyeDir = ((AGLtoASL positionCameraToWorld [0, 0, 1]) vectorDiff (AGLtoASL positionCameraToWorld [0, 0, 0]));
private _dirToUnitVector = _eyePos vectorFromTo _grenadePosASL;
private _angleDiff = acos (_eyeDir vectorDotProduct _dirToUnitVector);
TRACE_2("",_angleDiff,((1 - (_angleDiff - 45) / (120 - 45)) max 0));
// From 0-45deg, full effect
if (_angleDiff > 45) then {
_strength = _strength * ((1 - (_angleDiff - 45) / (120 - 45)) max 0);
};
// Blind player
if (_strength > 0.1) then {
private _blend = [[1, 1, 1, 0], [0.3, 0.3, 0.3, 1]] select EGVAR(common,epilepsyFriendlyMode);
GVAR(flashbangPPEffectCC) ppEffectEnable true;
GVAR(flashbangPPEffectCC) ppEffectAdjust [1, 1, (0.8 + _strength) min 1, _blend, [0, 0, 0, 1], [0, 0, 0, 0]];
GVAR(flashbangPPEffectCC) ppEffectCommit 0.01;
// PARTIALRECOVERY - start decreasing effect over time
[{
params ["_strength", "_blend"];
GVAR(flashbangPPEffectCC) ppEffectAdjust [1, 1, 0, _blend, [0, 0, 0, 1], [0, 0, 0, 0]];
GVAR(flashbangPPEffectCC) ppEffectCommit (10 * _strength);
}, [_strength, _blend], 7 * _strength] call CBA_fnc_waitAndExecute;
// FULLRECOVERY - end effect
[{
GVAR(flashbangPPEffectCC) ppEffectEnable false;
}, [], 17 * _strength] call CBA_fnc_waitAndExecute;
};
// Make player flinch
if (_strength <= 0.2) exitWith {};
private _minFlinch = linearConversion [0.2, 1, _strength, 0, 60, true];
private _maxFlinch = linearConversion [0.2, 1, _strength, 0, 95, true];
private _flinch = (_minFlinch + random (_maxFlinch - _minFlinch)) * selectRandom [-1, 1];
ACE_player setDir (getDir ACE_player + _flinch);
[QGVAR(flashbangedPlayer), [_strength, _grenadePosASL]] call CBA_fnc_localEvent;

View File

@ -4,7 +4,7 @@
* Waits for the flashbang grenade fuze to trigger and 'explode'
*
* Arguments:
* 0: projectile - Flashbang Grenade <OBJECT>
* 0: Flashbang grenade <OBJECT>
*
* Return Value:
* None
@ -18,16 +18,17 @@
params ["_projectile"];
TRACE_1("params",_projectile);
if (alive _projectile) then {
private _sounds = getArray (_projectile call CBA_fnc_getObjectConfig >> QGVAR(flashbangExplodeSound));
if (!alive _projectile) exitWith {};
(if (_sounds isEqualTo []) then {
[format ["A3\Sounds_F\arsenal\explosives\grenades\Explosion_HE_grenade_0%1.wss", floor (random 4) + 1], 5, 1.2, 400]
} else {
selectRandom _sounds
}) params ["_file", "_volume", "_pitch", "_distance"];
private _posASL = getPosASL _projectile;
private _sounds = getArray (_projectile call CBA_fnc_getObjectConfig >> QGVAR(flashbangExplodeSound));
playSound3D [_file, _projectile, false, getPosASL _projectile, _volume, _pitch, _distance];
(if (_sounds isEqualTo []) then {
[format ["A3\Sounds_F\arsenal\explosives\grenades\Explosion_HE_grenade_0%1.wss", floor (random 4) + 1], 5, 1.2, 400]
} else {
selectRandom _sounds
}) params ["_file", "_volume", "_pitch", "_distance"];
["ace_flashbangExploded", [getPosASL _projectile]] call CBA_fnc_globalEvent;
};
playSound3D [_file, _projectile, false, _posASL, _volume, _pitch, _distance];
["ace_flashbangExploded", [_posASL]] call CBA_fnc_globalEvent;

View File

@ -1,11 +1,12 @@
#include "..\script_component.hpp"
/*
* Author: commy2
* Makes incendiary burn.
* Makes an incendiary grenade burn.
*
* Arguments:
* 0: The grenade <OBJECT>
* 0: Incendiary grenade <OBJECT>
* 1: Incendiary lifetime <OBJECT>
* 2: Instigator's side <SIDE>
*
* Return Value:
* None
@ -42,16 +43,16 @@ if (isNull _projectile) exitWith {TRACE_1("null",_projectile);};
private _position = position _projectile;
// --- AI
// Alert nearby hostile AI
private _nearLocalEnemies = [];
{
{
if (local _x && {[_center, side _x] call BIS_fnc_sideIsEnemy}) then { // WE WANT THE OBJECTS SIDE HERE!
if (local _x && {[_center, side group _x] call BIS_fnc_sideIsEnemy}) then { // WE WANT THE OBJECT'S SIDE HERE!
_nearLocalEnemies pushBackUnique _x;
};
} forEach crew _x;
} forEach (_position nearObjects ALERT_NEAR_ENEMY_RANGE);
} forEach (_position nearObjects ALERT_NEAR_ENEMY_RANGE); //@todo replace with nearEntities in 2.18
{
if (behaviour _x in ["SAFE", "AWARE"]) then {
@ -59,7 +60,7 @@ private _nearLocalEnemies = [];
};
} forEach _nearLocalEnemies;
// --- fire
// Fire particles
private _fire = "#particlesource" createVehicleLocal _position;
_fire setParticleParams [
@ -99,7 +100,7 @@ _fire setParticleRandom [PARTICLE_LIFE_TIME / 4, [0.15 * EFFECT_SIZE, 0.15 * EFF
_fire setParticleFire [1.2,1.0,0.1];
_fire setDropInterval (1 / PARTICLE_DENSITY);
// --- smoke
// Smoke particles
private _smoke = "#particlesource" createVehicleLocal _position;
_smoke setParticleParams [
@ -137,7 +138,7 @@ _smoke setParticleParams [
_smoke setParticleRandom [PARTICLE_SMOKE_LIFE_TIME / 2, [0.5 * EFFECT_SIZE, 0.5 * EFFECT_SIZE, 0.2 * EFFECT_SIZE], [0.3,0.3,0.5], 1, 0, [0,0,0,0.06], 0, 0];
_smoke setDropInterval (1 / PARTICLE_SMOKE_DENSITY);
// --- light
// Light
private _light = "#lightpoint" createVehicleLocal (_position vectorAdd [0,0,0.5]);
_light setLightBrightness 1.0;
@ -150,19 +151,20 @@ _light setLightDayLight false;
_light lightAttachObject [_projectile, [0,0,0]];
// --- sound
// Sound
private _sound = objNull;
if (isServer) then {
_sound = createSoundSource ["Sound_Fire", _position, [], 0];
private _radius = 1.5 * getNumber (configOf _projectile >> "indirectHitRange");
private _intensity = getNumber (configOf _projectile >> "hit");
[QEGVAR(fire,addFireSource), [_projectile, _radius, _intensity, _projectile, {
params ["_endTime", "_projectile"];
// If incendiary no longer exists, exit
if (isNull _projectile) exitWith {
false
false // return
};
// Need to get the position every time, as grenade might have been moved
@ -181,37 +183,38 @@ if (isServer) then {
{deleteVehicle _x} forEach _this;
}, [_fire, _smoke, _light, _sound], _timeToLive] call CBA_fnc_waitAndExecute;
// --- damage
// Damage
{
if (local _x && {isDamageAllowed _x}) then {
//systemChat format ["burn: %1", _x];
// Inflame fireplace, barrels etc.
_x inflame true;
// --- destroy nearby static weapons and ammo boxes
if (_x isKindOf "StaticWeapon" || {_x isKindOf "ACE_RepairItem_Base"}) then {
// Destroy nearby static weapons and ammo boxes
if (_x isKindOf "StaticWeapon" || {_x isKindOf "ACE_RepairItem_Base"}) then {
_x setDamage 1;
continue;
};
if (_x isKindOf "ReammoBox_F") then {
if (
(["ace_cookoff"] call EFUNC(common,isModLoaded)) &&
{EGVAR(cookoff,enableAmmobox)} &&
{EGVAR(cookoff,ammoCookoffDuration) != 0} &&
{_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]}
) then {
[QEGVAR(cookOff,cookOffBoxServer), _box] call CBA_fnc_serverEvent;
} else {
_x setDamage 1;
};
if (_x isKindOf "ReammoBox_F") then {
if (
(["ace_cookoff"] call EFUNC(common,isModLoaded)) &&
{EGVAR(cookoff,enableAmmobox)} &&
{EGVAR(cookoff,ammoCookoffDuration) != 0} &&
{_x getVariable [QEGVAR(cookoff,enableAmmoCookoff), true]}
) then {
[QEGVAR(cookOff,cookOffBoxServer), _box] call CBA_fnc_serverEvent;
} else {
_x setDamage 1;
};
};
// --- delete nearby ground weapon holders
if (_x isKindOf "WeaponHolder" || {_x isKindOf "WeaponHolderSimulated"}) then {
deleteVehicle _x;
};
// --- inflame fireplace, barrels etc.
_x inflame true;
continue;
};
} forEach (_position nearObjects DESTRUCTION_RADIUS);
// Delete nearby ground weapon holders
if (_x isKindOf "WeaponHolder" || {_x isKindOf "WeaponHolderSimulated"}) then {
deleteVehicle _x;
};
} forEach ((_position nearObjects DESTRUCTION_RADIUS) select {local _x && {isDamageAllowed _x}});
{
// Damage vehicles (locality is checked in FUNC(damageEngineAndWheels))

View File

@ -7,21 +7,16 @@
* None
*
* Return Value:
* Handeled <BOOL>
* Handled <BOOL>
*
* Example:
* [] call ace_grenades_fnc_nextMode
* call ace_grenades_fnc_nextMode
*
* Public: No
*/
private _mode = GVAR(currentThrowMode);
if (_mode == 4) then {
_mode = 0;
} else {
_mode = _mode + 1;
};
// _mode is 0-4, don't overflow
private _mode = (GVAR(currentThrowMode) + 1) % 5;
private _currentThrowable = currentThrowable ACE_player;

View File

@ -27,40 +27,26 @@ if (isNull _projectile) then {
private _config = configFile >> "CfgAmmo" >> _ammo;
// handle special grenades and sounds
// Handle special grenades and sounds
if (local _unit) then {
// handle priming sound, if present
private _soundConfig = getArray (configFile >> "CfgAmmo" >> _ammo >> QGVAR(pullPinSound));
// Handle priming sound, if present
private _soundConfig = getArray (_config >> QGVAR(pullPinSound));
if (_soundConfig isNotEqualTo []) then {
_soundConfig params ["_file", "_volume", "_pitch", "_distance"];
playSound3D [_file, objNull, false, getPosASL _projectile, _volume, _pitch, _distance];
playSound3D [_file, objNull, insideBuilding _unit >= 0.5, getPosASL _projectile, _volume, _pitch, _distance];
};
if (getNumber (_config >> QGVAR(flashbang)) == 1) then {
private _bangs = 1;
private _entry = _config >> QGVAR(flashbangBangs);
if (isNumber _entry || isText _entry) then {
_bangs = getNumber _entry;
};
private _fuzeTimeBase = getNumber (_config >> "explosionTime");
private _interval = 0.5;
_entry = _config >> QGVAR(flashbangInterval);
if (isNumber _entry || isText _entry) then {
_interval = getNumber _entry;
};
private _maxDeviation = 0.1;
_entry = _config >> QGVAR(flashbangIntervalMaxDeviation);
if (isNumber _entry || isText _entry) then {
_maxDeviation = getNumber _entry;
};
private _bangs = [_config >> QGVAR(flashbangBangs), "NUMBER", 1] call CBA_fnc_getConfigEntry;
private _interval = [_config >> QGVAR(flashbangInterval), "NUMBER", 0.5] call CBA_fnc_getConfigEntry;
private _maxDeviation = [_config >> QGVAR(flashbangIntervalMaxDeviation), "NUMBER", 0.1] call CBA_fnc_getConfigEntry;
for "_i" from 0 to (_bangs - 1) do {
private _fuzeTime = _fuzeTimeBase + _i*_interval + random [- _maxDeviation, 0, _maxDeviation];
private _fuzeTime = _fuzeTimeBase + _i * _interval + random [-_maxDeviation, 0, _maxDeviation];
[FUNC(flashbangThrownFuze), [_projectile], _fuzeTime] call CBA_fnc_waitAndExecute;
[LINKFUNC(flashbangThrownFuze), _projectile, _fuzeTime] call CBA_fnc_waitAndExecute;
};
};
};
@ -71,60 +57,56 @@ if (getNumber (_config >> QGVAR(flare)) == 1) then {
private _color = getArray (_config >> QGVAR(color));
private _intensity = _color deleteAt 3;
[FUNC(flare), [_projectile, _color, _intensity, _timeToLive], _fuzeTime] call CBA_fnc_waitAndExecute;
[LINKFUNC(flare), [_projectile, _color, _intensity, _timeToLive], _fuzeTime] call CBA_fnc_waitAndExecute;
};
if (getNumber (_config >> QGVAR(incendiary)) == 1) then {
private _fuzeTime = getNumber (_config >> "explosionTime");
private _timeToLive = getNumber (_config >> "timeToLive");
[FUNC(incendiary), [_projectile, _timeToLive, side _unit], _fuzeTime] call CBA_fnc_waitAndExecute; // WE WANT THE OBJECTS SIDE HERE!
[LINKFUNC(incendiary), [_projectile, _timeToLive, side group _unit], _fuzeTime] call CBA_fnc_waitAndExecute; // Get the unit's real side (will return civilian if unconscious)
};
// handle throw modes
// Handle throw modes
if (_unit != ACE_player) exitWith {};
if (_unit getVariable [QEGVAR(advanced_throwing,primed), false]) exitWith {LOG("advanced_throwing throw");};
private _mode = GVAR(currentThrowMode);
if (GVAR(currentThrowMode) == 0) exitWith {};
if (_mode != 0) then {
private _velocity = velocity _projectile;
private _velocity = velocity _projectile;
switch (_mode) do {
//high throw
case 1 : {
_velocity = [
0.5 * (_velocity select 0),
0.5 * (_velocity select 1),
[0, 0, 0] distance (_velocity vectorMultiply 0.5)
];
};
//precise throw
case 2 : {
_velocity = (_unit weaponDirection _weapon) vectorMultiply (vectorMagnitude _velocity);
};
//roll grenade
case 3 : {
private _posASL = getPosASL _projectile;
switch (GVAR(currentThrowMode)) do {
// High throw
case 1: {
_velocity = _velocity vectorMultiply 0.5;
// getPos is unreliable, as surfaces in some ruins are not recognised as surfaces
private _lisPos = (lineIntersectsSurfaces [_posASL, _posASL vectorAdd [0, 0, -1e11], ACE_player, objNull, true, 1, "ROADWAY", "FIRE"]) select 0;
_projectile setPosASL ((_lisPos select 0) vectorAdd [0, 0, 0.2]);
// Rotate throwables by 90° to the side by default, so cylindrical throwables can be rolled
private _vectorDirAndUp = getArray (_config >> QGVAR(rollVectorDirAndUp));
_vectorDirAndUp params [["_vectorDir", [0, 1, 0], [[]], 3], ["_vectorUp", [1, 0, 0], [[]], 3]];
// Do as if object were facing north
_projectile setVectorDirAndUp ([[_vectorDir, _vectorUp], -(direction _projectile), 0, 0] call BIS_fnc_transformVectorDirAndUp);
_velocity = (vectorDir _unit) vectorMultiply 10;
};
//drop grenade
case 4 : {
_velocity = [0, 0, 0];
};
_velocity set [2, vectorMagnitude _velocity];
};
// Precise throw
case 2: {
_velocity = (_unit weaponDirection _weapon) vectorMultiply (vectorMagnitude _velocity);
};
// Roll grenade
case 3: {
private _posASL = getPosASL _projectile;
_projectile setVelocity _velocity;
// getPos is unreliable, as surfaces in some ruins are not recognised as surfaces
private _lisPos = (lineIntersectsSurfaces [_posASL, _posASL vectorAdd [0, 0, -1e11], ACE_player, objNull, true, 1, "ROADWAY", "FIRE"]) select 0;
_projectile setPosASL ((_lisPos select 0) vectorAdd [0, 0, 0.2]);
// Rotate throwables by 90° to the side by default, so cylindrical throwables can be rolled
private _vectorDirAndUp = getArray (_config >> QGVAR(rollVectorDirAndUp));
_vectorDirAndUp params [["_vectorDir", [0, 1, 0], [[]], 3], ["_vectorUp", [1, 0, 0], [[]], 3]];
// Do as if object were facing north
_projectile setVectorDirAndUp ([[_vectorDir, _vectorUp], -(direction _projectile), 0, 0] call BIS_fnc_transformVectorDirAndUp);
_velocity = (vectorDir _unit) vectorMultiply 10;
};
// Drop grenade
case 4: {
_velocity = [0, 0, 0];
};
};
_projectile setVelocity _velocity;

View File

@ -1,9 +1,10 @@
[
QGVAR(convertExplosives), "CHECKBOX",
QGVAR(convertExplosives),
"CHECKBOX",
[LSTRING(convertExplosives_DisplayName), LSTRING(convertExplosives_Description)],
LSTRING(Settings_DisplayName),
true,
true,
{},
true
1,
{[QGVAR(convertExplosives), _this] call EFUNC(common,cbaSettings_settingChanged)},
true // Needs mission restart
] call CBA_fnc_addSetting;

View File

@ -16,11 +16,6 @@
#include "\z\ace\addons\main\script_macros.hpp"
#define EFFECT_STAGE_RESETAI 0
#define EFFECT_STAGE_DELETELIGHT 1
#define EFFECT_STAGE_PARTIALRECOVERY 2
#define EFFECT_STAGE_FULLRECOVERY 3
#define EFFECT_SIZE 1
#define MIN_EXPLOSION_TIME_FOR_ROLL 1