diff --git a/AUTHORS.txt b/AUTHORS.txt index c8145e3970..8b729a6f63 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -101,3 +101,4 @@ Valentin Torikian VyMajoris(W-Cephei) Winter zGuba +Drill diff --git a/addons/finger/$PBOPREFIX$ b/addons/finger/$PBOPREFIX$ new file mode 100644 index 0000000000..746f380ecc --- /dev/null +++ b/addons/finger/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\finger \ No newline at end of file diff --git a/addons/finger/ACE_Settings.hpp b/addons/finger/ACE_Settings.hpp new file mode 100644 index 0000000000..584d1d03de --- /dev/null +++ b/addons/finger/ACE_Settings.hpp @@ -0,0 +1,23 @@ +#include "code\addon.hpp" + +#define LOC(x) $__LOCALIZE_PREFIX__##x + + +class ACE_Settings { + class GVAR(FP_indicator_for_self) { + displayName = LOC(indicator_for_self); + description = LOC(indicator_for_self__desc); + isClientSettable = 1; + typeName = "BOOL"; + value = 1; + }; + class GVAR(FP_indicator_color) + { + value[] = {0.83, 0.68, 0.21, 0.75}; + typeName = "COLOR"; + isClientSettable = 1; + displayName = LOC(color); + description = LOC(color__desc); + }; + +}; diff --git a/addons/finger/code/addon.hpp b/addons/finger/code/addon.hpp new file mode 100644 index 0000000000..aedbcad672 --- /dev/null +++ b/addons/finger/code/addon.hpp @@ -0,0 +1,26 @@ +#ifndef __ADDON_HPP_ +#define __ADDON_HPP_ + + +#define __ADDON_NAME__ ace_finger +#define __BASENAME__ __ADDON_NAME__##_var +#define __PREFIX__ "\z\ace\addons\finger" +#define __PREFIXC__ "\z\ace\addons\finger\code\" + +#define FUNC(x) __BASENAME__##_fnc_##x +#define CFUNC(x) __ADDON_NAME__##_fnc_##x + +#define GVAR(x) __BASENAME__##_##x + +#define __LOCALIZE_PREFIX__ STR_Addons_ACE__dfinger__ +#define LOCALIZE(x) (localize ('__LOCALIZE_PREFIX__##x')) + + + + +#define PV(x) private ['x']; x + + + + +#endif diff --git a/addons/finger/code/fn__OEF_renderer.sqf b/addons/finger/code/fn__OEF_renderer.sqf new file mode 100644 index 0000000000..586e852ef0 --- /dev/null +++ b/addons/finger/code/fn__OEF_renderer.sqf @@ -0,0 +1,24 @@ +#include "addon.hpp" +#include "main.hpp" + +#define BASE_SIZE 44 + + +PV(_pos) = [0,0,0]; +PV(_name) = ""; + + +PV(_fov_corr) = ((worldToScreen (positionCameraToWorld [1000, 0, 10000])) select 0) - 0.5; +PV(_sz) = BASE_SIZE * _fov_corr; + +{ + _pos = _x select 0; + _name = _x select 1; + + drawIcon3D [FP_ICON, [ + GVAR(FP_indicator_color) select 0, + GVAR(FP_indicator_color) select 1, + GVAR(FP_indicator_color) select 2, + (GVAR(FP_indicator_color) select 3) max MIN_OPAQUE + ], _pos, _sz, _sz, 0, _name, 1, 0.03, "PuristaMedium"]; +} forEach MAP_VALUES(GVAR(cur_fps)); diff --git a/addons/finger/code/fn__comm.sqf b/addons/finger/code/fn__comm.sqf new file mode 100644 index 0000000000..fd1a088325 --- /dev/null +++ b/addons/finger/code/fn__comm.sqf @@ -0,0 +1,94 @@ +#include "addon.hpp" +#include "main.hpp" + +// finger-pointing array format: +// 1: source player +// 2: position of finger-pointing +// 3: players to broadcast the finger-pointing to + +// server-side event-handlers + +if (isServer) then +{ + // receives finger-pointing array and broadcasts it to provided players + + GVAR(fnc_pv_fpToServer) = + { + LOGV(_this); + + PV(_val) = _this select 1; + + PV(_sp) = _val select 0; + PV(_pfp) = _val select 1; + PV(_dps) = _val select 2; + + GVAR(pv_fpToClient) = [_sp, _pfp]; + PV(_owner) = 0; + { + _owner = owner _x; + + LOGV(_x); + LOGV(_owner); + + if (_owner > 0 && {isPlayer _x}) then + { + if (player == _x) then + { + [0, GVAR(pv_fpToClient)] call GVAR(fnc_pv_fpToClient); + } + else + { + _owner publicVariableClient 'GVAR(pv_fpToClient)'; + }; + }; + } forEach _dps; + + }; + + + + 'GVAR(pv_fpToServer)' addPublicVariableEventHandler GVAR(fnc_pv_fpToServer); + +}; + + +if (hasInterface) then +{ + // currently shown finger-pointings map + // key: source player + // value: [position, source player name, last update time] + // + + + GVAR(cur_fps) = CREATE_MAP(); + + GVAR(fp_handler_running) = false; + + + // receives pointing-object and starts drawing process in format + // 1: source player + // 2: position of finger-pointing + // + + GVAR(fnc_pv_fpToClient) = { + LOGV(_this); + + PV(_val) = _this select 1; + PV(_sp) = _val select 0; + PV(_pfp) = _val select 1; + + PV(_newval) = [_pfp, name _sp, diag_tickTime]; + MAP_SET(GVAR(cur_fps), _sp, _newval); + + if (!GVAR(fp_handler_running)) then + { + GVAR(fp_handler_running) = true; + + [] spawn CFUNC(_fp_handler); + }; + }; + + 'GVAR(pv_fpToClient)' addPublicVariableEventHandler GVAR(fnc_pv_fpToClient); + + +}; diff --git a/addons/finger/code/fn__fp_handler.sqf b/addons/finger/code/fn__fp_handler.sqf new file mode 100644 index 0000000000..52dedaf9be --- /dev/null +++ b/addons/finger/code/fn__fp_handler.sqf @@ -0,0 +1,44 @@ +#include "addon.hpp" +#include "main.hpp" + +['GVAR(_OEF_renderer)', "onEachFrame", CFUNC(_OEF_renderer)] + call BIS_fnc_addStackedEventHandler; + + +// deleting figner-pointings which last more than FP_TIMEOUT + +while {MAP_LEN(GVAR(cur_fps)) > 0} do +{ + if (!( + alive player && + {player == vehicle player || + (vehicle player) isKindOf "StaticWeapon"} + )) exitWith + { + GVAR(cur_fps) = CREATE_MAP(); + }; + + + _ct = diag_tickTime; + + _i = 0; + while {_i < MAP_LEN(GVAR(cur_fps))} do + { + _e = MAP_VALUES(GVAR(cur_fps)) select _i; + if (_ct > (_e select 2) + FP_TIMEOUT) then + { + MAP_IDEL(GVAR(cur_fps), _i); + } + else + { + _i = _i + 1; + }; + }; + + sleep 0.1; +}; + + +['GVAR(_OEF_renderer)', "onEachFrame"] call BIS_fnc_addStackedEventHandler; + +GVAR(fp_handler_running) = false; diff --git a/addons/finger/code/fn__init.sqf b/addons/finger/code/fn__init.sqf new file mode 100644 index 0000000000..266c4017fb --- /dev/null +++ b/addons/finger/code/fn__init.sqf @@ -0,0 +1,18 @@ +#include "addon.hpp" +#include "main.hpp" + +[] spawn +{ + [] call CFUNC(_comm); +}; + + +if (hasInterface) then +{ + [] spawn + { + [] call CFUNC(_mainLoop); + }; +}; + + diff --git a/addons/finger/code/fn__mainLoop.sqf b/addons/finger/code/fn__mainLoop.sqf new file mode 100644 index 0000000000..087d6b0f55 --- /dev/null +++ b/addons/finger/code/fn__mainLoop.sqf @@ -0,0 +1,90 @@ +#include "addon.hpp" +#include "main.hpp" + +LOG("Starting"); + +//while {isNull (findDisplay 46)} do {sleep 1;}; + + +GVAR(FP_keyComb) = [41, false, true, false]; // Ctrl + Tilda + +GVAR(lastFPTime) = -FP_ACTION_TIMEOUT; + + +["ACE3 Common", + "point_finger_at", + [LOCALIZE(keyComb), LOCALIZE(keyComb)], + { + + PV(_rv) = false; + if (alive player) then + { + if (!( + (player == vehicle player || + (vehicle player) isKindOf "StaticWeapon") && + cameraView in ["INTERNAL", "EXTERNAL"] + )) exitWith {}; + + _rv = true; + + if (diag_tickTime < GVAR(lastFPTime) + FP_ACTION_TIMEOUT) + exitWith {}; + + + PV(_pos_prec) = positionCameraToWorld [0, 0, FP_DISTANCE]; + PV(_pos) = positionCameraToWorld [ + random (2*FP_RANDOMIZATION_X) - FP_RANDOMIZATION_X, + random (2*FP_RANDOMIZATION_Y) - FP_RANDOMIZATION_Y, + FP_DISTANCE + ]; + + + PV(_dest_players) = []; + + PV(_pep) = eyePos player; + { + if (isPlayer _x && _x != player && alive _x && + {(_x == vehicle _x || (vehicle _x) isKindOf "StaticWeapon") && { + ((eyePos _x) vectorDistance _pep) < MAX_DIST_TO_OTHER_PLAYERS + }}) then + { + _dest_players pushBack _x; + }; + } forEach playableUnits; + + GVAR(pv_fpToServer) = [player, _pos, _dest_players]; + + LOGV(GVAR(pv_fpToServer)); + + if (isServer) then + { + [0, GVAR(pv_fpToServer)] call GVAR(fnc_pv_fpToServer); + } + else + { + publicVariableServer 'GVAR(pv_fpToServer)'; + }; + + + if (GVAR(FP_indicator_for_self)) then + { + [0, [player, _pos_prec]] call GVAR(fnc_pv_fpToClient); + }; + + player playActionNow "GestureGo"; + GVAR(lastFPTime) = diag_tickTime; + + _rv = true; + }; + + _rv; + }, + "", + [GVAR(FP_keyComb) select 0, + [GVAR(FP_keyComb) select 1, GVAR(FP_keyComb) select 2, GVAR(FP_keyComb) select 3]] +] call cba_fnc_addKeybind; + + + + +LOG("Done"); diff --git a/addons/finger/code/macros.hpp b/addons/finger/code/macros.hpp new file mode 100644 index 0000000000..13b3a30807 --- /dev/null +++ b/addons/finger/code/macros.hpp @@ -0,0 +1,54 @@ +#define XOR(x,y) (((x)||(y)) && !((x)&&(y))) +#define SQR(x) ((x)*(x)) + + +// debug + + +#ifdef DEBUG + #define LOG(msg) (diag_log text format["%1:%2> %3", __FILE__, __LINE__, (msg)]) + #define LOGV(msg) (diag_log text format["%1:%2> %3 = %4", __FILE__, __LINE__, (#msg), (msg)]) +#else + #define LOG(msg) + #define LOGV(msg) +#endif + + + + + +// map macros + +#define CREATE_MAP() [[],[]] + +#define MAP_KEYS(m) ((m) select 0) +#define MAP_VALUES(m) ((m) select 1) + +#define MAP_SET(m, k, v) if (true) then {_____map_t = MAP_KEYS(m) find (k);\ + if (_____map_t >= 0) exitWith {MAP_VALUES(m) set [_____map_t, (v)]};\ + _____map_t = count MAP_KEYS(m);\ + MAP_KEYS(m) set [_____map_t, (k)];\ + MAP_VALUES(m) set [_____map_t, (v)];\ +} + +#define MAP_GET(m, k) if (true) then {_____map_t = MAP_KEYS(m) find (k);\ + if (_____map_t >= 0) exitWith {MAP_VALUES(m) select _____map_t};\ + nil\ +} + +#define MAP_DEL(m, k) if (true) then {_____map_t = MAP_KEYS(m) find (k);\ + if (_____map_t >= 0) exitWith {\ + MAP_KEYS(m) deleteAt _____map_t;\ + MAP_VALUES(m) deleteAt _____map_t;\ + };\ +} + +#define MAP_LEN(m) (count MAP_KEYS(m)) + +#define MAP_IKEY(m, k) (MAP_KEYS(m) find (k)) +#define MAP_IGET(m, i) (MAP_VALUES(m) select (i)) +#define MAP_ISET(m, i, v) (MAP_VALUES(m) set [(i), (v)]) +#define MAP_IDEL(m, i) if (true) then {\ + MAP_KEYS(m) deleteAt (i);\ + MAP_VALUES(m) deleteAt (i);\ +} diff --git a/addons/finger/code/main.hpp b/addons/finger/code/main.hpp new file mode 100644 index 0000000000..7a58ba5a75 --- /dev/null +++ b/addons/finger/code/main.hpp @@ -0,0 +1,12 @@ +#ifndef __MAIN_HPP_ +#define __MAIN_HPP_ + +#include "addon.hpp" + +#include "settings.hpp" + +#include "structures.hpp" +#include "macros.hpp" + + +#endif diff --git a/addons/finger/code/settings.hpp b/addons/finger/code/settings.hpp new file mode 100644 index 0000000000..42d13ec809 --- /dev/null +++ b/addons/finger/code/settings.hpp @@ -0,0 +1,23 @@ +#ifndef __STRUCTURES_H__ +#define __STRUCTURES_H__ + +// #define DEBUG + + +#define FP_ICON "\z\ace\addons\finger\img\fp_icon.paa" + + +#define FP_TIMEOUT 2 +#define FP_ACTION_TIMEOUT 1 + +#define FP_DISTANCE 10000 +#define FP_RANDOMIZATION_X 350 +#define FP_RANDOMIZATION_Y 100 + +#define MAX_DIST_TO_OTHER_PLAYERS 4 + + +#define MIN_OPAQUE 0.1 + + +#endif diff --git a/addons/finger/code/structures.hpp b/addons/finger/code/structures.hpp new file mode 100644 index 0000000000..4922612347 --- /dev/null +++ b/addons/finger/code/structures.hpp @@ -0,0 +1,10 @@ +#ifndef __STRUCTURES_H__ +#define __STRUCTURES_H__ + + + + + + + +#endif diff --git a/addons/finger/config.cpp b/addons/finger/config.cpp new file mode 100644 index 0000000000..dd97a6294d --- /dev/null +++ b/addons/finger/config.cpp @@ -0,0 +1,52 @@ +#include "script_component.hpp" + +#define RECOMPILE 0 + +class CfgPatches +{ + class ace_finger + { + units[]={}; + weapons[]={}; + + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common"}; + + author[]= + { + "Drill" + }; + authorUrl = "https://github.com/TheDrill/"; + + addon_version=6; + + VERSION_CONFIG; + }; +}; + +class CfgFunctions +{ + class ace_finger + { + class Main + { + file="\z\ace\addons\finger\code"; + class _init + { + preInit=0; + postInit=1; + recompile=RECOMPILE; + }; + + class _mainLoop {recompile=RECOMPILE;}; + class _comm {recompile=RECOMPILE;}; + class _fp_handler {recompile=RECOMPILE;}; + class _OEF_renderer {recompile=RECOMPILE;}; + }; + }; +}; + + + +#include "ACE_Settings.hpp" + diff --git a/addons/finger/img/fp_icon.paa b/addons/finger/img/fp_icon.paa new file mode 100644 index 0000000000..9fccb144f1 Binary files /dev/null and b/addons/finger/img/fp_icon.paa differ diff --git a/addons/finger/script_component.hpp b/addons/finger/script_component.hpp new file mode 100644 index 0000000000..3d1bf7d049 --- /dev/null +++ b/addons/finger/script_component.hpp @@ -0,0 +1,12 @@ +#define COMPONENT finger +#include "\z\ace\Addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_FINGER + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_FINGER + #define DEBUG_SETTINGS DEBUG_SETTINGS_FINGER +#endif + +#include "\z\ace\Addons\main\script_macros.hpp" \ No newline at end of file diff --git a/addons/finger/stringtable.xml b/addons/finger/stringtable.xml new file mode 100644 index 0000000000..ad8e643c75 --- /dev/null +++ b/addons/finger/stringtable.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + Show finger indicator to self + Отображать пальце-индикатор для показывающего игрока + + + Render the indicator for the pointing player. This option doesn't affect whether the other players would see the indicator + Отображать индикатор для показывающего игрока. Эта настройка не влияет на то, будутт ли другие игроки видеть индикатор + + + + Finger indicator + Пальце-индикатор + + + Color of the finger-pointing indicator circle + Цвет индикатора пальце-указания + + + + Action "point a finger at" + Действие "показать пальцем на" + + + +