2023-09-12 18:58:10 +00:00
|
|
|
#include "..\script_component.hpp"
|
2015-01-14 20:40:37 +00:00
|
|
|
/*
|
2015-02-14 06:39:01 +00:00
|
|
|
* Author: KoffeinFlummi
|
|
|
|
* Creates the flashbang effect and knock out AI units.
|
|
|
|
*
|
|
|
|
* Arguments:
|
2016-02-03 23:53:24 +00:00
|
|
|
* 0: The flashBang position ASL <ARRAY>
|
2015-02-14 06:39:01 +00:00
|
|
|
*
|
|
|
|
* Return Value:
|
2015-08-13 20:36:58 +00:00
|
|
|
* None
|
2015-02-14 06:39:01 +00:00
|
|
|
*
|
|
|
|
* Example:
|
2016-02-03 23:53:24 +00:00
|
|
|
* [[0,0,0]] call ace_grenades_fnc_flashbangExplosionEH
|
2015-02-14 06:39:01 +00:00
|
|
|
*
|
|
|
|
* Public: No
|
|
|
|
*/
|
2015-01-17 06:39:46 +00:00
|
|
|
|
2016-02-03 23:53:24 +00:00
|
|
|
params ["_grenadePosASL"];
|
|
|
|
TRACE_1("params",_grenadePosASL);
|
2015-01-17 06:39:46 +00:00
|
|
|
|
2016-02-19 15:02:29 +00:00
|
|
|
// 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;
|
2019-05-12 04:43:32 +00:00
|
|
|
_light setLightAttenuation [0, 1, 5, 1000, 0, 20];
|
2016-02-19 15:02:29 +00:00
|
|
|
|
|
|
|
// Reduce the light after 0.1 seconds
|
|
|
|
[{
|
|
|
|
params ["_light"];
|
|
|
|
_light setLightBrightness 5;
|
|
|
|
// Delete the light after 0.2 more seconds
|
|
|
|
[{
|
|
|
|
params ["_light"];
|
|
|
|
deleteVehicle _light;
|
2016-05-22 13:27:24 +00:00
|
|
|
}, [_light], 0.2] call CBA_fnc_waitAndExecute;
|
|
|
|
}, [_light], 0.1] call CBA_fnc_waitAndExecute;
|
2016-02-19 15:02:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Affect local AI
|
|
|
|
// @todo: Affect units in static weapons, turned out, etc
|
2016-02-03 23:53:24 +00:00
|
|
|
private _affected = (ASLtoAGL _grenadePosASL) nearEntities ["CAManBase", 20];
|
2016-02-19 15:02:29 +00:00
|
|
|
_affected = _affected - [ACE_player];
|
2015-01-17 06:39:46 +00:00
|
|
|
{
|
2015-09-26 20:39:12 +00:00
|
|
|
if (local _x && {alive _x}) then {
|
2021-11-05 18:01:01 +00:00
|
|
|
private _unit = _x;
|
|
|
|
private _strength = 1 - (((eyePos _unit) vectorDistance _grenadePosASL) min 20) / 20;
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2021-11-05 18:01:01 +00:00
|
|
|
TRACE_3("FlashBangEffect Start",_unit,((getPosASL _unit) vectorDistance _grenadePosASL),_strength);
|
2015-04-10 02:58:45 +00:00
|
|
|
|
2021-11-05 18:01:01 +00:00
|
|
|
[_unit, true] call EFUNC(common,disableAI);
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2020-02-22 20:36:25 +00:00
|
|
|
// Make AI try to look away
|
2021-11-05 18:01:01 +00:00
|
|
|
private _dirToFlash = _unit getDir _grenadePosASL;
|
|
|
|
_unit setDir (_dirToFlash + linearConversion [0.2, 1, _strength, 40, 135] * selectRandom [-1, 1]);
|
2015-09-26 20:39:12 +00:00
|
|
|
|
2021-11-05 18:01:01 +00:00
|
|
|
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];
|
|
|
|
{
|
|
|
|
_unit setSkill [_x, (_unit skill _x) / 50];
|
|
|
|
} forEach SUBSKILLS;
|
|
|
|
[{
|
|
|
|
params ["_unit"];
|
|
|
|
CBA_missiontime >= _unit getVariable [QGVAR(flashReactionDebounce), 0]
|
|
|
|
},{
|
|
|
|
params ["_unit"];
|
2015-09-26 20:39:12 +00:00
|
|
|
|
2021-11-05 18:01:01 +00:00
|
|
|
_unit setVariable [QGVAR(flashStrength), 0, true];
|
2015-04-10 02:58:45 +00:00
|
|
|
|
2021-11-05 18:01:01 +00:00
|
|
|
// 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;
|
|
|
|
};
|
2016-02-19 15:02:29 +00:00
|
|
|
};
|
|
|
|
} count _affected;
|
2015-08-15 01:25:27 +00:00
|
|
|
|
2016-02-19 18:22:24 +00:00
|
|
|
// Affect local player, independently of distance
|
2016-02-19 15:02:29 +00:00
|
|
|
if (hasInterface && {!isNull ACE_player} && {alive ACE_player}) then {
|
2021-02-18 18:58:08 +00:00
|
|
|
if ((getNumber (configOf ACE_player >> "isPlayableLogic")) == 1) exitWith {
|
2019-06-03 14:44:17 +00:00
|
|
|
TRACE_1("skipping playable logic",typeOf ACE_player); // VirtualMan_F (placeable logic zeus / spectator)
|
|
|
|
};
|
2016-02-19 15:02:29 +00:00
|
|
|
// 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
|
2015-08-15 01:25:27 +00:00
|
|
|
|
2016-02-19 18:22:24 +00:00
|
|
|
private _strength = 1 - ((_eyePos vectorDistance _grenadePosASL) min 20) / 20;
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:18:22 +00:00
|
|
|
// Check for line of sight (check 4 points in case grenade is stuck in an object or underground)
|
|
|
|
private _losCoefficient = 1;
|
2016-02-19 15:02:29 +00:00
|
|
|
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 {
|
2016-02-19 15:18:22 +00:00
|
|
|
_losCoefficient = 0.1;
|
2016-02-19 15:02:29 +00:00
|
|
|
};
|
2016-02-19 15:18:22 +00:00
|
|
|
_strength = _strength * _losCoefficient;
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:18:22 +00:00
|
|
|
// Add ace_hearing ear ringing sound effect
|
2024-01-01 01:45:01 +00:00
|
|
|
if (["ace_hearing"] call EFUNC(common,isModLoaded) && {_strength > 0 && {EGVAR(hearing,damageCoefficent) > 0.25}}) then {
|
2018-12-29 17:29:29 +00:00
|
|
|
private _earringingStrength = 40 * _strength;
|
2018-12-28 13:46:13 +00:00
|
|
|
[_earringingStrength] call EFUNC(hearing,earRinging);
|
|
|
|
TRACE_1("Earringing Strength",_earringingStrength);
|
2016-02-19 15:02:29 +00:00
|
|
|
};
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:02:29 +00:00
|
|
|
// add ace_medical pain effect:
|
2024-01-01 01:45:01 +00:00
|
|
|
if (["ace_medical"] call EFUNC(common,isModLoaded) && {_strength > 0.1}) then {
|
2016-02-19 15:02:29 +00:00
|
|
|
[ACE_player, _strength / 2] call EFUNC(medical,adjustPainLevel);
|
2015-01-17 06:39:46 +00:00
|
|
|
};
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:18:22 +00:00
|
|
|
// 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]));
|
2016-02-19 15:34:50 +00:00
|
|
|
private _dirToUnitVector = _eyePos vectorFromTo _grenadePosASL;
|
2016-02-19 15:18:22 +00:00
|
|
|
private _angleDiff = acos (_eyeDir vectorDotProduct _dirToUnitVector);
|
2016-02-19 15:34:50 +00:00
|
|
|
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);
|
2016-02-19 15:18:22 +00:00
|
|
|
};
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:18:22 +00:00
|
|
|
// Blind player
|
2016-02-19 15:02:29 +00:00
|
|
|
if (_strength > 0.1) then {
|
2021-10-05 17:29:22 +00:00
|
|
|
private _blend = [[1,1,1,0], [0.3,0.3,0.3,1]] select EGVAR(common,epilepsyFriendlyMode);
|
|
|
|
|
2016-02-19 15:02:29 +00:00
|
|
|
GVAR(flashbangPPEffectCC) ppEffectEnable true;
|
2021-10-05 17:29:22 +00:00
|
|
|
GVAR(flashbangPPEffectCC) ppEffectAdjust [1, 1, (0.8 + _strength) min 1, _blend, [0,0,0,1], [0,0,0,0]];
|
2016-02-19 15:02:29 +00:00
|
|
|
GVAR(flashbangPPEffectCC) ppEffectCommit 0.01;
|
2015-02-14 06:39:01 +00:00
|
|
|
|
2016-02-19 15:02:29 +00:00
|
|
|
//PARTIALRECOVERY - start decreasing effect over time
|
|
|
|
[{
|
|
|
|
params ["_strength"];
|
2015-04-10 03:00:03 +00:00
|
|
|
|
2016-02-19 15:02:29 +00:00
|
|
|
GVAR(flashbangPPEffectCC) ppEffectAdjust [1,1,0,[1,1,1,0],[0,0,0,1],[0,0,0,0]];
|
|
|
|
GVAR(flashbangPPEffectCC) ppEffectCommit (10 * _strength);
|
2016-05-22 13:27:24 +00:00
|
|
|
}, [_strength], 7 * _strength] call CBA_fnc_waitAndExecute;
|
2016-02-19 15:02:29 +00:00
|
|
|
|
|
|
|
//FULLRECOVERY - end effect
|
|
|
|
[{
|
|
|
|
GVAR(flashbangPPEffectCC) ppEffectEnable false;
|
2016-05-22 13:27:24 +00:00
|
|
|
}, [], 17 * _strength] call CBA_fnc_waitAndExecute;
|
2015-01-17 06:39:46 +00:00
|
|
|
};
|
2016-02-19 15:33:49 +00:00
|
|
|
|
2020-02-22 20:36:25 +00:00
|
|
|
// 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);
|
2016-02-19 15:02:29 +00:00
|
|
|
};
|
|
|
|
true
|