From 28c4afdcde8f2d84128c0e343e826a6a9c0c6fc7 Mon Sep 17 00:00:00 2001 From: mharis001 Date: Sat, 1 Oct 2022 02:37:09 -0400 Subject: [PATCH 1/3] Visibility - Add during placement only mode and max distance setting --- .../common/functions/fnc_getPosFromScreen.sqf | 52 +++++++++++------ .../common/functions/fnc_selectPosition.sqf | 8 +-- addons/context_menu/script_component.hpp | 2 +- addons/visibility/XEH_postInit.sqf | 2 +- addons/visibility/functions/fnc_draw.sqf | 57 ++++++++++--------- addons/visibility/initSettings.sqf | 29 ++++++++-- addons/visibility/script_component.hpp | 4 ++ addons/visibility/stringtable.xml | 19 ++++++- 8 files changed, 117 insertions(+), 56 deletions(-) diff --git a/addons/common/functions/fnc_getPosFromScreen.sqf b/addons/common/functions/fnc_getPosFromScreen.sqf index dcf7fb95c..4d1e34dbe 100644 --- a/addons/common/functions/fnc_getPosFromScreen.sqf +++ b/addons/common/functions/fnc_getPosFromScreen.sqf @@ -2,11 +2,14 @@ /* * Author: mharis001 * Returns a world position based on the given screen position. - * Will attempt to find a flat position on an intersecting surface if enabled. + * Can attempt to find a flat position on an intersecting surface if enabled. * * Arguments: * 0: Screen Position (default: getMousePosition) - * 1: Check Intersections (default: true) + * 1: Check Intersections (default: true) + * - 0, false: Do not check for intersections, return position on terrain. + * - 1, true: Check for intersections with surfaces. + * - 2: Check for intersections and attempt to find a flat surface. * * Return Value: * Position ASL @@ -19,26 +22,41 @@ #define MAX_RESULTS 5 -params [["_screenPos", getMousePosition, [[]], 2], ["_checkIntersections", true, [true]]]; +params [["_screenPos", getMousePosition, [[]], 2], ["_checkIntersections", true, [true, 0]]]; + +if (_checkIntersections isEqualType true) then { + _checkIntersections = parseNumber _checkIntersections; +}; if (visibleMap) then { private _ctrlMap = findDisplay IDD_RSCDISPLAYCURATOR displayCtrl IDC_RSCDISPLAYCURATOR_MAINMAP; - private _pos2D = _ctrlMap ctrlMapScreenToWorld _screenPos; - - AGLtoASL (_pos2D + [0]) + AGLToASL (_ctrlMap posScreenToWorld _screenPos) } else { - private _position = AGLtoASL screenToWorld _screenPos; + private _position = AGLToASL screenToWorld _screenPos; - if (_checkIntersections) then { - { - _x params ["_intersectPos", "_surfaceNormal"]; + switch (_checkIntersections) do { + case 0: { + _position + }; + case 1: { + lineIntersectsSurfaces [getPosASL curatorCamera, _position] param [0, []] param [0, _position] + }; + case 2: { + { + _x params ["_intersectPos", "_surfaceNormal"]; - // Use the intersection position if the surface is relatively flat - if (_surfaceNormal vectorDotProduct [0, 0, 1] > 0.5) exitWith { - _position = _intersectPos; - }; - } forEach lineIntersectsSurfaces [getPosASL curatorCamera, _position, objNull, objNull, true, MAX_RESULTS, "VIEW", "FIRE", false]; - }; + // Always keep the first intersection as a fallback + if (_forEachIndex == 0) then { + _position = _intersectPos; + }; + + // Use the intersection position if the surface is relatively flat + if (_surfaceNormal vectorDotProduct [0, 0, 1] > 0.5) exitWith { + _position = _intersectPos; + }; + } forEach lineIntersectsSurfaces [getPosASL curatorCamera, _position, objNull, objNull, true, MAX_RESULTS, "VIEW", "FIRE", false]; - _position + _position + }; + }; }; diff --git a/addons/common/functions/fnc_selectPosition.sqf b/addons/common/functions/fnc_selectPosition.sqf index c821568ca..19cf3f2ed 100644 --- a/addons/common/functions/fnc_selectPosition.sqf +++ b/addons/common/functions/fnc_selectPosition.sqf @@ -81,7 +81,7 @@ private _mouseEH = [_display, "MouseButtonDown", { if (_button != 0) exitWith {}; - private _position = [] call FUNC(getPosFromScreen); + private _position = [nil, 2] call FUNC(getPosFromScreen); _thisArgs params ["_objects", "_function", "_args"]; [true, _objects, _position, _args, _shift, _ctrl, _alt] call _function; @@ -94,7 +94,7 @@ private _keyboardEH = [_display, "KeyDown", { if (_key != DIK_ESCAPE) exitWith {false}; - private _position = [] call FUNC(getPosFromScreen); + private _position = [nil, 2] call FUNC(getPosFromScreen); _thisArgs params ["_objects", "_function", "_args"]; [false, _objects, _position, _args, _shift, _ctrl, _alt] call _function; @@ -108,7 +108,7 @@ private _drawEH = [_ctrlMap, "Draw", { params ["_ctrlMap"]; _thisArgs params ["_objects", "_args", "_visuals", "_modifierFunction"]; - private _position = [] call FUNC(getPosFromScreen); + private _position = [nil, 2] call FUNC(getPosFromScreen); [_objects, _position, _args, _visuals] call _modifierFunction; _visuals params ["_text", "_icon", "_angle", "_color"]; @@ -155,7 +155,7 @@ private _drawEH = [_ctrlMap, "Draw", { // No 3D drawing needed if the map is visible if (visibleMap) exitWith {}; - private _position = [] call FUNC(getPosFromScreen); + private _position = [nil, 2] call FUNC(getPosFromScreen); [_objects, _position, _args, _visuals] call _modifierFunction; _visuals params ["_text", "_icon", "_angle", "_color"]; diff --git a/addons/context_menu/script_component.hpp b/addons/context_menu/script_component.hpp index 72436ff40..4593a9a4f 100644 --- a/addons/context_menu/script_component.hpp +++ b/addons/context_menu/script_component.hpp @@ -39,7 +39,7 @@ // _contextPosASL and _selectedObjects, _selectedGroups .., kept for BWC #define SETUP_ACTION_VARS \ - private _position = [GVAR(mousePos)] call EFUNC(common,getPosFromScreen); \ + private _position = [GVAR(mousePos), 2] call EFUNC(common,getPosFromScreen); \ private _hoveredEntity = GVAR(hovered); \ +GVAR(selected) params ["_objects", "_groups", "_waypoints", "_markers"]; \ private _contextPosASL = _position; \ diff --git a/addons/visibility/XEH_postInit.sqf b/addons/visibility/XEH_postInit.sqf index 3eca6b728..69d4a3951 100644 --- a/addons/visibility/XEH_postInit.sqf +++ b/addons/visibility/XEH_postInit.sqf @@ -1,7 +1,7 @@ #include "script_component.hpp" ["zen_curatorDisplayLoaded", { - if (GVAR(enabled)) then { + if (GVAR(enabled) != INDICATOR_DISABLED) then { call FUNC(start); }; }] call CBA_fnc_addEventHandler; diff --git a/addons/visibility/functions/fnc_draw.sqf b/addons/visibility/functions/fnc_draw.sqf index 195570cca..563b87ed2 100644 --- a/addons/visibility/functions/fnc_draw.sqf +++ b/addons/visibility/functions/fnc_draw.sqf @@ -15,46 +15,49 @@ * Public: No */ -if (call EFUNC(common,isInScreenshotMode)) exitWith {}; +if ( + call EFUNC(common,isInScreenshotMode) + || {GVAR(enabled) == INDICATOR_PLACEMENT_ONLY && {!call EFUNC(common,isPlacementActive)}} +) exitWith {}; -// The cursor position in the world -private _pos = AGLtoASL screenToWorld getMousePosition; -private _intersections = lineIntersectsSurfaces [getPosASL curatorCamera, _pos]; -if (_intersections isNotEqualTo []) then { - _pos = _intersections select 0 select 0; -}; - -// Check 1.5 above the cursor to prevent a small object on the terrain blocking the view +// Get the cursor's position in the world +// Check 1.5 m above the position to check for small terrain objects blocking the view +// Converting to AGL here to avoid repeated conversions in the loop +private _pos = [] call EFUNC(common,getPosFromScreen); private _posHigh = _pos vectorAdd [0, 0, 1.5]; -private _draw = false; +private _posAGL = ASLToAGL _pos; + +private _visible = false; { // Check if the cursor's position is in the player's view (filter the local player and virtual units) - if (_x != player && {side _x != sideLogic} && {((_x getRelDir _posHigh) + 90) mod 360 < 180}) then { + if ( + //_x != player + side _x != sideLogic + && {_x distance _posAGL <= GVAR(maxDistance)} + && { + private _dir = _x getRelDir _pos; + _dir <= 90 || {_dir >= 270} + } + ) then { private _eyePos = eyePos _x; - if (lineIntersectsSurfaces [_eyePos, _pos, _x, objNull] isEqualTo [] || {lineIntersectsSurfaces [_eyePos, _posHigh, _x, objNull] isEqualTo []}) then { + + if ( + lineIntersectsSurfaces [_eyePos, _pos, _x] isEqualTo [] + || {lineIntersectsSurfaces [_eyePos, _posHigh, _x] isEqualTo []} + ) then { // Check visibility through smoke private _visibility = [objNull, "VIEW"] checkVisibility [_eyePos, _posHigh]; // Draw a line from each player that can see the cursor - drawLine3D [ASLToAGL _eyePos, ASLToAGL _pos, [1, 0, 0, _visibility]]; + drawLine3D [ASLToAGL _eyePos, _posAGL, [1, 0, 0, _visibility]]; - _draw = true; + _visible = true; }; }; } forEach allPlayers; -// Write visible under the cursor if any player can see the position -if (_draw) then { - drawIcon3D [ - "", - [1, 0, 0, 1], - ASLToAGL _pos, - 1, 1.3, 0, - LLSTRING(Visible), - 2, - 0.04, - "PuristaMedium", - "center" - ]; +// Write visible under the cursor if a player can see the position +if (_visible) then { + drawIcon3D ["", [1, 0, 0, 1], _posAGL, 1, 1.3, 0, LLSTRING(Visible), 2, 0.04, "PuristaMedium", "center"]; }; diff --git a/addons/visibility/initSettings.sqf b/addons/visibility/initSettings.sqf index d0b4416e4..416cd59fa 100644 --- a/addons/visibility/initSettings.sqf +++ b/addons/visibility/initSettings.sqf @@ -1,19 +1,40 @@ [ QGVAR(enabled), - "CHECKBOX", + "LIST", [LSTRING(Enabled), LSTRING(Enabled_Description)], - ELSTRING(main,DisplayName), - false, + [ELSTRING(main,DisplayName), LSTRING(DisplayName)], + [ + [ + INDICATOR_DISABLED, + INDICATOR_ENABLED, + INDICATOR_PLACEMENT_ONLY + ], + [ + ELSTRING(common,Disabled), + ELSTRING(common,Enabled), + [LSTRING(DuringPlacementOnly), LSTRING(DuringPlacementOnly_Description)] + ], + 0 + ], false, { params ["_value"]; if (isNull findDisplay IDD_RSCDISPLAYCURATOR) exitWith {}; - if (_value) then { + if (_value != INDICATOR_DISABLED) then { call FUNC(start); } else { call FUNC(stop); }; } ] call CBA_fnc_addSetting; + +[ + QGVAR(maxDistance), + "SLIDER", + [LSTRING(MaxDistance), LSTRING(MaxDistance_Description)], + [ELSTRING(main,DisplayName), LSTRING(DisplayName)], + [100, 5000, 5000, -1], + false +] call CBA_fnc_addSetting; diff --git a/addons/visibility/script_component.hpp b/addons/visibility/script_component.hpp index 9ee018b6e..aa5828899 100644 --- a/addons/visibility/script_component.hpp +++ b/addons/visibility/script_component.hpp @@ -17,3 +17,7 @@ #include "\x\zen\addons\main\script_macros.hpp" #include "\x\zen\addons\common\defineResinclDesign.inc" + +#define INDICATOR_DISABLED 0 +#define INDICATOR_ENABLED 1 +#define INDICATOR_PLACEMENT_ONLY 2 diff --git a/addons/visibility/stringtable.xml b/addons/visibility/stringtable.xml index fd03fdcda..df278522d 100644 --- a/addons/visibility/stringtable.xml +++ b/addons/visibility/stringtable.xml @@ -1,7 +1,7 @@ - + Visibility Indicator Indicateur de visibilité Sichtbarkeitsindikator @@ -11,8 +11,11 @@ 能见度指标 Indicatore di visibilità + + Enable Visibility Indicator + - Indicates when a player can see the Zeus' cursor. + Enables showing an indicator when a player can see the Zeus cursor position. Indique quand un joueur peut voir le curseur de Zeus. Zeigt an, wann ein Spieler den Zeuszeiger sehen könnte. Wskazuje czy kursor Zeusa jest widoczny dla gracza. @@ -21,6 +24,18 @@ 顯示玩家何時能看到宙斯的光標。 Indica quando un giocatore può vedere il cursore 'Zeus' + + During Placement Only + + + Only show the indicator while placing objects. + + + Max Check Distance + + + Controls the maximum distance from the cursor's position that players are considered for visibility checks. + VISIBLE VISIBLE From c2c715fc040280c45fb6e1240fa65b2745de1523 Mon Sep 17 00:00:00 2001 From: Kex Date: Sat, 1 Oct 2022 16:20:21 +0200 Subject: [PATCH 2/3] Add German translations --- addons/visibility/stringtable.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/visibility/stringtable.xml b/addons/visibility/stringtable.xml index df278522d..870b6f6b9 100644 --- a/addons/visibility/stringtable.xml +++ b/addons/visibility/stringtable.xml @@ -13,6 +13,7 @@ Enable Visibility Indicator + Aktiviere den Sichtbarkeitsindikator Enables showing an indicator when a player can see the Zeus cursor position. @@ -26,15 +27,19 @@ During Placement Only + Nur während dem Platzieren Only show the indicator while placing objects. + Zeigt den Indikator nur an während dem Platzieren Max Check Distance + Maximale Distanz Controls the maximum distance from the cursor's position that players are considered for visibility checks. + Die Maximale Distanz zwischen dem Mauszeiger and den Spielern, bei der die Sichtbarkeit überprüft wird. VISIBLE From 6134db74d6a2e07b6e1c992e8b61ce1f1c2dd287 Mon Sep 17 00:00:00 2001 From: mharis001 <34453221+mharis001@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:52:03 -0400 Subject: [PATCH 3/3] Fix commented out code --- addons/visibility/functions/fnc_draw.sqf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/visibility/functions/fnc_draw.sqf b/addons/visibility/functions/fnc_draw.sqf index 563b87ed2..a90f4f6e9 100644 --- a/addons/visibility/functions/fnc_draw.sqf +++ b/addons/visibility/functions/fnc_draw.sqf @@ -32,8 +32,8 @@ private _visible = false; { // Check if the cursor's position is in the player's view (filter the local player and virtual units) if ( - //_x != player - side _x != sideLogic + _x != player + && {side _x != sideLogic} && {_x distance _posAGL <= GVAR(maxDistance)} && { private _dir = _x getRelDir _pos;