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 - Add Electronic Hearing Protection #10476

Merged
merged 25 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e43b8d7
Refactor hearing capability, add fade duration
BaerMitUmlaut Oct 19, 2024
f09e784
Remove hasEarPlugsIn function
BaerMitUmlaut Oct 19, 2024
10d4c0d
Add base electronic hearing protection implementation
BaerMitUmlaut Oct 23, 2024
709abdc
Update macro
BaerMitUmlaut Oct 27, 2024
a77e8b5
Update docs
BaerMitUmlaut Oct 27, 2024
c165e91
Fix typo
BaerMitUmlaut Oct 27, 2024
62b2b72
Handle vehicle explosions
BaerMitUmlaut Nov 3, 2024
fa7d83e
Use effects volume again for ear ringing
BaerMitUmlaut Nov 3, 2024
92c69b6
Copy remaining functionality and docs from earplugs
BaerMitUmlaut Nov 3, 2024
123ed1e
Fix EHP muting with built in EHP
BaerMitUmlaut Nov 3, 2024
0eb6881
Fix docs
BaerMitUmlaut Nov 3, 2024
f915ba1
Remove hasEarPlugsIn again
BaerMitUmlaut Nov 4, 2024
cb2c68f
Remove outdated comment
BaerMitUmlaut Nov 4, 2024
b645624
Fix indentation
BaerMitUmlaut Nov 4, 2024
a093489
Lowercase ID for backwards compatibility
BaerMitUmlaut Nov 4, 2024
3b4d92e
Merge remote-tracking branch 'origin' into ehp
LinkIsGrim Dec 14, 2024
48c8bc3
fix stringtable
LinkIsGrim Dec 14, 2024
9616207
update logical order
LinkIsGrim Dec 16, 2024
9c3f6b4
add Field Manual stringtables
LinkIsGrim Dec 16, 2024
d0354eb
Merge remote-tracking branch 'origin' into ehp
LinkIsGrim Dec 16, 2024
b517d88
fix field manual
LinkIsGrim Dec 16, 2024
f29958c
arsenal stats
LinkIsGrim Dec 16, 2024
19382d6
fix field manual
LinkIsGrim Dec 16, 2024
3b172f0
Merge remote-tracking branch 'origin' into ehp
LinkIsGrim Dec 17, 2024
926d02a
stats
LinkIsGrim Dec 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion addons/common/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ GVAR(statusEffect_Names) = [];
GVAR(statusEffect_isGlobal) = [];
GVAR(statusEffect_sendJIP) = [];

GVAR(setHearingCapabilityMap) = [];
GVAR(setHearingCapabilityMap) = createHashMap;
BaerMitUmlaut marked this conversation as resolved.
Show resolved Hide resolved

[] call FUNC(setupLocalUnitsHandler); // Add local units event handlers (ace_common_localUnits)

Expand Down
43 changes: 14 additions & 29 deletions addons/common/functions/fnc_setHearingCapability.sqf
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#include "..\script_component.hpp"
/*
* Author: Glowbal
* Author: Glowbal, BaerMitUmlaut
* Handle set volume calls. Will use the lowest available volume setting.
*
* Arguments:
* 0: ID <STRING>
* 1: Settings <NUMBER>
* 2: Add (true) or remove (false) <BOOL> (default: true)
* 3: Volume fade duration <NUMBER> (default: 0)
*
* Return Value:
* None
Expand All @@ -17,40 +18,24 @@
* Public: Yes
*/

params ["_id", "_setting", ["_add", true]];
params ["_id", "_setting", ["_add", true], ["_fadeDuration", 0]];
BaerMitUmlaut marked this conversation as resolved.
Show resolved Hide resolved

private _exists = false;
private _lowestVolume = 1;

GVAR(setHearingCapabilityMap) = GVAR(setHearingCapabilityMap) select {
_x params ["_xID", "_xSetting"];
if (_id == _xID) then {
_exists = true;
if (_add) then {
_x set [1, _setting];
_lowestVolume = _lowestVolume min _setting;
true
} else {
false
};
} else {
_lowestVolume = _lowestVolume min _xSetting;
true
};
// Save setting
if (_add) then {
GVAR(setHearingCapabilityMap) set [_id, _setting];
} else {
GVAR(setHearingCapabilityMap) deleteAt _id;
};

if (!_exists && _add) then {
_lowestVolume = _lowestVolume min _setting;
GVAR(setHearingCapabilityMap) pushBack [_id, _setting];
};
private _lowestVolume = selectMin values GVAR(setHearingCapabilityMap);

// in game sounds
0 fadeSound _lowestVolume;
0 fadeRadio _lowestVolume;
// In-game sounds
_fadeDuration fadeSound _lowestVolume;
_fadeDuration fadeRadio _lowestVolume;
if (GVAR(allowFadeMusic)) then {
0 fadeMusic _lowestVolume;
_fadeDuration fadeMusic _lowestVolume;
};

// Set Radio mod variables.
// Set radio mod variables
ACE_player setVariable ["tf_globalVolume", _lowestVolume];
if (!isNil "acre_api_fnc_setGlobalVolume") then { [_lowestVolume^0.33] call acre_api_fnc_setGlobalVolume; };
8 changes: 8 additions & 0 deletions addons/fieldmanual/CfgHints.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ class CfgHints {
description = CSTRING(Items_EarPlugs_Description);
tip = "<a href='https://ace3.acemod.org/wiki/feature/hearing'>Hearing Wiki</a>";
};
class ACE_EHP: ACE_FieldManual_Base {
logicalOrder = 10;
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved
arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_EHP' call FUNC(getItemName))};
displayName = "%14";
displayNameShort = CSTRING(Items_EHP_ShortName);
description = CSTRING(Items_EHP_Description);
LinkIsGrim marked this conversation as resolved.
Show resolved Hide resolved
tip = "<a href='https://ace3.acemod.org/wiki/feature/hearing'>Hearing Wiki</a>";
};
class ACE_EntrenchingTool: ACE_FieldManual_Base {
logicalOrder = 11;
arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_EntrenchingTool' call FUNC(getItemName))};
Expand Down
33 changes: 33 additions & 0 deletions addons/hearing/CfgEventHandlers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,36 @@ class Extended_Respawn_EventHandlers {
};
};
};

class Extended_Killed_EventHandlers {
class Car {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
class Tank {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
class Motorcycle {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
class Helicopter {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
class Plane {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
class Ship_F {
class ADDON {
killed = QUOTE(_this call FUNC(handleVehicleKilled));
};
};
};
30 changes: 28 additions & 2 deletions addons/hearing/CfgVehicles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,36 @@ class CfgVehicles {
class ACE_Equipment {
class ACE_PutInEarplugs {
displayName = CSTRING(EarPlugs_On);
condition = QUOTE(GVAR(enableCombatDeafness) && {!(_player call FUNC(hasEarPlugsIn)) && {[ARR_2(_player,'ACE_EarPlugs')] call EFUNC(common,hasItem)}});
condition = QUOTE(GVAR(enableCombatDeafness) && {!(_player getVariable [ARR_2('ACE_hasEarPlugsIn',false)]) && {[ARR_2(_player,'ACE_EarPlugs')] call EFUNC(common,hasItem)}});
exceptions[] = {"isNotSwimming", "isNotInside", "isNotSitting"};
statement = QUOTE([ARR_2(_player,true)] call FUNC(putInEarPlugs));
showDisabled = 0;
icon = QPATHTOF(UI\ACE_earplugs_x_ca.paa);
};
class ACE_RemoveEarplugs {
displayName = CSTRING(EarPlugs_Off);
condition = QUOTE(GVAR(enableCombatDeafness) && {_player call FUNC(hasEarPlugsIn)});
condition = QUOTE(GVAR(enableCombatDeafness) && {_player getVariable [ARR_2('ACE_hasEarPlugsIn',false)]});
exceptions[] = {"isNotSwimming", "isNotInside", "isNotSitting"};
statement = QUOTE([ARR_2(_player,true)] call FUNC(removeEarPlugs));
showDisabled = 0;
icon = QPATHTOF(UI\ACE_earplugs_x_ca.paa);
};
class ACE_PutOnEHP {
displayName = CSTRING(ElectronicHearingProtection_On);
condition = QUOTE([_player] call FUNC(canPutOnEHP));
exceptions[] = {"isNotSwimming", "isNotInside", "isNotSitting"};
statement = QUOTE([ARR_2(_player,true)] call FUNC(putOnEHP));
showDisabled = 0;
icon = "\A3\Characters_F_Orange\Headgear\Data\UI\icon_H_EarProtectors_black_F_CA.paa";
};
class ACE_RemoveEHP {
displayName = CSTRING(ElectronicHearingProtection_Off);
condition = QUOTE(GVAR(EnableCombatDeafness) && {_player getVariable [ARR_2('ACE_hasEHP',false)]});
exceptions[] = {"isNotSwimming", "isNotInside", "isNotSitting"};
statement = QUOTE([ARR_2(_player,true)] call FUNC(removeEHP));
showDisabled = 0;
icon = "\A3\Characters_F_Orange\Headgear\Data\UI\icon_H_EarProtectors_black_F_CA.paa";
};
};
};
};
Expand All @@ -32,60 +48,70 @@ class CfgVehicles {
class Box_NATO_Support_F: NATO_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class B_supplyCrate_F: ReammoBox_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class Box_East_Support_F: EAST_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class O_supplyCrate_F: B_supplyCrate_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class Box_IND_Support_F: IND_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class Box_FIA_Support_F: FIA_Box_Base_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class I_supplyCrate_F: B_supplyCrate_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class IG_supplyCrate_F: ReammoBox_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class C_supplyCrate_F: ReammoBox_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

class ACE_Box_Misc: Box_NATO_Support_F {
class TransportItems {
MACRO_ADDITEM(ACE_EarPlugs,12);
MACRO_ADDITEM(ACE_EHP,12);
};
};

Expand Down
12 changes: 12 additions & 0 deletions addons/hearing/CfgWeapons.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ class CfgWeapons {
};
};

class ACE_EHP: ACE_ItemCore {
author = ECSTRING(common,ACETeam);
displayName = CSTRING(ElectronicHearingProtection_Name);
descriptionShort = CSTRING(ElectronicHearingProtection_Description);
model = "\A3\Characters_F_Orange\Headgear\H_EarProtectors_F.p3d";
picture = "\A3\Characters_F_Orange\Headgear\Data\UI\icon_H_EarProtectors_black_F_CA.paa";
scope = 2;
class ItemInfo: CBA_MiscItem_ItemInfo {
mass = 8.4; // 380g, based on 3M Peltor
};
};


class H_HelmetB;
class H_HelmetCrew_B: H_HelmetB {
Expand Down
5 changes: 4 additions & 1 deletion addons/hearing/XEH_PREP.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
PREP(addEarPlugs);
PREP(canPutOnEHP);
PREP(earRinging);
PREP(explosion);
PREP(firedNear);
PREP(getAmmoLoudness);
PREP(handleRespawn);
PREP(hasEarPlugsIn);
PREP(handleVehicleKilled);
PREP(moduleHearing);
PREP(putInEarPlugs);
PREP(putOnEHP);
PREP(removeEarPlugs);
PREP(removeEHP);
PREP(updateHearingProtection);
PREP(updatePlayerVehAttenuation);
PREP(updateVolume);
3 changes: 2 additions & 1 deletion addons/hearing/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ GVAR(time3) = 0;
GVAR(damageCoefficent) = 1;
GVAR(volumeAttenuation) = 1;
GVAR(lastPlayerVehicle) = objNull;
GVAR(ehpTimeout) = -1;

["CBA_settingsInitialized", {
TRACE_1("settingInit - client",GVAR(enableCombatDeafness));
Expand Down Expand Up @@ -97,6 +98,6 @@ GVAR(lastPlayerVehicle) = objNull;
GVAR(deafnessPrior) = 0;
GVAR(time3) = 0;

UPDATE_HEARING_EARPLUGS call FUNC(updateHearingProtection);
UPDATE_HEARING call FUNC(updateHearingProtection);
}, true] call CBA_fnc_addPlayerEventHandler;
}] call CBA_fnc_addEventHandler;
13 changes: 13 additions & 0 deletions addons/hearing/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ PREP_RECOMPILE_END;
[QGVAR(updateVolume), true, _unit] call CBA_fnc_targetEvent;
};
};

if (_extendedInfo getOrDefault ["ace_ehp", false]) then {
_unit setVariable ["ACE_hasEHP", true, true];

// Only force update volume if unit is a player (including remote controlled)
if (_unit call EFUNC(common,isPlayer)) then {
[QGVAR(updateVolume), true, _unit] call CBA_fnc_targetEvent;
};
};
}] call CBA_fnc_addEventHandler;

["CBA_loadoutGet", {
Expand All @@ -27,6 +36,10 @@ PREP_RECOMPILE_END;
if (_unit getVariable ["ACE_hasEarPlugsIn", false]) then {
_extendedInfo set ["ace_earplugs", true]
};

if (_unit getVariable ["ACE_hasEHP", false]) then {
_extendedInfo set ["ace_ehp", true]
};
}] call CBA_fnc_addEventHandler;

ADDON = true;
2 changes: 1 addition & 1 deletion addons/hearing/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {"ACE_EarPlugs"};
weapons[] = {"ACE_EarPlugs", "ACE_EHP"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_interaction"};
author = ECSTRING(common,ACETeam);
Expand Down
2 changes: 1 addition & 1 deletion addons/hearing/functions/fnc_addEarPlugs.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ params ["_unit"];
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 {};
if ((_unit getVariable ["ACE_hasEarPlugsIn", false]) || {[_unit, "ACE_EarPlugs"] call EFUNC(common,hasItem)}) exitWith {};

// Add earplugs if enabled for everyone or if the unit has a rocket launcher
if (GVAR(autoAddEarplugsToUnits) == 2 || {(secondaryWeapon _unit) != ""}) exitWith {
Expand Down
23 changes: 23 additions & 0 deletions addons/hearing/functions/fnc_canPutOnEHP.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "..\script_component.hpp"
/*
* Author: BaerMitUmlaut
* Checks if the unit can put on electronic hearing protection.
*
* Arguments:
* 0: Unit <OBJECT>
*
* Return Value:
* True if unit can put on electronic hearing protection, otherwise false.
*
* Example:
* [player] call ace_hearing_fnc_canPutOnEHP
*
* Public: No
*/
params ["_unit"];

GVAR(enableCombatDeafness)
&& {!(_unit getVariable ["ACE_hasEHP", false])}
&& {[_unit, "ACE_EHP"] call EFUNC(common,hasItem)}
&& {(headgear _unit == "") || {getNumber (configFile >> "CfgWeapons" >> headgear _unit >> QGVAR(hasEHP)) == 0}}
&& {(goggles _unit == "") || {getNumber (configFile >> "CfgGlasses" >> goggles _unit >> QGVAR(hasEHP)) == 0}}
19 changes: 19 additions & 0 deletions addons/hearing/functions/fnc_earRinging.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,23 @@ if (!GVAR(enabledForZeusUnits) && {player != ACE_player}) exitWith {};

TRACE_2("adding",_strength * GVAR(damageCoefficent),GVAR(deafnessDV));

// Handle volume reduction by electronic hearing protection
if (
_strength >= EHP_MIN_STRENGTH
&& {ACE_player getVariable ["ACE_hasEHP", false] || {ACE_player getVariable ["ACE_hasBuiltInEHP", false]}}
) then {
if (GVAR(ehpTimeout) == -1) then {
[QGVAR(ehp), EHP_REDUCTION * GVAR(volumeAttenuation), true] call EFUNC(common,setHearingCapability);

[{
CBA_missionTime >= GVAR(ehpTimeout)
}, {
[QGVAR(ehp), 1, true, EHP_FADE_IN] call EFUNC(common,setHearingCapability);
GVAR(ehpTimeout) = -1;
}] call CBA_fnc_waitUntilAndExecute;
};

GVAR(ehpTimeout) = CBA_missionTime + EHP_TIMEOUT;
};

GVAR(deafnessDV) = GVAR(deafnessDV) + (_strength * GVAR(damageCoefficent));
Loading