mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge pull request #3279 from acemod/changeHearingDefaults
Overhaul ACE_Hearing and change default settings.
This commit is contained in:
commit
d3468649e3
@ -91,10 +91,9 @@ if (hasInterface && {!isNull ACE_player} && {alive ACE_player}) then {
|
||||
};
|
||||
_strength = _strength * _losCoefficient;
|
||||
|
||||
|
||||
// Add ace_hearing ear ringing sound effect
|
||||
if (isClass (configFile >> "CfgPatches" >> "ACE_Hearing") && {_strength > 0}) then {
|
||||
[ACE_player, 40 * _strength] call EFUNC(hearing,earRinging);
|
||||
[40 * _strength] call EFUNC(hearing,earRinging);
|
||||
};
|
||||
|
||||
// add ace_medical pain effect:
|
||||
|
@ -1,31 +1,38 @@
|
||||
class ACE_Settings {
|
||||
class GVAR(EnableCombatDeafness) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
displayName = CSTRING(CombatDeafness_DisplayName);
|
||||
description = CSTRING(CombatDeafness_Description);
|
||||
displayName = CSTRING(EnableCombatDeafness_DisplayName);
|
||||
description = CSTRING(EnableCombatDeafness_Description);
|
||||
};
|
||||
class GVAR(EarplugsVolume) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 0.5;
|
||||
typeName = "SCALAR";
|
||||
};
|
||||
class GVAR(UnconsciousnessVolume) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 0.4;
|
||||
typeName = "SCALAR";
|
||||
};
|
||||
class GVAR(DisableEarRinging) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 0;
|
||||
typeName = "BOOL";
|
||||
isClientSettable = 1;
|
||||
displayName = CSTRING(DisableEarRinging);
|
||||
displayName = CSTRING(DisableEarRinging_DisplayName);
|
||||
description = CSTRING(DisableEarRinging_Description);
|
||||
};
|
||||
class GVAR(enabledForZeusUnits) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
displayName = CSTRING(enabledForZeusUnits_DisplayName);
|
||||
description = CSTRING(enabledForZeusUnits_Description);
|
||||
};
|
||||
class GVAR(autoAddEarplugsToUnits) {
|
||||
category = CSTRING(Module_DisplayName);
|
||||
value = 1;
|
||||
typeName = "BOOL";
|
||||
displayName = CSTRING(autoAddEarplugsToUnits_DisplayName);
|
||||
|
@ -11,9 +11,21 @@ class CfgSounds {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\ACE_earringing_heavy.wav)),8,1.7};
|
||||
titles[] = {};
|
||||
};
|
||||
class ACE_Combat_Deafness {
|
||||
class ACE_Combat_Deafness_Heavy {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\deafness.ogg)),8,1};
|
||||
titles[] = {};
|
||||
};
|
||||
class ACE_Combat_Deafness_Medium {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\deafness.ogg)),3,1};
|
||||
titles[] = {};
|
||||
};
|
||||
class ACE_Combat_Deafness_Heavy_NoRing {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\deafness_noring.ogg)),8,1};
|
||||
titles[] = {};
|
||||
};
|
||||
class ACE_Combat_Deafness_Medium_NoRing {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\deafness_noring.ogg)),3,1};
|
||||
titles[] = {};
|
||||
};
|
||||
class ACE_Ring_Backblast {
|
||||
sound[] = {QUOTE(PATHTOF(sounds\backblast_ring.ogg)),1,1};
|
||||
|
@ -103,13 +103,14 @@ class CfgVehicles {
|
||||
icon = PATHTOF(UI\Icon_Module_Hearing_ca.paa);
|
||||
class Arguments {
|
||||
class EnableCombatDeafness {
|
||||
displayName = CSTRING(CombatDeafness_DisplayName);
|
||||
description = CSTRING(CombatDeafness_Description);
|
||||
displayName = CSTRING(EnableCombatDeafness_DisplayName);
|
||||
description = CSTRING(EnableCombatDeafness_Description);
|
||||
typeName = "BOOL";
|
||||
defaultValue = 1;
|
||||
};
|
||||
class DisableEarRinging {
|
||||
displayName = CSTRING(DisableEarRinging);
|
||||
displayName = CSTRING(DisableEarRinging_DisplayName);
|
||||
description = CSTRING(DisableEarRinging_Description);
|
||||
typeName = "NUMBER";
|
||||
class values {
|
||||
class DoNotForce {
|
||||
|
@ -2,38 +2,40 @@
|
||||
|
||||
if (!hasInterface) exitWith {};
|
||||
|
||||
GVAR(cacheAmmoLoudness) = createLocation ["ACE_HashLocation", [-10000,-10000,-10000], 0, 0];
|
||||
GVAR(cacheAmmoLoudness) setText QGVAR(cacheAmmoLoudness);
|
||||
GVAR(cacheAmmoLoudness) = call CBA_fnc_createNamespace;
|
||||
|
||||
GVAR(deafnessDV) = 0;
|
||||
GVAR(deafnessPrior) = 0;
|
||||
GVAR(volume) = 1;
|
||||
GVAR(playerVehAttenuation) = 1;
|
||||
|
||||
GVAR(beep) = false;
|
||||
GVAR(beep2) = false;
|
||||
GVAR(time2) = 0;
|
||||
GVAR(time3) = 0;
|
||||
GVAR(time4) = 0;
|
||||
GVAR(damageCoefficent) = 1;
|
||||
GVAR(volumeAttenuation) = 1;
|
||||
|
||||
["SettingsInitialized", {
|
||||
TRACE_1("settingInit",GVAR(EnableCombatDeafness));
|
||||
// Only run PFEH and install event handlers if combat deafness is enabled
|
||||
if (!GVAR(EnableCombatDeafness)) exitWith {};
|
||||
|
||||
// Update hearing protection now:
|
||||
[] call FUNC(updateHearingProtection);
|
||||
|
||||
// Spawn volume updating process
|
||||
[FUNC(updateVolume), 1, [false]] call CBA_fnc_addPerFrameHandler;
|
||||
|
||||
// Update veh attunation when player veh changes
|
||||
["playerVehicleChanged", {_this call FUNC(updatePlayerVehAttenuation);}] call EFUNC(common,addEventHandler);
|
||||
["playerTurretChanged", {_this call FUNC(updatePlayerVehAttenuation);}] call EFUNC(common,addEventHandler);
|
||||
|
||||
// Reset deafness on respawn (or remote control player switch)
|
||||
["playerChanged", {
|
||||
GVAR(deafnessDV) = 0;
|
||||
GVAR(deafnessPrior) = 0;
|
||||
ACE_player setVariable [QGVAR(deaf), false];
|
||||
GVAR(time3) = 0;
|
||||
[] call FUNC(updateHearingProtection);
|
||||
}] call EFUNC(common,addEventhandler);
|
||||
|
||||
// Update protection on possible helmet change
|
||||
["playerInventoryChanged", {[] call FUNC(updateHearingProtection);}] call EFUNC(common,addEventhandler);
|
||||
}] call EFUNC(common,addEventHandler);
|
||||
|
||||
//Update veh attunation when player veh changes
|
||||
["playerVehicleChanged", {_this call FUNC(updatePlayerVehAttenuation);}] call EFUNC(common,addEventHandler);
|
||||
["playerTurretChanged", {_this call FUNC(updatePlayerVehAttenuation);}] call EFUNC(common,addEventHandler);
|
||||
|
||||
//Reset deafness on respawn (or remote control player switch)
|
||||
["playerChanged", {
|
||||
GVAR(deafnessDV) = 0;
|
||||
GVAR(deafnessPrior) = 0;
|
||||
ACE_player setVariable [QGVAR(deaf), false];
|
||||
|
||||
GVAR(beep) = false;
|
||||
GVAR(beep2) = false;
|
||||
GVAR(time2) = 0;
|
||||
GVAR(time3) = 0;
|
||||
GVAR(time4) = 0;
|
||||
}] call EFUNC(common,addEventhandler);
|
||||
|
@ -11,6 +11,7 @@ PREP(hasEarPlugsIn);
|
||||
PREP(moduleHearing);
|
||||
PREP(putInEarPlugs);
|
||||
PREP(removeEarPlugs);
|
||||
PREP(updateHearingProtection);
|
||||
PREP(updatePlayerVehAttenuation);
|
||||
PREP(updateVolume);
|
||||
|
||||
|
@ -1,39 +1,25 @@
|
||||
/*
|
||||
* Author: KoffeinFlummi, commy2, Rocko, Rommel, Ruthberg
|
||||
* Ear ringing PFH
|
||||
* Handle new sound souce near ace_player and apply hearing damage
|
||||
*
|
||||
* Arguments:
|
||||
* 0: unit <OBJECT>
|
||||
* 1: strength of ear ringing (Number between 0 and 1) <NUMBER>
|
||||
* 0: strength of ear ringing <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [_unit, _strength] call ace_hearing_fnc_earRinging
|
||||
* [_strength] call ace_hearing_fnc_earRinging
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
params ["_unit", "_strength"];
|
||||
params ["_strength"];
|
||||
|
||||
if (_unit != ACE_player) exitWith {};
|
||||
if (_strength < 0.05) exitWith {};
|
||||
if (!isNull curatorCamera) exitWith {};
|
||||
if ((!GVAR(enabledForZeusUnits)) && {player != ACE_player}) exitWith {};
|
||||
|
||||
if (_unit getVariable ["ACE_hasEarPlugsin", false]) then {
|
||||
_strength = _strength / 4;
|
||||
};
|
||||
TRACE_2("adding",_strength * GVAR(damageCoefficent),GVAR(deafnessDV));
|
||||
|
||||
//headgear hearing protection
|
||||
if(headgear _unit != "") then {
|
||||
private _protection = (getNumber (configFile >> "CfgWeapons" >> (headgear _unit) >> QGVAR(protection))) min 1;
|
||||
if(_protection > 0) then {
|
||||
_strength = _strength * (1 - _protection);
|
||||
};
|
||||
};
|
||||
|
||||
TRACE_2("adding",_strength,GVAR(deafnessDV));
|
||||
|
||||
GVAR(deafnessDV) = GVAR(deafnessDV) + _strength;
|
||||
GVAR(deafnessDV) = GVAR(deafnessDV) + (_strength * GVAR(damageCoefficent));
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
//Only run if deafness or ear ringing is enabled:
|
||||
if ((!GVAR(enableCombatDeafness)) && GVAR(DisableEarRinging)) exitWith {};
|
||||
// Only run if combat deafness is enabled
|
||||
if (!GVAR(EnableCombatDeafness)) exitWith {};
|
||||
|
||||
params ["_unit", "_damage"];
|
||||
|
||||
@ -29,4 +29,5 @@ private ["_strength"];
|
||||
_strength = (0 max _damage) * 30;
|
||||
if (_strength < 0.01) exitWith {};
|
||||
|
||||
[{_this call FUNC(earRinging)}, [_unit, _strength], 0.2] call EFUNC(common,waitAndExecute);
|
||||
// Call inmediately, as it will get pick up later anyway by the update thread
|
||||
[_strength] call FUNC(earRinging);
|
||||
|
@ -22,8 +22,8 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
//Only run if deafness or ear ringing is enabled:
|
||||
if ((!GVAR(enableCombatDeafness)) && GVAR(DisableEarRinging)) exitWith {};
|
||||
// Only run if combat deafness is enabled
|
||||
if (!GVAR(EnableCombatDeafness)) exitWith {};
|
||||
|
||||
params ["_object", "_firer", "_distance", "_weapon", "", "", "_ammo"];
|
||||
|
||||
@ -97,4 +97,5 @@ TRACE_1("result",_strength);
|
||||
|
||||
if (_strength < 0.01) exitWith {};
|
||||
|
||||
[{_this call FUNC(earRinging)}, [ACE_player, _strength], 0.2] call EFUNC(common,waitAndExecute);
|
||||
// Call inmediately, as it will get pick up later anyway by the update thread
|
||||
[_strength] call FUNC(earRinging);
|
||||
|
@ -12,13 +12,12 @@
|
||||
|
||||
params ["_logic"];
|
||||
|
||||
[_logic, QGVAR(enableCombatDeafness), "EnableCombatDeafness"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(EnableCombatDeafness), "EnableCombatDeafness"] call EFUNC(common,readSettingFromModule);
|
||||
|
||||
// Do Not Force - read module setting only non-default is set due to using SCALAR
|
||||
if ((_logic getVariable "DisableEarRinging") != -1) then {
|
||||
[_logic, QGVAR(DisableEarRinging), "DisableEarRinging"] call EFUNC(common,readSettingFromModule);
|
||||
};
|
||||
|
||||
[_logic, QGVAR(enabledForZeusUnits), "enabledForZeusUnits"] call EFUNC(common,readSettingFromModule);
|
||||
[_logic, QGVAR(autoAddEarplugsToUnits), "autoAddEarplugsToUnits"] call EFUNC(common,readSettingFromModule);
|
||||
ACE_LOGINFO("Hearing Module Initialized.");
|
||||
|
@ -29,3 +29,5 @@ _player setVariable ["ACE_hasEarPlugsIn", true, true];
|
||||
|
||||
/*// No Earplugs in inventory, telling user
|
||||
[localize LSTRING(NoPlugs)] call EFUNC(common,displayTextStructured);*/
|
||||
|
||||
[] call FUNC(updateHearingProtection);
|
||||
|
@ -30,3 +30,5 @@ _player setVariable ["ACE_hasEarPlugsIn", false, true];
|
||||
|
||||
//Force an immediate fast volume update:
|
||||
[[true]] call FUNC(updateVolume);
|
||||
|
||||
[] call FUNC(updateHearingProtection);
|
||||
|
36
addons/hearing/functions/fnc_updateHearingProtection.sqf
Normal file
36
addons/hearing/functions/fnc_updateHearingProtection.sqf
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Updates the hearing protection and volume attenuation for player on earbuds/helmet change
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_hearing_fnc_updateHearingProtection
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
TRACE_1("params",_this);
|
||||
|
||||
if (isNull ACE_player) exitWith {
|
||||
GVAR(damageCoefficent) = 0;
|
||||
GVAR(volumeAttenuation) = 1;
|
||||
};
|
||||
|
||||
// Handle Earplugs
|
||||
private _hasEarPlugsIn = [ACE_player] call FUNC(hasEarPlugsIn);
|
||||
GVAR(damageCoefficent) = [1, 0.25] select _hasEarPlugsIn;
|
||||
GVAR(volumeAttenuation) = [1, GVAR(EarplugsVolume)] select _hasEarPlugsIn;
|
||||
|
||||
// Handle Headgear
|
||||
if (headgear ACE_player != "") then {
|
||||
private _protection = (getNumber (configFile >> "CfgWeapons" >> (headgear ACE_player) >> QGVAR(protection))) min 1;
|
||||
GVAR(damageCoefficent) = GVAR(damageCoefficent) * (1 - _protection);
|
||||
private _attenuation = (getNumber (configFile >> "CfgWeapons" >> (headgear ACE_player) >> QGVAR(lowerVolume))) min 1;
|
||||
GVAR(volumeAttenuation) = GVAR(volumeAttenuation) * (1 - _attenuation);
|
||||
};
|
@ -16,75 +16,38 @@
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
//Only run if deafness or ear ringing is enabled:
|
||||
if ((!GVAR(enableCombatDeafness)) && GVAR(DisableEarRinging)) exitWith {};
|
||||
|
||||
(_this select 0) params ["_justUpdateVolume"];
|
||||
|
||||
|
||||
GVAR(deafnessDV) = (GVAR(deafnessDV) min 20) max 0;
|
||||
GVAR(volume) = (1 - (GVAR(deafnessDV) / 20)) max 0;
|
||||
GVAR(volume) = (1 - (GVAR(deafnessDV) / 20)) max 0.05;
|
||||
TRACE_3("",GVAR(volume),GVAR(deafnessDV),GVAR(deafnessDV) - GVAR(deafnessPrior));
|
||||
|
||||
if (!_justUpdateVolume) then {
|
||||
//If we got a big increase in the last second:
|
||||
if ((GVAR(deafnessDV) - GVAR(deafnessPrior)) > 2) then {
|
||||
if (ACE_time > GVAR(time3)) then {
|
||||
GVAR(beep2) = false;
|
||||
};
|
||||
if ((!GVAR(DisableEarRinging)) && {!GVAR(beep2)}) then {
|
||||
playSound "ACE_Combat_Deafness";
|
||||
GVAR(beep2) = true;
|
||||
GVAR(time3) = ACE_time + 5;
|
||||
// Ring if we got a big increase in the last second or enough accumulated damage
|
||||
if (GVAR(deafnessDV) - GVAR(deafnessPrior) > 1 ||
|
||||
GVAR(deafnessDV) > 10) then {
|
||||
|
||||
if (ACE_time - GVAR(time3) < 3) exitWith {};
|
||||
GVAR(time3) = ACE_time;
|
||||
|
||||
if (GVAR(deafnessDV) > 19.75) then {
|
||||
playSound (["ACE_Combat_Deafness_Heavy", "ACE_Combat_Deafness_Heavy_NoRing"] select GVAR(DisableEarRinging));
|
||||
} else {
|
||||
playSound (["ACE_Combat_Deafness_Medium", "ACE_Combat_Deafness_Medium_NoRing"] select GVAR(DisableEarRinging));
|
||||
};
|
||||
};
|
||||
|
||||
GVAR(deafnessPrior) = GVAR(deafnessDV);
|
||||
|
||||
if (GVAR(deafnessDV) > 19.75) then {
|
||||
ACE_player setVariable [QGVAR(deaf), true];
|
||||
if ((!GVAR(DisableEarRinging)) && {ACE_time > GVAR(time4)}) then {
|
||||
playSound "ACE_Combat_Deafness";
|
||||
GVAR(beep2) = true;
|
||||
GVAR(time3) = ACE_time + 10;
|
||||
GVAR(time4) = ACE_time + 30;
|
||||
};
|
||||
} else {
|
||||
ACE_player setVariable [QGVAR(deaf), false];
|
||||
};
|
||||
|
||||
if (GVAR(deafnessDV) > 10) then {
|
||||
//check if the ringing is already being played
|
||||
if (ACE_time > GVAR(time2)) then {
|
||||
GVAR(beep) = false;
|
||||
};
|
||||
if ((!GVAR(DisableEarRinging)) && {!GVAR(beep)}) then {
|
||||
playSound "ACE_Ring_Backblast";
|
||||
GVAR(time2) = ACE_time + 22;
|
||||
GVAR(beep) = true;
|
||||
};
|
||||
};
|
||||
|
||||
// Hearing takes longer to return to normal after it hits rock bottom
|
||||
GVAR(deafnessDV) = (GVAR(deafnessDV) - (0.5 * (GVAR(volume) max 0.1))) max 0;
|
||||
};
|
||||
|
||||
if ((missionNameSpace getVariable [QGVAR(disableVolumeUpdate), false]) || {!GVAR(enableCombatDeafness)}) exitWith {};
|
||||
if (missionNameSpace getVariable [QGVAR(disableVolumeUpdate), false]) exitWith {};
|
||||
|
||||
private _volume = GVAR(volume);
|
||||
|
||||
// Earplugs reduce hearing 50%
|
||||
if ([ACE_player] call FUNC(hasEarPlugsIn)) then {
|
||||
_volume = _volume min GVAR(EarplugsVolume);
|
||||
};
|
||||
|
||||
// Headgear can reduce hearing
|
||||
if(headgear ACE_player != "") then {
|
||||
private ["_lowerVolume"];
|
||||
_lowerVolume = (getNumber (configFile >> "CfgWeapons" >> (headgear ACE_player) >> QGVAR(lowerVolume))) min 1;
|
||||
if(_lowerVolume > 0) then {
|
||||
_volume = _volume min (1 - _lowerVolume);
|
||||
};
|
||||
};
|
||||
// Earplugs and headgear can attenuate hearing
|
||||
_volume = _volume min GVAR(volumeAttenuation);
|
||||
|
||||
// Reduce volume if player is unconscious
|
||||
if (ACE_player getVariable ["ACE_isUnconscious", false]) then {
|
||||
|
BIN
addons/hearing/sounds/deafness_noring.ogg
Normal file
BIN
addons/hearing/sounds/deafness_noring.ogg
Normal file
Binary file not shown.
@ -97,7 +97,7 @@
|
||||
<Hungarian>Nincs több hely</Hungarian>
|
||||
<Russian>Нет места в инвентаре</Russian>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Hearing_DisableEarRinging">
|
||||
<Key ID="STR_ACE_Hearing_DisableEarRinging_DisplayName">
|
||||
<English>Disable ear ringing</English>
|
||||
<French>Désactiver le bourdonnement</French>
|
||||
<Spanish>Desactivar zumbido de oídos</Spanish>
|
||||
@ -109,6 +109,9 @@
|
||||
<Italian>Disabilita i fischi nelle orecchie</Italian>
|
||||
<Portuguese>Desabilitar zumbido de ouvidos</Portuguese>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Hearing_DisableEarRinging_Description">
|
||||
<English>Remove tinnitus effect when the player takes hearing damage</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Hearing_Module_DisplayName">
|
||||
<English>Hearing</English>
|
||||
<Polish>Słuch</Polish>
|
||||
@ -121,10 +124,10 @@
|
||||
<Russian>Слух</Russian>
|
||||
<Italian>Udito</Italian>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Hearing_CombatDeafness_DisplayName">
|
||||
<English>Combat Deafness</English>
|
||||
<Key ID="STR_ACE_Hearing_EnableCombatDeafness_DisplayName">
|
||||
<English>Enable Combat Deafness</English>
|
||||
<Polish>Wł. głuchotę bojową</Polish>
|
||||
<Spanish>¿Habilitar sordera de combate?</Spanish>
|
||||
<Spanish>Habilitar sordera de combate</Spanish>
|
||||
<German>Aktiviere Taubheit im Gefecht?</German>
|
||||
<Czech>Povolit ztrátu sluchu?</Czech>
|
||||
<Portuguese>Ativar surdez em combate?</Portuguese>
|
||||
@ -133,7 +136,7 @@
|
||||
<Russian>Оглушение</Russian>
|
||||
<Italian>Sordità in combattimento</Italian>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Hearing_CombatDeafness_Description">
|
||||
<Key ID="STR_ACE_Hearing_EnableCombatDeafness_Description">
|
||||
<English>Reduces the hearing ability as the player takes hearing damage</English>
|
||||
<Polish>Możliwość chwilowej utraty słuchu przy głośnych wystrzałach i jednoczesnym braku włożonych stoperów</Polish>
|
||||
<Spanish>Habilita la sordera de combate</Spanish>
|
||||
|
Loading…
Reference in New Issue
Block a user