diff --git a/.editorconfig b/.editorconfig index f6f23b8d1b..0deca3d2ab 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,7 +1,7 @@ root = true [*] -end_of_line = lf +end_of_line = crlf insert_final_newline = true charset = utf-8 indent_style = space diff --git a/addons/captives/CfgEventHandlers.hpp b/addons/captives/CfgEventHandlers.hpp index 722750f915..0ce09280a7 100644 --- a/addons/captives/CfgEventHandlers.hpp +++ b/addons/captives/CfgEventHandlers.hpp @@ -9,7 +9,6 @@ class Extended_PostInit_EventHandlers { init = QUOTE(call COMPILE_FILE(XEH_postInit)); }; }; - //release escorted captive when entering a vehicle class Extended_GetIn_EventHandlers { class All { @@ -18,7 +17,6 @@ class Extended_GetIn_EventHandlers { }; }; }; - //reset captive animation after leaving vehicle class Extended_GetOut_EventHandlers { class All { @@ -27,7 +25,6 @@ class Extended_GetOut_EventHandlers { }; }; }; - //reset captivity and escorting status when getting killed class Extended_Killed_EventHandlers { class CAManBase { @@ -36,7 +33,6 @@ class Extended_Killed_EventHandlers { }; }; }; - //mission start class Extended_InitPost_EventHandlers { class CAManBase { @@ -45,4 +41,3 @@ class Extended_InitPost_EventHandlers { }; }; }; - diff --git a/addons/captives/CfgMoves.hpp b/addons/captives/CfgMoves.hpp index 6e67f3615b..d60fab5a33 100644 --- a/addons/captives/CfgMoves.hpp +++ b/addons/captives/CfgMoves.hpp @@ -72,7 +72,7 @@ class CfgMovesMaleSdr: CfgMovesBasic { InterpolateTo[] = {"Unconscious",0.01}; }; class ACE_AmovPercMstpSsurWnonDnon_AmovPercMstpSnonWnonDnon: ACE_AmovPercMstpSnonWnonDnon_AmovPercMstpSsurWnonDnon { - speed = 0.333; //for gameplay reasons, slow this down + speed = 0.5; //for gameplay reasons, slow this down actions = "CivilStandActions"; file = "\A3\anims_f\Data\Anim\Sdr\mov\erc\stp\sur\non\AmovPercMstpSsurWnonDnon_AmovPercMstpSnonWnonDnon"; ConnectTo[] = {"AmovPercMstpSnonWnonDnon",0.1}; diff --git a/addons/captives/CfgVehicles.hpp b/addons/captives/CfgVehicles.hpp index 57f9644a4a..3e4147eee1 100644 --- a/addons/captives/CfgVehicles.hpp +++ b/addons/captives/CfgVehicles.hpp @@ -90,7 +90,7 @@ class CfgVehicles { class ACE_StartSurrenderingSelf { displayName = "$STR_ACE_Captives_StartSurrendering"; condition = QUOTE([ARR_2(_player, true)] call FUNC(canSurrender)); - statement = QUOTE([ARR_2(_player, true)] call FUNC(surrender)); + statement = QUOTE([ARR_2(_player, true)] call FUNC(setSurrendered)); exceptions[] = {}; showDisabled = 0; priority = 0; @@ -98,7 +98,7 @@ class CfgVehicles { class ACE_StopSurrenderingSelf { displayName = "$STR_ACE_Captives_StopSurrendering"; condition = QUOTE([ARR_2(_player, false)] call FUNC(canSurrender)); - statement = QUOTE([ARR_2(_player, false)] call FUNC(surrender)); + statement = QUOTE([ARR_2(_player, false)] call FUNC(setSurrendered)); exceptions[] = {QGVAR(isNotSurrendering)}; showDisabled = 0; priority = 0; diff --git a/addons/captives/XEH_postInit.sqf b/addons/captives/XEH_postInit.sqf index 9d1a242d4d..ac86d71915 100644 --- a/addons/captives/XEH_postInit.sqf +++ b/addons/captives/XEH_postInit.sqf @@ -1,12 +1,9 @@ #include "script_component.hpp" -["playerChanged", {_this call FUNC(handlePlayerChanged)}] call EFUNC(common,addEventhandler); -["MoveInCaptive", {_this call FUNC(vehicleCaptiveMoveIn)}] call EFUNC(common,addEventHandler); -["MoveOutCaptive", {_this call FUNC(vehicleCaptiveMoveOut)}] call EFUNC(common,addEventHandler); -["SetHandcuffed", {_this call FUNC(setHandcuffed)}] call EFUNC(common,addEventHandler); //Handles when someone starts escorting and then disconnects, leaving the captive attached //This is normaly handled by the PFEH in doEscortCaptive, but that won't be running if they DC + if (isServer) then { addMissionEventHandler ["HandleDisconnect", { PARAMS_1(_disconnectedPlayer); @@ -21,6 +18,15 @@ if (isServer) then { }]; }; +["playerVehicleChanged", {_this call FUNC(handleVehicleChanged)}] call EFUNC(common,addEventHandler); +["zeusDisplayChanged", {_this call FUNC(handleZeusDisplayChanged)}] call EFUNC(common,addEventHandler); +["playerChanged", {_this call FUNC(handlePlayerChanged)}] call EFUNC(common,addEventhandler); +["MoveInCaptive", {_this call FUNC(vehicleCaptiveMoveIn)}] call EFUNC(common,addEventHandler); +["MoveOutCaptive", {_this call FUNC(vehicleCaptiveMoveOut)}] call EFUNC(common,addEventHandler); + +["SetHandcuffed", {_this call FUNC(setHandcuffed)}] call EFUNC(common,addEventHandler); +["SetSurrendered", {_this call FUNC(setSurrendered)}] call EFUNC(common,addEventHandler); + //TODO: Medical Integration Events??? // [_unit, "knockedOut", { diff --git a/addons/captives/XEH_preInit.sqf b/addons/captives/XEH_preInit.sqf index 75ee77e9bc..34c9bca910 100644 --- a/addons/captives/XEH_preInit.sqf +++ b/addons/captives/XEH_preInit.sqf @@ -23,9 +23,10 @@ PREP(handleKnockedOut); PREP(handlePlayerChanged); PREP(handleUnitInitPost); PREP(handleWokeUp); +PREP(handleZeusDisplayChanged); PREP(moduleSurrender); PREP(setHandcuffed); -PREP(surrender); +PREP(setSurrendered); PREP(vehicleCaptiveMoveIn); PREP(vehicleCaptiveMoveOut); diff --git a/addons/captives/functions/fnc_canSurrender.sqf b/addons/captives/functions/fnc_canSurrender.sqf index 238087c62b..3ee687cfc1 100644 --- a/addons/captives/functions/fnc_canSurrender.sqf +++ b/addons/captives/functions/fnc_canSurrender.sqf @@ -18,5 +18,12 @@ PARAMS_2(_unit,_newSurrenderState); -//TODO: any other conditions?? -(!((_unit getVariable [QGVAR(isSurrendering), false]) isEqualTo _newSurrenderState)) +private "_returnValue"; + +_returnValue = if (_newSurrenderState) then { + !(_unit getVariable [QGVAR(isSurrendering), false]); //Not currently surrendering +} else { + (_unit getVariable [QGVAR(isSurrendering), false]); //is Surrendering +}; + +_returnValue diff --git a/addons/captives/functions/fnc_handleGetIn.sqf b/addons/captives/functions/fnc_handleGetIn.sqf index 54133e2362..cf7d2c7271 100644 --- a/addons/captives/functions/fnc_handleGetIn.sqf +++ b/addons/captives/functions/fnc_handleGetIn.sqf @@ -19,6 +19,12 @@ PARAMS_3(_vehicle,_dontcare,_unit); -if ((local _unit) && (_unit getVariable [QGVAR(isEscorting), false])) then { - _unit setVariable [QGVAR(isEscorting), false, true]; +if (local _unit) then { + if (_unit getVariable [QGVAR(isEscorting), false]) then { + _unit setVariable [QGVAR(isEscorting), false, true]; + }; + + if (_unit getVariable [QGVAR(isSurrendering), false]) then { + [_unit, false] call FUNC(setSurrender); + }; }; diff --git a/addons/captives/functions/fnc_handleKnockedOut.sqf b/addons/captives/functions/fnc_handleKnockedOut.sqf index 3257d544ca..1cd969807d 100644 --- a/addons/captives/functions/fnc_handleKnockedOut.sqf +++ b/addons/captives/functions/fnc_handleKnockedOut.sqf @@ -1,2 +1,25 @@ -// by commy2 +/* + * Author: commy2, PabstMirror + * Handles when a unit gets knocked out. Ends surrendering. + * + * Arguments: + * 0: Unit + * + * Return Value: + * Nothing + * + * Example: + * [bob, true] call ACE_captives_fnc_handleKnockedOut + * + * Public: No + */ +#include "script_component.hpp" + +//ToDo: Waiting on medical integration + +PARAMS_1(_unit); + +if (_unit getVariable [QGVAR(isSurrendering), false]) then { //If surrendering, stop + [_unit, false] call FUNC(setSurrendered); +}; diff --git a/addons/captives/functions/fnc_handlePlayerChanged.sqf b/addons/captives/functions/fnc_handlePlayerChanged.sqf index 13e284ef80..21fd1e1ec3 100644 --- a/addons/captives/functions/fnc_handlePlayerChanged.sqf +++ b/addons/captives/functions/fnc_handlePlayerChanged.sqf @@ -18,10 +18,16 @@ PARAMS_2(_newUnit,_oldUnit); +//set showHUD based on new unit status: if ((_newUnit getVariable [QGVAR(isHandcuffed), false]) || {_newUnit getVariable [QGVAR(isSurrendering), false]}) then { TRACE_1("Player Change (showHUD false)",_newUnit); - showHUD false; + showHUD false; } else { TRACE_1("Player Change (showHUD true)",_newUnit); showHUD true; }; + +//If old player was escorting, stop +if (_oldUnit getVariable [QGVAR(isEscorting), false]) then { + _oldUnit setVariable [QGVAR(isEscorting), false, true]; +}; diff --git a/addons/captives/functions/fnc_handleUnitInitPost.sqf b/addons/captives/functions/fnc_handleUnitInitPost.sqf index 1a5a8f2ecd..a8b601300a 100644 --- a/addons/captives/functions/fnc_handleUnitInitPost.sqf +++ b/addons/captives/functions/fnc_handleUnitInitPost.sqf @@ -29,6 +29,6 @@ if (local _unit) then { if (_unit getVariable [QGVAR(isSurrendering), false]) then { _unit setVariable [QGVAR(isSurrendering), false]; - [_unit, true] call FUNC(surrender); + [_unit, true] call FUNC(setSurrendered); }; }; diff --git a/addons/captives/functions/fnc_handleZeusDisplayChanged.sqf b/addons/captives/functions/fnc_handleZeusDisplayChanged.sqf new file mode 100644 index 0000000000..84b90e78c2 --- /dev/null +++ b/addons/captives/functions/fnc_handleZeusDisplayChanged.sqf @@ -0,0 +1,31 @@ +/* + * Author: PabstMirror + * Handles ZeusDisplayChanged event + * Need to reset showHUD after closing zeus + * + * Arguments: + * 0: Unit + * 1: Display is now open + * + * Return Value: + * Nothing + * + * Example: + * [bob1, false] call ACE_captives_fnc_handleZeusDisplayChanged + * + * Public: No + */ +#include "script_component.hpp" + +PARAMS_2(_unit,_zeusIsOpen); + +//set showHUD based on unit status: +if (!_zeusIsOpen) then { + if ((_unit getVariable [QGVAR(isHandcuffed), false]) || {_unit getVariable [QGVAR(isSurrendering), false]}) then { + TRACE_1("Player Change (showHUD false)",_unit); + showHUD false; + } else { + TRACE_1("Player Change (showHUD true)",_unit); + showHUD true; + }; +}; diff --git a/addons/captives/functions/fnc_moduleSurrender.sqf b/addons/captives/functions/fnc_moduleSurrender.sqf index 5cbf43aacc..1a335131a8 100644 --- a/addons/captives/functions/fnc_moduleSurrender.sqf +++ b/addons/captives/functions/fnc_moduleSurrender.sqf @@ -27,19 +27,31 @@ if (local _logic) then { if ((count _bisMouseOver) == 2) then {//check what mouse was over before the module was placed _mouseOverObject = _bisMouseOver select 1; if ((_mouseOverObject isKindOf "CAManBase") && {(vehicle _mouseOverObject) == _mouseOverObject}) then { - systemChat format ["Debug - module surrendering %1", (name _mouseOverObject)]; - [_mouseOverObject, true] call FUNC(surrender); + TRACE_2("Debug - module surrendering %1",_mouseOverObject,(name _mouseOverObject)); + if (alive _mouseOverObject) then { + if (!(_mouseOverObject getVariable [QGVAR(isSurrendering), false])) then { + ["SetSurrendered", [_mouseOverObject], [_mouseOverObject, true]] call EFUNC(common,targetEvent); + } else { + ["SetSurrendered", [_mouseOverObject], [_mouseOverObject, false]] call EFUNC(common,targetEvent); + }; + } else { + ["STR_ACE_Captives_Zeus_OnlyAlive"] call EFUNC(common,displayTextStructured); + }; } else { - systemChat format ["Only use on dismounted inf"]; + ["STR_ACE_Captives_Zeus_OnlyInfentry"] call EFUNC(common,displayTextStructured); }; } else { - systemChat format ["Nothing under mouse"]; + ["STR_ACE_Captives_Zeus_NothingSelected"] call EFUNC(common,displayTextStructured); }; - } else {//an editor module - { - systemChat format ["Debug - module surrendering %1", (name _x)]; - [_x, true] call FUNC(surrender); - } forEach _units; + } else { + //an editor module + //Modules run before postInit can instal the event handler, so we need to wait a little bit + [{ + PARAMS_1(_units); + { + ["SetSurrendered", [_x], [_x, true]] call EFUNC(common,targetEvent); + } forEach _units; + }, [_units], 0.05, 0.05]call EFUNC(common,waitAndExecute); }; deleteVehicle _logic; diff --git a/addons/captives/functions/fnc_setHandcuffed.sqf b/addons/captives/functions/fnc_setHandcuffed.sqf index 912b00662f..0deb68dc8b 100644 --- a/addons/captives/functions/fnc_setHandcuffed.sqf +++ b/addons/captives/functions/fnc_setHandcuffed.sqf @@ -18,19 +18,23 @@ PARAMS_2(_unit,_state); -// We only want this function to work on local machines -if (!local _unit) exitwith { - [_this, QUOTE(FUNC(setHandcuffed)), _unit] call EFUNC(common,execRemoteFnc); - TRACE_2("running setHandcuffed on remote unit",_unit,_state); -}; -if (_state isEqualTo (_unit getVariable [QGVAR(isHandcuffed), false])) then { - LOG("setHandcuffed: current state same as new"); +if (!local _unit) exitwith { + ERROR("running setHandcuffed on remote unit"); +}; +if ((_unit getVariable [QGVAR(isHandcuffed), false]) isEqualTo _state) exitWith { + ERROR("setHandcuffed: current state same as new"); }; if (_state) then { _unit setVariable [QGVAR(isHandcuffed), true, true]; [_unit, QGVAR(Handcuffed), true] call EFUNC(common,setCaptivityStatus); + + if (_unit getVariable [QGVAR(isSurrendering), false]) then { //If surrendering, stop + [_unit, false] call FUNC(setSurrendered); + }; + + //Set unit cargoIndex (will be -1 if dismounted) _unit setVariable [QGVAR(CargoIndex), ((vehicle _unit) getCargoIndex _unit), true]; if (_unit == ACE_player) then { @@ -43,11 +47,30 @@ if (_state) then { if (_unit getVariable [QGVAR(isHandcuffed), false] && {vehicle _unit == _unit}) then { [_unit] call EFUNC(common,fixLoweredRifleAnimation); [_unit, "ACE_AmovPercMstpScapWnonDnon", 1] call EFUNC(common,doAnimation); + + //Adds an animation changed eh + //If we get a change in animation then redo the animation (handles people vaulting to break the animation chain) + _animChangedEHID = _unit addEventHandler ["AnimChanged", { + PARAMS_2(_unit,_newAnimation); + if ((_newAnimation != "ACE_AmovPercMstpSsurWnonDnon") && (_newAnimation != "Unconscious")) then { + ERROR("Handcuff animation interrupted"); + systemChat format ["debug %2: new %1", _newAnimation, time]; + [_unit, "ACE_AmovPercMstpScapWnonDnon", 1] call EFUNC(common,doAnimation); + }; + }]; + _unit setVariable [QGVAR(handcuffAnimEHID), _animChangedEHID]; + }; }, [_unit], 0.01, 0] call EFUNC(common,waitAndExecute); } else { _unit setVariable [QGVAR(isHandcuffed), false, true]; [_unit, QGVAR(Handcuffed), false] call EFUNC(common,setCaptivityStatus); + + //remove AnimChanged EH + _animChangedEHID = _unit getVariable [QGVAR(handcuffAnimEHID), -1]; + _unit removeEventHandler ["AnimChanged", _animChangedEHID]; + _unit setVariable [QGVAR(handcuffAnimEHID), -1]; + if ((vehicle _unit) == _unit) then { //Break out of hands up animation loop (doAnimation handles Unconscious prioity) [_unit, "ACE_AmovPercMstpScapWnonDnon_AmovPercMstpSnonWnonDnon", 2] call EFUNC(common,doAnimation); diff --git a/addons/captives/functions/fnc_setSurrendered.sqf b/addons/captives/functions/fnc_setSurrendered.sqf new file mode 100644 index 0000000000..e49c6e9453 --- /dev/null +++ b/addons/captives/functions/fnc_setSurrendered.sqf @@ -0,0 +1,101 @@ +/* + * Author: commy2 PabstMirror + * Lets a unit surrender + * + * Arguments: + * 0: Unit + * 1: True to surrender, false to un-surrender + * + * Return Value: + * Nothing + * + * Example: + * [Pierre, true] call ACE_captives_fnc_setSurrendered; + * + * Public: No + */ +#include "script_component.hpp" + +PARAMS_2(_unit,_state); + + +if (!local _unit) exitwith { + ERROR("running surrender on remote unit"); +}; + +if ((_unit getVariable [QGVAR(isSurrendering), false]) isEqualTo _state) exitWith { + ERROR("Surrender: current state same as new"); +}; + +if (_state) then { + if ((vehicle _unit) != _unit) exitWith {ERROR("Cannot surrender while mounted");}; + if (_unit getVariable [QGVAR(isHandcuffed), false]) exitWith {ERROR("Cannot surrender while handcuffed");}; + + _unit setVariable [QGVAR(isSurrendering), true, true]; + + [_unit, QGVAR(Surrendered), true] call EFUNC(common,setCaptivityStatus); + + if (_unit == ACE_player) then { + showHUD false; + }; + + [_unit] call EFUNC(common,fixLoweredRifleAnimation); + [_unit, "ACE_AmovPercMstpSsurWnonDnon", 1] call EFUNC(common,doAnimation); + + // fix anim on mission start (should work on dedicated servers) + [{ + PARAMS_1(_unit); + if (_unit getVariable [QGVAR(isSurrendering), false] && {(vehicle _unit) == _unit}) then { + //Adds an animation changed eh + //If we get a change in animation then redo the animation (handles people vaulting to break the animation chain) + _animChangedEHID = _unit addEventHandler ["AnimChanged", { + PARAMS_2(_unit,_newAnimation); + if ((_newAnimation != "ACE_AmovPercMstpSsurWnonDnon") && (_newAnimation != "Unconscious")) then { + ERROR("Surrender animation interrupted"); + systemChat format ["debug %2: new %1", _newAnimation, time]; + [_unit, "ACE_AmovPercMstpSsurWnonDnon", 1] call EFUNC(common,doAnimation); + }; + }]; + _unit setVariable [QGVAR(surrenderAnimEHID), _animChangedEHID]; + }; + }, [_unit], 0.01, 0] call EFUNC(common,waitAndExecute); +} else { + _unit setVariable [QGVAR(isSurrendering), false, true]; + [_unit, QGVAR(Surrendered), false] call EFUNC(common,setCaptivityStatus); + + //remove AnimChanged EH + _animChangedEHID = _unit getVariable [QGVAR(surrenderAnimEHID), -1]; + _unit removeEventHandler ["AnimChanged", _animChangedEHID]; + _unit setVariable [QGVAR(surrenderAnimEHID), -1]; + + if (_unit == ACE_player) then { + //only re-enable HUD if not handcuffed + if (!(_unit getVariable [QGVAR(isHandcuffed), false])) then { + showHUD true; + }; + }; + + if (_unit getVariable ["ACE_isUnconscious", false]) exitWith {}; //don't touch animations if unconscious + + //if we are in "hands up" animationState, crack it now + if (((vehicle _unit) == _unit) && {(animationState _unit) == "ACE_AmovPercMstpSsurWnonDnon"}) then { + [_unit, "ACE_AmovPercMstpSsurWnonDnon_AmovPercMstpSnonWnonDnon", 2] call EFUNC(common,doAnimation); + } else { + //spin up a PFEH, to watching animationState for the next 20 seconds to make sure we don't enter "hands up" + //Handles long animation chains + [{ + PARAMS_2(_args,_pfID); + EXPLODE_2_PVT(_args,_unit,_maxTime); + //If waited long enough or they re-surrendered or they are unconscious, exit loop + if ((time > _maxTime) || {_unit getVariable [QGVAR(isSurrendering), false]} || {_unit getVariable ["ACE_isUnconscious", false]}) exitWith { + [_pfID] call CBA_fnc_removePerFrameHandler; + }; + //Only break animation if they are actualy the "hands up" animation (because we are using switchmove there won't be an transition) + if (((vehicle _unit) == _unit) && {(animationState _unit) == "ACE_AmovPercMstpSsurWnonDnon"}) exitWith { + [_pfID] call CBA_fnc_removePerFrameHandler; + //Break out of hands up animation loop + [_unit, "ACE_AmovPercMstpSsurWnonDnon_AmovPercMstpSnonWnonDnon", 2] call EFUNC(common,doAnimation); + }; + }, 0, [_unit, (time + 20)]] call CBA_fnc_addPerFrameHandler; + }; +}; diff --git a/addons/captives/functions/fnc_surrender.sqf b/addons/captives/functions/fnc_surrender.sqf deleted file mode 100644 index 1f0e232926..0000000000 --- a/addons/captives/functions/fnc_surrender.sqf +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Author: commy2 PabstMirror - * Lets a unit surrender - * - * Arguments: - * 0: Unit - * 1: State - * - * Return Value: - * Nothing - * - * Example: - * [Pierre, true] call ACE_captives_fnc_surrender; - * - * Public: No - */ -#include "script_component.hpp" - -PARAMS_2(_unit,_state); - -// We only want this function to work on local machines -if (!local _unit) exitwith { - [_this, QUOTE(FUNC(surrender)), _unit] call EFUNC(common,execRemoteFnc); - TRACE_2("running surrender on remote unit",_unit,_state); -}; - -if ((_unit getVariable [QGVAR(isSurrendering), false]) isEqualTo _state) then { - LOG("Surrender: current state same as new"); -}; - -if (_state) then { - _unit setVariable [QGVAR(isSurrendering), true, true]; - [_unit, QGVAR(Surrendered), true] call EFUNC(common,setCaptivityStatus); - - if (_unit == ACE_player) then { - showHUD false; - }; - - // fix anim on mission start (should work on dedicated servers) - [{ - PARAMS_1(_unit); - if (_unit getVariable [QGVAR(isSurrendering), false] && {vehicle _unit == _unit}) then { - [_unit] call EFUNC(common,fixLoweredRifleAnimation); - [_unit, "ACE_AmovPercMstpSsurWnonDnon", 1] call EFUNC(common,doAnimation); - }; - }, [_unit], 0.01, 0] call EFUNC(common,waitAndExecute); - - //PFEH - (TODO: move to event system?) - [{ - EXPLODE_1_PVT((_this select 0),_unit); - if (_unit getVariable [QGVAR(isSurrendering), false]) then { - //If unit dies, gets knocked out, or is handcuffed then end surrender - if ((!alive _unit) || {_unit getVariable ["ACE_isUnconscious", false]} || {_unit getVariable [QGVAR(isHandcuffed), false]}) then { - [_unit, false] call FUNC(surrender); - [(_this select 1)] call CBA_fnc_removePerFrameHandler; - }; - } else { - [(_this select 1)] call cba_fnc_removePerFrameHandler; - }; - }, 0.0, [_unit]] call CBA_fnc_addPerFrameHandler; -} else { - _unit setVariable [QGVAR(isSurrendering), false, true]; - [_unit, QGVAR(Surrendered), false] call EFUNC(common,setCaptivityStatus); - - if ((vehicle _unit) == _unit) then { - //Break out of hands up animation loop (doAnimation handles Unconscious prioity) - [_unit, "ACE_AmovPercMstpSsurWnonDnon_AmovPercMstpSnonWnonDnon", 2] call EFUNC(common,doAnimation); - }; - - if (_unit == ACE_player) then { - //only re-enable HUD if not handcuffed - if (!(_unit getVariable [QGVAR(isHandcuffed), false])) then { - showHUD true; - }; - }; -}; diff --git a/addons/captives/stringtable.xml b/addons/captives/stringtable.xml index 7d8096b3e6..f03f30a113 100644 --- a/addons/captives/stringtable.xml +++ b/addons/captives/stringtable.xml @@ -1,5 +1,5 @@  - + @@ -136,5 +136,14 @@ Stop Surrendering + + Only use on alive units + + + Only use on dismounted inf + + + Nothing under mouse + \ No newline at end of file diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf index dbb665d446..35b0f5c3fe 100644 --- a/addons/common/XEH_postInit.sqf +++ b/addons/common/XEH_postInit.sqf @@ -158,3 +158,6 @@ GVAR(OldPlayerTurret) = [ACE_player] call FUNC(getTurretIndex); PARAMS_2(_vehicle,_fuelLevel); _vehicle setFuel _fuelLevel; }] call FUNC(addEventhandler); + +["displayTextStructured", FUNC(displayTextStructured)] call FUNC(addEventhandler); +["displayTextPicture", FUNC(displayTextPicture)] call FUNC(addEventhandler); diff --git a/addons/common/functions/fnc_displayTextPicture.sqf b/addons/common/functions/fnc_displayTextPicture.sqf index 8472b3d1b6..fadf28b480 100644 --- a/addons/common/functions/fnc_displayTextPicture.sqf +++ b/addons/common/functions/fnc_displayTextPicture.sqf @@ -7,6 +7,7 @@ * 0: Text * 1: Image * 2: Image color + * 3: Target Unit. Will only display if target is the player controlled object * * Return value: * Nothing @@ -14,17 +15,30 @@ #include "script_component.hpp" -private ["_text", "_image", "_imageColor"]; +private ["_text", "_image", "_imageColor", "_target"]; _text = _this select 0; _image = _this select 1; _imageColor = if (count _this > 2) then {_this select 2} else {[1,1,1]}; _imageColor resize 3; +_target = if (count _this > 3) then {_this select 3} else {ACE_player}; + +if (_target != ACE_player) exitWith {}; if (typeName _text != "TEXT") then { - if (typeName _text == "STRING" && {isLocalized _text}) then { + if (typeName _text == "ARRAY") then { + if (count _text > 0) then { + { + if (typeName _x == "STRING" && {isLocalized _x}) then { + _text set [_foreachIndex, localize _x]; + }; + }foreach _text; + _text = format _text; + }; + }; + if (typeName _text == "STRING" && {isLocalized _text}) then { _text = localize _text; }; - _text = parseText format ["%1", _text]; + _text = parseText format ["%1", _text]; }; _text = composeText [parseText format ["", _image, _imageColor call BIS_fnc_colorRGBtoHTML], lineBreak, _text]; [_text, 2] call FUNC(displayTextStructured); diff --git a/addons/common/functions/fnc_displayTextStructured.sqf b/addons/common/functions/fnc_displayTextStructured.sqf index 054e98de70..cfe2feb3cb 100644 --- a/addons/common/functions/fnc_displayTextStructured.sqf +++ b/addons/common/functions/fnc_displayTextStructured.sqf @@ -6,6 +6,7 @@ * Argument: * 0: Text * 1: Size of the textbox + * 2: Target Unit. Will only display if target is the player controlled object * * Return value: * Nothing @@ -13,14 +14,24 @@ #include "script_component.hpp" -private ["_text", "_size", "_isShown", "_ctrlHint", "_yPos", "_xPos", "_wPos", "_hPos", "_position"]; - +private ["_text", "_size", "_isShown", "_ctrlHint", "_yPos", "_xPos", "_wPos", "_hPos", "_position", "_target"]; _text = _this select 0; -_size = _this select 1; +_size = if (count _this > 1) then {_this select 1} else {1.5;}; +_target = if (count _this > 2) then {_this select 2} else {ACE_player}; -if (isNil "_size") then {_size = 1.5}; +if (_target != ACE_player) exitWith {}; if (typeName _text != "TEXT") then { + if (typeName _text == "ARRAY") then { + if (count _text > 0) then { + { + if (typeName _x == "STRING" && {isLocalized _x}) then { + _text set [_foreachIndex, localize _x]; + }; + }foreach _text; + _text = format _text; + }; + }; if (typeName _text == "STRING" && {isLocalized _text}) then { _text = localize _text; }; @@ -48,6 +59,12 @@ _xPos = ((safezoneX + safezoneW) - (10 *(((safezoneW / safezoneH) min 1.2) / 40) _yPos = safeZoneY + 0.175 * safezoneH; _wPos = (10 *(((safezoneW / safezoneH) min 1.2) / 40)); _hPos = (2 *((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)); + +//Zeus Interface Open and Display would be under the "CREATE" list +if (!isnull curatorCamera) then { + _xPos = _xPos min ((safezoneX + safezoneW - 12.5 * (((safezoneW / safezoneH) min 1.2) / 40)) - _wPos); +}; + _position = [_xPos, _yPos, _wPos, _size * _hPos]; _ctrlHint ctrlSetPosition _position; diff --git a/addons/nametags/CfgVehicles.hpp b/addons/nametags/CfgVehicles.hpp index e3c4227834..d61c761bfc 100644 --- a/addons/nametags/CfgVehicles.hpp +++ b/addons/nametags/CfgVehicles.hpp @@ -55,6 +55,15 @@ class CfgVehicles { }; }; }; + class showCursorTagForVehicles { + displayName = "Show for Vehicles"; + description = "Show cursor NameTag for vehicle commander (only if client has name tags enabled)Default: No"; + typeName = "BOOL"; + class values { + class Yes {name = "Yes"; value = 1;}; + class No {default = 1; name = "No"; value = 0;}; + }; + }; }; }; }; diff --git a/addons/nametags/UI/soundwave0.paa b/addons/nametags/UI/soundwave0.paa new file mode 100644 index 0000000000..27f34b38ab Binary files /dev/null and b/addons/nametags/UI/soundwave0.paa differ diff --git a/addons/nametags/UI/soundwave1.paa b/addons/nametags/UI/soundwave1.paa new file mode 100644 index 0000000000..ce4f85eb69 Binary files /dev/null and b/addons/nametags/UI/soundwave1.paa differ diff --git a/addons/nametags/UI/soundwave2.paa b/addons/nametags/UI/soundwave2.paa new file mode 100644 index 0000000000..0bc59cde24 Binary files /dev/null and b/addons/nametags/UI/soundwave2.paa differ diff --git a/addons/nametags/UI/soundwave3.paa b/addons/nametags/UI/soundwave3.paa new file mode 100644 index 0000000000..39f3e8e95b Binary files /dev/null and b/addons/nametags/UI/soundwave3.paa differ diff --git a/addons/nametags/UI/soundwave4.paa b/addons/nametags/UI/soundwave4.paa new file mode 100644 index 0000000000..7ab8b6d944 Binary files /dev/null and b/addons/nametags/UI/soundwave4.paa differ diff --git a/addons/nametags/UI/soundwave5.paa b/addons/nametags/UI/soundwave5.paa new file mode 100644 index 0000000000..f3e98d47aa Binary files /dev/null and b/addons/nametags/UI/soundwave5.paa differ diff --git a/addons/nametags/UI/soundwave6.paa b/addons/nametags/UI/soundwave6.paa new file mode 100644 index 0000000000..3f29976c9f Binary files /dev/null and b/addons/nametags/UI/soundwave6.paa differ diff --git a/addons/nametags/UI/soundwave7.paa b/addons/nametags/UI/soundwave7.paa new file mode 100644 index 0000000000..e705c70b42 Binary files /dev/null and b/addons/nametags/UI/soundwave7.paa differ diff --git a/addons/nametags/UI/soundwave8.paa b/addons/nametags/UI/soundwave8.paa new file mode 100644 index 0000000000..e6027d878a Binary files /dev/null and b/addons/nametags/UI/soundwave8.paa differ diff --git a/addons/nametags/UI/soundwave9.paa b/addons/nametags/UI/soundwave9.paa new file mode 100644 index 0000000000..91ddfd02df Binary files /dev/null and b/addons/nametags/UI/soundwave9.paa differ diff --git a/addons/nametags/XEH_postInit.sqf b/addons/nametags/XEH_postInit.sqf index c73ec08cfe..1ad0e38879 100644 --- a/addons/nametags/XEH_postInit.sqf +++ b/addons/nametags/XEH_postInit.sqf @@ -1,6 +1,8 @@ // by commy2 and CAA-Picard #include "script_component.hpp" +[] call FUNC(initIsSpeaking); + if (!hasInterface) exitWith {}; @@ -25,57 +27,4 @@ if (!hasInterface) exitWith {}; // Draw handle -addMissionEventHandler ["Draw3D", { - if (GVAR(showPlayerNames) == 0) exitWith {}; - - _player = ACE_player; - if (GVAR(showPlayerNames) in [2,4]) then { //only on cursor - _target = cursorTarget; - _target = if (_target in allUnitsUAV) then {objNull} else {effectiveCommander _target}; - - if (!isNull _target && {side group _target == playerSide} && {_target != _player} && {isPlayer _target || {GVAR(ShowNamesForAI)}} && {!(_target getVariable ["ACE_hideName", false])}) then { - _distance = _player distance _target; - _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min 1) * GVAR(PlayerNamesMaxAlpha); - if ((GVAR(showPlayerNames) in [3,4])) then { //only on keypress - _alpha = _alpha min (1 - (time - GVAR(ShowNamesTime) - 1)); - }; - [_player, _target, _alpha, _distance * 0.026] call FUNC(drawNameTagIcon); - }; - } else { - _pos = positionCameraToWorld [0, 0, 0]; - _targets = _pos nearObjects ["Man", GVAR(PlayerNamesViewDistance) + 5]; - - if (!surfaceIsWater _pos) then { - _pos = ATLtoASL _pos; - }; - _pos2 = positionCameraToWorld [0, 0, 1]; - if (!surfaceIsWater _pos2) then { - _pos2 = ATLtoASL _pos2; - }; - _vecy = _pos2 vectorDiff _pos; - - { - _target = if (_x in allUnitsUAV) then {objNull} else {effectiveCommander _x}; - - if (!isNull _target && {side group _target == playerSide} && {_target != _player} && {isPlayer _target || {GVAR(ShowNamesForAI)}} && {!(_target getVariable ["ACE_hideName", false])}) then { - _relPos = (visiblePositionASL _target) vectorDiff _pos; - _distance = vectorMagnitude _relPos; - _projDist = _relPos vectorDistance (_vecy vectorMultiply (_relPos vectorDotProduct _vecy)); - - _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min (1 - 0.15 * (_projDist * 5 - _distance - 3)) min 1) * GVAR(PlayerNamesMaxAlpha); - - if ((GVAR(showPlayerNames) in [3,4])) then { //only on keypress - _alpha = _alpha min (1 - (time - GVAR(ShowNamesTime) - 1)); - }; - - // Check if there is line of sight - if (_alpha > 0) then { - if (lineIntersects [_pos, (visiblePositionASL _target) vectorAdd [0,0,1], vehicle _player, _target]) then { - _alpha = 0; - }; - }; - [_player, _target, _alpha, _distance * 0.026] call FUNC(drawNameTagIcon); - }; - } forEach _targets; - }; -}]; +addMissionEventHandler ["Draw3D", {_this call FUNC(onDraw3d);}]; diff --git a/addons/nametags/XEH_preInit.sqf b/addons/nametags/XEH_preInit.sqf index 79258c5cec..80c06cff1f 100644 --- a/addons/nametags/XEH_preInit.sqf +++ b/addons/nametags/XEH_preInit.sqf @@ -6,7 +6,9 @@ PREP(canShow); PREP(doShow); PREP(drawNameTagIcon); PREP(getVehicleData); +PREP(initIsSpeaking); PREP(moduleNameTags); +PREP(onDraw3d); PREP(onMouseZChanged); PREP(setText); diff --git a/addons/nametags/config.cpp b/addons/nametags/config.cpp index aa55dd2aad..25992c0174 100644 --- a/addons/nametags/config.cpp +++ b/addons/nametags/config.cpp @@ -16,6 +16,12 @@ class CfgPatches { #include "CfgVehicles.hpp" class ACE_Settings { + class GVAR(defaultNametagColor) { + value[] = {0.77, 0.51, 0.08, 1}; + typeName = "COLOR"; + isClientSetable = 1; + displayName = "$STR_ACE_NameTags_DefaultNametagColor"; + }; class GVAR(showPlayerNames) { value = 1; typeName = "SCALAR"; @@ -40,8 +46,19 @@ class ACE_Settings { typeName = "BOOL"; isClientSetable = 1; displayName = "$STR_ACE_NameTags_ShowNamesForAI"; + }; + class GVAR(showCursorTagForVehicles) { + value = 0; + typeName = "BOOL"; + isClientSetable = 0; + }; + class GVAR(showSoundWaves) { + value = 1; + typeName = "SCALAR"; + isClientSetable = 1; + displayName = "$STR_ACE_NameTags_ShowSoundWaves"; + values[] = {"Disabled", "Use Nametag settings", "Always Show All"}; }; - class GVAR(PlayerNamesViewDistance) { value = 5; typeName = "SCALAR"; diff --git a/addons/nametags/functions/fnc_drawNameTagIcon.sqf b/addons/nametags/functions/fnc_drawNameTagIcon.sqf index af3932f118..8ccbfc9b4a 100644 --- a/addons/nametags/functions/fnc_drawNameTagIcon.sqf +++ b/addons/nametags/functions/fnc_drawNameTagIcon.sqf @@ -4,16 +4,18 @@ * Draw the nametag and rank icon. * * Argument: - * 0: Unit (Array) - * 1: alpha (Number) - * 2: Height offset (Number) + * 0: Unit (Player) + * 1: Target + * 2: alpha (Number) + * 4: Height offset (Number) + * 5: Draw Type * * Return value: * None. */ #include "script_component.hpp" - + #define TEXTURES_RANKS [ \ "", \ "\A3\Ui_f\data\GUI\Cfg\Ranks\private_gs.paa", \ @@ -23,41 +25,58 @@ "\A3\Ui_f\data\GUI\Cfg\Ranks\captain_gs.paa", \ "\A3\Ui_f\data\GUI\Cfg\Ranks\major_gs.paa", \ "\A3\Ui_f\data\GUI\Cfg\Ranks\colonel_gs.paa" \ -] + ] -private ["_player", "_target", "_alpha", "_heightOffset", "_height", "_position", "_color", "_name", "_rank", "_size"]; +private ["_height", "_position", "_color", "_name", "_rank", "_size"]; -_player = _this select 0; -_target = _this select 1; -_alpha = _this select 2; -_heightOffset = _this select 3; +PARAMS_5(_player,_target,_alpha,_heightOffset,_iconType); -_height = [2, 1.5, 1, 1.5, 1] select (["STAND", "CROUCH", "PRONE", "UNDEFINED", ""] find stance _target); +if (_alpha < 0) exitWith {}; //Don't waste time if not visable +if (_iconType == ICON_NONE) exitWith {}; //Don't waste time if not visable -_position = visiblePositionASL _target; -// Convert position to ASLW (expected by drawIcon3D) and add height offsets -_position set [2, ((_target modelToWorld [0,0,0]) select 2) + _height + _heightOffset]; -_color = if !(group _target == group _player) then { - [0.77, 0.51, 0.08, _alpha] +//Set Text: +_name = if (_iconType in [ICON_NAME, ICON_NAME_RANK, ICON_NAME_SPEAK]) then { + [_target, true] call EFUNC(common,getName) } else { - [[1, 1, 1, _alpha], [1, 0, 0, _alpha], [0, 1, 0, _alpha], [0, 0, 1, _alpha], [1, 1, 0, _alpha]] select (["MAIN", "RED", "GREEN", "BLUE", "YELLOW"] find (if (_target == _player) then {0} else {assignedTeam _target})) max 0 + "" }; -_name = [_target, true] call EFUNC(common,getName); +//Set Icon: +_icon = ""; +_size = 0; +if ((_iconType == ICON_NAME_SPEAK) || (_iconType == ICON_SPEAK)) then { + _icon = QUOTE(PATHTOF(UI\soundwave)) + str (floor (random 10)) + ".paa"; + _size = 0.75; + _alpha = _alpha + 0.6;//Boost alpha when speaking +} else { + if (_iconType == ICON_NAME_RANK) then { + _icon = TEXTURES_RANKS select ((["PRIVATE", "CORPORAL", "SERGEANT", "LIEUTENANT", "CAPTAIN", "MAJOR", "COLONEL"] find (rank _target)) + 1); + _size = 0.75; + }; +}; -_rank = TEXTURES_RANKS select ((["PRIVATE", "CORPORAL", "SERGEANT", "LIEUTENANT", "CAPTAIN", "MAJOR", "COLONEL"] find rank _target) + 1); -_size = [0, 1] select GVAR(showPlayerRanks); +//Set Color: +if !(group _target == group _player) then { + _color = +GVAR(defaultNametagColor); //Make a copy, then multiply both alpha values (allows client to decrease alpha in settings) + _color set [3, (_color select 3) * _alpha]; +} else { + _color = [[1, 1, 1, _alpha], [1, 0, 0, _alpha], [0, 1, 0, _alpha], [0, 0, 1, _alpha], [1, 1, 0, _alpha]] select (["MAIN", "RED", "GREEN", "BLUE", "YELLOW"] find (if (_target == _player) then {0} else {assignedTeam _target})) max 0 +}; + +_height = [2, 1.5, 1, 1.5, 1] select (["STAND", "CROUCH", "PRONE", "UNDEFINED", ""] find (stance _target)); +// Convert position to ASLW (expected by drawIcon3D) and add height offsets +_position = _target modelToWorldVisual [0, 0, (_height + _heightOffset)]; drawIcon3D [ - _rank, - _color, - _position, - _size, - _size, - 0, - _name, - 2, - 0.033, - "PuristaMedium" +_icon, +_color, +_position, +_size, +_size, +0, +_name, +2, +0.033, +"PuristaMedium" ]; diff --git a/addons/nametags/functions/fnc_initIsSpeaking.sqf b/addons/nametags/functions/fnc_initIsSpeaking.sqf new file mode 100644 index 0000000000..b7dc920fa2 --- /dev/null +++ b/addons/nametags/functions/fnc_initIsSpeaking.sqf @@ -0,0 +1,76 @@ +/* + * Author: Glowbal, PabstMirror + * Starts up a PFEH to monitor the when players are talking. + * Compatiblity with TFR/ACRE and Arma's VON + * + * Arguments: + * NONE + * + * Return Value: + * NONE + * + * Example: + * [] call ACE_nametags_fnc_initIsSpeaking + * + * Public: No + */ +#include "script_component.hpp" + +if (isServer) then { + //If someone disconnects while speaking, reset their variable + addMissionEventHandler ["HandleDisconnect", { + PARAMS_1(_disconnectedPlayer); + if (_disconnectedPlayer getVariable [QGVAR(isSpeaking), false]) then { + _disconnectedPlayer setVariable [QGVAR(isSpeaking), false, true]; + }; + }]; +}; + +if (!hasInterface) exitWith {}; + +["playerChanged", { + //When player changes, make sure to reset old unit's variable + PARAMS_2(_newUnit,_oldUnit); + if (_oldUnit getVariable [QGVAR(isSpeaking), false]) then { + _oldUnit setVariable [QGVAR(isSpeaking), false, true]; + }; +}] call EFUNC(common,addEventHandler); + + +//For performance, chose different code paths at mission start based on installed mods (once, instead of checking each time) +_pfEHCode = switch (true) do { +case (isClass (configFile >> "cfgPatches" >> "acre_api")): { + { + _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; + _newSetting = ([ACE_player] call ACRE_api_fnc_isBroadcasting) || {!(isNull findDisplay 55)}; + if (!(_oldSetting isEqualTo _newSetting)) then { + ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; + }; + }; + }; +case (isClass (configFile >> "cfgPatches" >> "task_force_radio")): { + //Note: TFAR has a TFAR_fnc_isSpeaking function, but it has a fairly costly `callExtension` + //I think it's much faster to use the internal "tf_isSpeaking" variable + //If we don't care about the built-in VON, we could switch this to a pure event driven system + { + _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; + _newSetting = (ACE_player getVariable ["tf_isSpeaking", false]) || {!(isNull findDisplay 55)}; + if (!(_oldSetting isEqualTo _newSetting)) then { + ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; + }; + }; + }; + default { + //Note: class RscDisplayVoiceChat {idd = 55}; //only present when talking + { + _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; + _newSetting = (!(isNull findDisplay 55)); + if (!(_oldSetting isEqualTo _newSetting)) then { + ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; + }; + }; + }; +}; + +//Is 0.05sec precision enough?? +[_pfEHCode, 0.05, []] call CBA_fnc_addPerFrameHandler; diff --git a/addons/nametags/functions/fnc_moduleNameTags.sqf b/addons/nametags/functions/fnc_moduleNameTags.sqf index 24b30e5d6b..a998e5d8a3 100644 --- a/addons/nametags/functions/fnc_moduleNameTags.sqf +++ b/addons/nametags/functions/fnc_moduleNameTags.sqf @@ -25,5 +25,6 @@ GVAR(Module) = true; [_logic, QGVAR(PlayerNamesViewDistance), "PlayerNamesViewDistance" ] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(ShowNamesForAI), "ShowNamesForAI" ] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(showVehicleCrewInfo), "showVehicleCrewInfo" ] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(showCursorTagForVehicles), "showCursorTagForVehicles" ] call EFUNC(common,readSettingFromModule); diag_log text "[ACE]: NameTags Module Initialized."; diff --git a/addons/nametags/functions/fnc_onDraw3d.sqf b/addons/nametags/functions/fnc_onDraw3d.sqf new file mode 100644 index 0000000000..8aa503d377 --- /dev/null +++ b/addons/nametags/functions/fnc_onDraw3d.sqf @@ -0,0 +1,108 @@ +#include "script_component.hpp" + +_player = ACE_player; + +//don't show nametags in spectator +if (!alive _player) exitWith {}; + +_onKeyPressAlphaMax = if ((GVAR(showPlayerNames) in [3,4])) then { + 2 + (GVAR(ShowNamesTime) - time); //after release 1 second of full opacity, 1 second of fading to 0 +} else { + 1 +}; + +_defaultIcon = if (GVAR(showPlayerRanks)) then { + ICON_NAME_RANK; +} else { + ICON_NAME; +}; + +//When cursorTarget is on a vehicle show the nametag for the commander. +//If set to "Only On Keypress" settings, fade just like main tags +if (GVAR(showCursorTagForVehicles) && {_onKeyPressAlphaMax > 0}) then { + _target = cursorTarget; + if ((!(_target isKindOf "CAManBase")) && {!(_target in allUnitsUAV)}) then { + _target = effectiveCommander _target; + if ((!isNull _target) && + {(side (group _target)) == (side (group _player))} && + {_target != _player} && + {GVAR(ShowNamesForAI) || {[_target] call EFUNC(common,isPlayer)}} && + {!(_target getVariable ["ACE_hideName", false])}) then { + _distance = _player distance _target; + _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min 1) * GVAR(PlayerNamesMaxAlpha); + _alpha = _alpha min _onKeyPressAlphaMax; + [_player, _target, _alpha, _distance * 0.026, _defaultIcon] call FUNC(drawNameTagIcon); + }; + }; +}; + +//"Only Cursor" mode, only show nametags for humans on cursorTarget +if ((GVAR(showPlayerNames) in [2,4]) && {_onKeyPressAlphaMax > 0}) then { + _target = cursorTarget; + if ((!isNull _target) && + {_target isKindOf "CAManBase"} && + {(side (group _target)) == (side (group _player))} && + {_target != _player} && + {GVAR(ShowNamesForAI) || {[_target] call EFUNC(common,isPlayer)}} && + {!(_target getVariable ["ACE_hideName", false])}) then { + _distance = _player distance _target; + _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min 1) * GVAR(PlayerNamesMaxAlpha); + _alpha = _alpha min _onKeyPressAlphaMax; + _icon = ICON_NONE; + if (GVAR(showSoundWaves) == 2) then { //icon will be drawn below, so only show name here + _icon = if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}) then {ICON_NAME} else {_defaultIcon}; + } else { + _icon = if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {ICON_NAME_SPEAK} else {_defaultIcon}; + }; + + [_player, _target, _alpha, _distance * 0.026, _icon] call FUNC(drawNameTagIcon); + }; +}; + +if (((GVAR(showPlayerNames) in [1,3]) && {_onKeyPressAlphaMax > 0}) || {GVAR(showSoundWaves) == 2}) then { + _pos = positionCameraToWorld [0, 0, 0]; + _targets = _pos nearObjects ["CAManBase", GVAR(PlayerNamesViewDistance) + 5]; + + if (!surfaceIsWater _pos) then { + _pos = ATLtoASL _pos; + }; + _pos2 = positionCameraToWorld [0, 0, 1]; + if (!surfaceIsWater _pos2) then { + _pos2 = ATLtoASL _pos2; + }; + _vecy = _pos2 vectorDiff _pos; + + { + _target = _x; + + _icon = ICON_NONE; + if ((GVAR(showPlayerNames) in [1,3]) && {_onKeyPressAlphaMax > 0}) then { + if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {_icon = ICON_NAME_SPEAK;} else {_icon = _defaultIcon}; + } else { + //showSoundWaves must be 2, only draw speak icon + if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}) then {_icon = ICON_SPEAK;}; + }; + + if ((_icon != ICON_NONE) && + {(side (group _target)) == (side (group _player))} && + {_target != _player} && + {GVAR(ShowNamesForAI) || {[_target] call EFUNC(common,isPlayer)}} && + {!(_target getVariable ["ACE_hideName", false])}) then { + + if (lineIntersects [_pos, (visiblePositionASL _target) vectorAdd [0,0,1], vehicle _player, _target]) exitWith {}; // Check if there is line of sight + _relPos = (visiblePositionASL _target) vectorDiff _pos; + _distance = vectorMagnitude _relPos; + _projDist = _relPos vectorDistance (_vecy vectorMultiply (_relPos vectorDotProduct _vecy)); + + _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min (1 - 0.15 * (_projDist * 5 - _distance - 3)) min 1) * GVAR(PlayerNamesMaxAlpha); + + if ((GVAR(showSoundWaves) == 2) && {(_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}}) then { + _alpha = 1; + } else { + _alpha = _alpha min _onKeyPressAlphaMax; + }; + + [_player, _target, _alpha, _distance * 0.026, _icon] call FUNC(drawNameTagIcon); + }; + } forEach _targets; +}; diff --git a/addons/nametags/script_component.hpp b/addons/nametags/script_component.hpp index 6cffb95618..e80768a723 100644 --- a/addons/nametags/script_component.hpp +++ b/addons/nametags/script_component.hpp @@ -9,4 +9,10 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_NAMETAGS #endif -#include "\z\ace\addons\main\script_macros.hpp" \ No newline at end of file +#include "\z\ace\addons\main\script_macros.hpp" + +#define ICON_NONE 0 +#define ICON_NAME 1 +#define ICON_NAME_RANK 2 +#define ICON_NAME_SPEAK 3 +#define ICON_SPEAK 4 diff --git a/addons/nametags/stringtable.xml b/addons/nametags/stringtable.xml index 9cd99adaef..622df44aca 100644 --- a/addons/nametags/stringtable.xml +++ b/addons/nametags/stringtable.xml @@ -1,5 +1,5 @@  - + @@ -69,5 +69,13 @@ Show name tags for AI units + + Show SoundWaves (requires player names) + Zeigen Schallwelle (benötigt spielernamen) + Mostrar onda sonora (requiere Mostrar nombres de jugadores) + + + Default Nametag Color (Non Group Members) + - + \ No newline at end of file