Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hearing - Improve and cleanup code #9933

Merged
merged 15 commits into from
May 24, 2024
Merged
1 change: 1 addition & 0 deletions addons/hearing/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ PREP(addEarPlugs);
PREP(earRinging);
PREP(explosionNear);
PREP(firedNear);
PREP(getAmmoLoudness);
PREP(handleRespawn);
PREP(hasEarPlugsIn);
PREP(moduleHearing);
Expand Down
2 changes: 1 addition & 1 deletion addons/hearing/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if (!hasInterface) exitWith {};

#include "initKeybinds.inc.sqf"

GVAR(cacheAmmoLoudness) = call CBA_fnc_createNamespace;
GVAR(cacheAmmoLoudness) = createHashMap;

GVAR(deafnessDV) = 0;
GVAR(deafnessPrior) = 0;
Expand Down
60 changes: 33 additions & 27 deletions addons/hearing/functions/fnc_addEarPlugs.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Called on unit initialization. Adds earplugs if the unit is equipped with either a really loud primary weapon or a rocket launcher.
*
* Arguments:
* 0: A Soldier <Object>
* 0: Unit <Object>
*
* Return Value:
* None
Expand All @@ -15,9 +15,9 @@
* Public: No
*/

// only run this after the settings are initialized
if !(EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(addEarPlugs), _this];
// Only run this after the settings are initialized
if (!EGVAR(common,settingsInitFinished)) exitWith {
EGVAR(common,runAtSettingsInitialized) pushBack [LINKFUNC(addEarPlugs), _this];
};

// Exit if hearing is disabled or if autoAdd is disabled
Expand All @@ -29,42 +29,48 @@ TRACE_2("params",_unit,typeOf _unit);
// Exit if the unit already has earplugs (in ears (persistence scenarios) or inventory)
if (_unit call FUNC(hasEarPlugsIn) || {[_unit, "ACE_EarPlugs"] call EFUNC(common,hasItem)}) exitWith {};

// Add earplugs if enabled for everyone or if the soldier has a rocket launcher
// Add earplugs if enabled for everyone or if the unit has a rocket launcher
if (GVAR(autoAddEarplugsToUnits) == 2 || {(secondaryWeapon _unit) != ""}) exitWith {
TRACE_1("has launcher - adding",_unit);
_unit addItem "ACE_EarPlugs";
};

// otherwise add earplugs if the soldier has a big rifle
if ((primaryWeapon _unit) == "") exitWith {};
// Otherwise add earplugs if the unit has a big rifle
private _weapon = primaryWeapon _unit;

(primaryWeaponMagazine _unit) params [["_magazine", ""]];
if (_magazine == "") exitWith {};
if (_weapon == "") exitWith {};

private _cfgMagazine = configFile >> "CfgMagazines" >> _magazine;
if (isNil QGVAR(cacheMaxAmmoLoudness)) then {
GVAR(cacheMaxAmmoLoudness) = createHashMap;
};

private _initSpeed = getNumber (_cfgMagazine >> "initSpeed");
private _ammo = getText (_cfgMagazine >> "ammo");
private _count = getNumber (_cfgMagazine >> "count");
// Cache maximum loudness for future calls
private _maxLoudness = GVAR(cacheMaxAmmoLoudness) getOrDefaultCall [_weapon, {
// Get the weapon's compatible magazines, so that all magazines are cached
// From all the loudness factors, take the max
private _maxLoudness = selectMax ((compatibleMagazines _weapon) apply {_x call FUNC(getAmmoLoudness)});

private _cfgAmmo = configFile >> "CfgAmmo";
// ace_gunbag_fnc_isMachineGun
private _config = _weapon call CBA_fnc_getItemConfig;

private _caliber = getNumber (_cfgAmmo >> _ammo >> "ACE_caliber");
_caliber = call {
if (_ammo isKindOf ["ShellBase", _cfgAmmo]) exitWith { 80 };
if (_ammo isKindOf ["RocketBase", _cfgAmmo]) exitWith { 200 };
if (_ammo isKindOf ["MissileBase", _cfgAmmo]) exitWith { 600 };
if (_ammo isKindOf ["SubmunitionBase", _cfgAmmo]) exitWith { 80 };
[_caliber, 6.5] select (_caliber <= 0);
};
private _loudness = (_caliber ^ 1.25 / 10) * (_initspeed / 1000) / 5;
// Definition of a machine gun by BIS_fnc_itemType
private _cursor = getText (_config >> "cursor");

if (toLowerANSI _cursor in ["", "emptycursor"]) then {
_cursor = getText (_config >> "cursorAim");
};

// If unit has a machine gun boost effective loudness 50%
if (_cursor == "MG") then {
_maxLoudness = _maxLoudness * 1.5;
};

//If unit has a machine gun boost effective loudness 50%
if (_count >= 50) then {_loudness = _loudness * 1.5};
_maxLoudness
}, true];

TRACE_2("primaryWeapon",_unit,_loudness);
TRACE_3("primaryWeapon",_unit,_weapon,_maxLoudness);

if (_loudness > 0.2) then {
if (_maxLoudness > 0.2) then {
TRACE_1("loud gun - adding",_unit);
_unit addItem "ACE_EarPlugs";
};
1 change: 0 additions & 1 deletion addons/hearing/functions/fnc_explosionNear.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ params ["_unit", "_damage"];
TRACE_2("explosion near player",_unit,_damage);

private _strength = (0 max _damage) * 30;
if (_strength < 0.01) exitWith {};

// Call inmediately, as it will get pick up later anyway by the update thread
[_strength] call FUNC(earRinging);
97 changes: 30 additions & 67 deletions addons/hearing/functions/fnc_firedNear.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,97 +4,60 @@
* Handles deafness due to large-caliber weapons going off near the player.
*
* Arguments:
* 0: Unit - Object the event handler is assigned to <OBJECT>
* 1: Firer: Object - Object which fires a weapon near the unit <OBJECT>
* 2: Distance - Distance in meters between the unit and firer <NUMBER>
* 3: weapon - Fired weapon <STRING>
* 4: muzzle - Muzzle that was used (not used) <STRING>
* 5: mode - Current mode of the fired weapon (not used) <STRING>
* 6: ammo - Ammo used <STRING>
* 0: Object the event handler is assigned to <OBJECT> (unused)
* 1: Object which fires a weapon near the unit <OBJECT>
* 2: Distance in meters between the unit and firer <NUMBER>
* 3: Weapon <STRING>
* 4: Muzzle <STRING>
* 5: Current mode of the fired weapon <STRING>
* 6: Ammo <STRING>
* 7: Unit that fired the weapon <STRING>
*
* Return Value:
* None
*
* Example:
* [clientFiredNearEvent] call ace_hearing_fnc_firedNear
* [player, player, 10, "arifle_MX_ACO_pointer_F", "arifle_MX_ACO_pointer_F", "single", "B_65x39_Caseless"] call ace_hearing_fnc_firedNear
* [player, player, 10, "arifle_MX_ACO_pointer_F", "arifle_MX_ACO_pointer_F", "single", "B_65x39_Caseless", player] call ace_hearing_fnc_firedNear
*
* Public: No
*/

params ["_object", "_firer", "_distance", "_weapon", "", "", "_ammo"];
params ["", "_firer", "_distance", "_weapon", "_muzzle", "_mode", "_ammo", "_gunner"];

if (_weapon in ["Throw", "Put"]) exitWith {};
if (_distance > 50) exitWith {};

private _vehAttenuation = [GVAR(playerVehAttenuation), 1] select (
(ACE_player == (vehicle ACE_player)) || {isTurnedOut ACE_player}
);
private _distance = 1 max _distance;

private _silencer = switch (_weapon) do {
case (primaryWeapon _firer) : {(primaryWeaponItems _firer) select 0};
case (secondaryWeapon _firer) : {(secondaryWeaponItems _firer) select 0};
case (handgunWeapon _firer) : {(handgunItems _firer) select 0};
default {""};
};

_distance = 1 max _distance;
private _audibleFireCoef = 1;
if (_silencer != "") then {
_audibleFireCoef = getNumber (configFile >> "CfgWeapons" >> _silencer >> "ItemInfo" >> "AmmoCoef" >> "audibleFire");
};

private _loudness = GVAR(cacheAmmoLoudness) getVariable (format ["%1%2",_weapon,_ammo]);
if (isNil "_loudness") then {
private _muzzles = getArray (configFile >> "CfgWeapons" >> _weapon >> "muzzles");
private _weaponMagazines = getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines");
{
if (_x != "this") then {
private _muzzleMagazines = getArray (configFile >> "CfgWeapons" >> _weapon >> _x >> "magazines");
_weaponMagazines append _muzzleMagazines;
};
} forEach _muzzles;
{
private _ammoType = getText(configFile >> "CfgMagazines" >> _x >> "ammo");
_weaponMagazines set [_forEachIndex, [_x, _ammoType]];
} forEach _weaponMagazines;
// Unit that fired is on foot
private _magazine = if (_gunner == _firer) then {
// Check if the unit has a suppressor
private _suppressor = (_firer weaponAccessories _weapon) select 0;

private _magazine = "";
{
_x params ["_magazineType", "_ammoType"];
if (_ammoType == _ammo) exitWith {
_magazine = _magazineType;
};
} forEach _weaponMagazines;
if (_suppressor != "") then {
_audibleFireCoef = getNumber (configFile >> "CfgWeapons" >> _suppressor >> "ItemInfo" >> "AmmoCoef" >> "audibleFire");
};

if (_magazine == "") then {
_loudness = 0;
TRACE_2("No mag for Weapon/Ammo??",_weapon,_ammo);
} else {
private _initSpeed = getNumber(configFile >> "CfgMagazines" >> _magazine >> "initSpeed");
private _caliber = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ACE_caliber");
_caliber = call {
// If explicilty defined, use ACE_caliber
if ((count configProperties [(configFile >> "CfgAmmo" >> _ammo), "configName _x == 'ACE_caliber'", false]) == 1) exitWith {_caliber};
if (_ammo isKindOf ["ShellBase", (configFile >> "CfgAmmo")]) exitWith { 80 };
if (_ammo isKindOf ["RocketBase", (configFile >> "CfgAmmo")]) exitWith { 200 };
if (_ammo isKindOf ["MissileBase", (configFile >> "CfgAmmo")]) exitWith { 600 };
if (_ammo isKindOf ["SubmunitionBase", (configFile >> "CfgAmmo")]) exitWith { 80 };
[_caliber, 6.5] select (_caliber <= 0)
};
(_firer weaponState _muzzle) select 3
} else {
// Unit that fired is in a vehicle
(weaponState [_firer, _firer unitTurret _gunner, _weapon, _muzzle, _mode]) select 3
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved
};

_loudness = (_caliber ^ 1.25 / 10) * (_initspeed / 1000) / 5;
TRACE_6("building cache",_weapon,_ammo,_magazine,_initSpeed,_caliber,_loudness);
};
GVAR(cacheAmmoLoudness) setVariable [(format ["%1%2",_weapon,_ammo]), _loudness];
if (_magazine == "") exitWith {
TRACE_5("No mag for weapon/ammo??",_weapon,_muzzle,_ammo,_firer,_gunner);
};

TRACE_6("mag",_magazine,_weapon,_muzzle,_ammo,_firer,_gunner);

private _vehAttenuation = [GVAR(playerVehAttenuation), 1] select (isNull objectParent ACE_player || {isTurnedOut ACE_player});
private _loudness = _magazine call FUNC(getAmmoLoudness);

_loudness = _loudness * _audibleFireCoef;
private _strength = _vehAttenuation * (_loudness - (_loudness / 50 * _distance)); // linear drop off

TRACE_1("result",_strength);

if (_strength < 0.01) exitWith {};

// Call inmediately, as it will get pick up later anyway by the update thread
[_strength] call FUNC(earRinging);
44 changes: 44 additions & 0 deletions addons/hearing/functions/fnc_getAmmoLoudness.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "..\script_component.hpp"
/*
* Author: KoffeinFlummi, commy2, johnb43
* Get the loudness of ammo.
* However, because `initSpeed` is a magazine attribute, the magazine name needs to be used instead of the ammo.
*
* Arguments:
* 0: Magazine <STRING>
*
* Return Value:
* None
*
* Example:
* "30Rnd_65x39_caseless_mag" call ace_hearing_fnc_getAmmoLoudness
*
* Public: No
*/

params ["_magazine"];

GVAR(cacheAmmoLoudness) getOrDefaultCall [_magazine, {
private _magazineConfig = configFile >> "CfgMagazines" >> _magazine;
private _ammo = getText (_magazineConfig >> "ammo");
private _initSpeed = getNumber (_magazineConfig >> "initSpeed");

private _cfgAmmo = configFile >> "CfgAmmo";
private _ammoConfig = _cfgAmmo >> _ammo;
private _caliber = getNumber (_ammoConfig >> "ACE_caliber");

_caliber = switch (true) do {
// If explicilty defined, use ACE_caliber
case (inheritsFrom (_ammoConfig >> "ACE_caliber") isEqualTo _ammoConfig): {_caliber};
case (_ammo isKindOf ["ShellBase", _cfgAmmo]): {80};
case (_ammo isKindOf ["RocketBase", _cfgAmmo]): {200};
case (_ammo isKindOf ["MissileBase", _cfgAmmo]): {600};
case (_ammo isKindOf ["SubmunitionBase", _cfgAmmo]): {80};
default {[_caliber, 6.5] select (_caliber <= 0)};
};

private _loudness = (_caliber ^ 1.25 / 10) * (_initspeed / 1000) / 5;
TRACE_5("building cache",_ammo,_magazine,_initSpeed,_caliber,_loudness);

_loudness
}, true]