diff --git a/.gitignore b/.gitignore
index f05646fb8a..f312ddb55e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ texHeaders.bin
*.swp
*.swo
*.biprivatekey
+Thumbs.db
diff --git a/ace_parse_imagepath.dll b/ace_parse_imagepath.dll
new file mode 100644
index 0000000000..33264959a8
Binary files /dev/null and b/ace_parse_imagepath.dll differ
diff --git a/addons/advanced_ballistics/stringtable.xml b/addons/advanced_ballistics/stringtable.xml
index 8ba88dee2b..5c6dd58d6e 100644
--- a/addons/advanced_ballistics/stringtable.xml
+++ b/addons/advanced_ballistics/stringtable.xml
@@ -210,7 +210,6 @@
Define o raio ao redor do jogador (em metros) onde a balística avançada será aplicada aos projéteis
-
Moduł ten pozwala aktywować zaawansowaną balistykę biorącą przy obliczeniach trajektorii lotu pocisku pod uwagę takie rzeczy jak temperatura powietrza, ciśnienie atmosferyczne, wilgotność powietrza, siły Coriolisa i Eotvosa, grawitację a także broń z jakiej wykonywany jest strzał oraz rodzaj amunicji. Wszystko to sprowadza się na bardzo dokładne odwzorowanie balistyki.
Tento modul umožňuje aktivovat pokročilou balistiku, která vypočítává trajektorii kulky a bere do úvahy věci jako je teplota vzduchu, atmosférický tlak, vlhkost vzduchu, gravitaci, typ munice a zbraň, ze které je náboj vystřelen. To vše přispívá k velmi přesné balistice.
Este módulo permite que você ative cálculos de balística avançada, fazendo a trajetória do projétil levar em consideração coisas como temperatura do ar, pressão atmosférica, umidade, força de Coriolis, a gravidade, o modelo da arma no qual o disparo é realizado e o tipo de munição. Tudo isso acrescenta-se a um balística muito precisa.
diff --git a/addons/backpacks/README.md b/addons/backpacks/README.md
index 9c721428b1..6fa54a9897 100644
--- a/addons/backpacks/README.md
+++ b/addons/backpacks/README.md
@@ -1,8 +1,7 @@
-ace_lockbackpacks
+ace_backpacks
=================
-Introduces the ability to lock one's backpack.
-
+Adds indication when someone else opens your backpack (soundeffect / camShake).
## Maintainers
diff --git a/addons/common/XEH_postInit.sqf b/addons/common/XEH_postInit.sqf
index ce79c078ba..8b8b3a9005 100644
--- a/addons/common/XEH_postInit.sqf
+++ b/addons/common/XEH_postInit.sqf
@@ -6,7 +6,7 @@
//Singe PFEH to handle execNextFrame and waitAndExec:
[{
private ["_entry"];
-
+
//Handle the waitAndExec array:
while {((count GVAR(waitAndExecArray)) > 0) && {((GVAR(waitAndExecArray) select 0) select 0) <= ACE_Time}} do {
_entry = GVAR(waitAndExecArray) deleteAt 0;
@@ -64,6 +64,10 @@
["setFuel", {(_this select 0) setFuel (_this select 1)}] call FUNC(addEventhandler);
["setSpeaker", {(_this select 0) setSpeaker (_this select 1)}] call FUNC(addEventhandler);
+if (isServer) then {
+ ["hideObjectGlobal", {(_this select 0) hideObjectGlobal (_this select 1)}] call FUNC(addEventHandler);
+};
+
// hack to get PFH to work in briefing
[QGVAR(onBriefingPFH), "onEachFrame", {
if (ACE_time > 0) exitWith {
diff --git a/addons/common/XEH_preInit.sqf b/addons/common/XEH_preInit.sqf
index de9d0aa91a..6c088a3542 100644
--- a/addons/common/XEH_preInit.sqf
+++ b/addons/common/XEH_preInit.sqf
@@ -106,6 +106,7 @@ PREP(goKneeling);
PREP(hadamardProduct);
PREP(hasItem);
PREP(hasMagazine);
+PREP(hideUnit);
PREP(inheritsFrom);
PREP(insertionSort);
PREP(interpolateFromArray);
@@ -183,6 +184,7 @@ PREP(toBin);
PREP(toBitmask);
PREP(toHex);
PREP(toNumber);
+PREP(unhideUnit);
PREP(uniqueElementsOnly);
PREP(unloadPerson);
PREP(unloadPersonLocal);
diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf
index 631329ecee..647a1b00a6 100644
--- a/addons/common/functions/fnc_checkFiles.sqf
+++ b/addons/common/functions/fnc_checkFiles.sqf
@@ -56,20 +56,23 @@ _addons = [_addons, {_this find "ace_" == 0}] call FUNC(filter);
} forEach getArray (configFile >> "ACE_Extensions" >> "extensions");
///////////////
-// check server version
+// check server version/addons
///////////////
if (isMultiplayer) then {
if (isServer) then {
// send servers version of ACE to all clients
GVAR(ServerVersion) = _version;
+ GVAR(ServerAddons) = _addons;
publicVariable QGVAR(ServerVersion);
+ publicVariable QGVAR(ServerAddons);
} else {
- // clients have to wait for the variable
+ // clients have to wait for the variables
[{
- if (isNil QGVAR(ServerVersion)) exitWith {};
+ if (isNil QGVAR(ServerVersion) || isNil QGVAR(ServerAddons)) exitWith {};
- private "_version";
- _version = _this select 0;
+ private ["_version","_addons"];
+ _version = (_this select 0) select 0;
+ _addons = (_this select 0) select 1;
if (_version != GVAR(ServerVersion)) then {
private "_errorMsg";
@@ -82,7 +85,18 @@ if (isMultiplayer) then {
};
};
+ _addons = _addons - GVAR(ServerAddons);
+ if !(_addons isEqualTo []) then {
+ _errorMsg = format ["Client/Server Addon Mismatch. Client has extra addons: %1.",_addons];
+
+ diag_log text format ["[ACE] ERROR: %1", _errorMsg];
+
+ if (hasInterface) then {diag_log str "1";
+ ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage);
+ };
+ };
+
[_this select 1] call CBA_fnc_removePerFrameHandler;
- }, 1, _version] call CBA_fnc_addPerFrameHandler;
+ }, 1, [_version,_addons]] call CBA_fnc_addPerFrameHandler;
};
};
diff --git a/addons/common/functions/fnc_checkPBOs.sqf b/addons/common/functions/fnc_checkPBOs.sqf
index 4733f1a81f..ac6d8fb270 100644
--- a/addons/common/functions/fnc_checkPBOs.sqf
+++ b/addons/common/functions/fnc_checkPBOs.sqf
@@ -8,8 +8,8 @@
* 0: Warn once
* 1: Warn permanently
* 2: Kick
- * 1: Check all PBOs? (Optional - default: "[]")
- * 2: Whitelist (Optinal - default: false)
+ * 1: Check all PBOs? (Optional - default: false)
+ * 2: Whitelist (Optinal - default: "[]")
*
* Return value:
* None
diff --git a/addons/common/functions/fnc_hideUnit.sqf b/addons/common/functions/fnc_hideUnit.sqf
new file mode 100644
index 0000000000..94857335f4
--- /dev/null
+++ b/addons/common/functions/fnc_hideUnit.sqf
@@ -0,0 +1,34 @@
+/*
+ * Author: SilentSpike (based on muteUnit)
+ * Globally hides a unit. This allows the handling of more than one reason to hide an object globally.
+ *
+ * Arguments:
+ * 0: Unit
Close Handheld Device
Cerrar dispositivo de mano
Fecha dispositivo de mão
+ Zamknij urządzenie podręczne
+ Zavřít ruční zařízení
Cycle Handheld Devices
Cambiar dispositivos de mano
Troca dispositivos de mão
+ Następne urządzenie podręczne
+ Procházet ruční zařízení
\ No newline at end of file
diff --git a/addons/concertina_wire/stringtable.xml b/addons/concertina_wire/stringtable.xml
index 4400866e87..812de87e6c 100644
--- a/addons/concertina_wire/stringtable.xml
+++ b/addons/concertina_wire/stringtable.xml
@@ -6,7 +6,7 @@
NATO-Draht
Проволочная спираль
Drut kolczasty
- Concertina wire
+ Alambre de espino
Concertina wire
Ostnatý drát
Concertina wire
@@ -18,7 +18,7 @@
NATO-Draht Rolle
Проволочная спираль (моток)
Zwój drutu kolczastego
- Concertina wire coil
+ Bobina de alambre de espino
Concertina wire coil
Smyčka ostnatého drátu
Concertina wire coil
@@ -30,7 +30,7 @@
NATO-Draht abbauen
Демонтировать проволочную спираль
Zwiń drut kolczasty
- Dismount Concertina wire
+ Desmontar alambre de espino
Dismount Concertina wire
Svinout ostnatý drát
Dismount Concertina wire
@@ -42,7 +42,7 @@
NATO-Draht verlegen
Монтировать проволочную спираль
Rozwiń drut kolczasty
- Deploy Concertina wire
+ Desplegar alambre de espino
Deploy Concertina wire
Rozvinout ostnatý drát
Deploy Concertina wire
diff --git a/addons/explosives/stringtable.xml b/addons/explosives/stringtable.xml
index 3227da5dff..7ab3c13fe0 100644
--- a/addons/explosives/stringtable.xml
+++ b/addons/explosives/stringtable.xml
@@ -548,13 +548,18 @@
Explode on defusal?
Explosão no desarmamento?
+ Eksplozja przy rozbrajaniu?
+ Explodovat při zneškodňování?
+ Explotar al desactivar?
Enable certain explosives to explode on defusal? Default: Yes
Ativa certos explosivos para detonar no desarmamento? Padrão: Sim
+ Spraw, aby niektóre ładunki wybuchowe eksplodowały przy próbie ich rozbrojenia? Domyślnie:Tak
+ Umožnit u některých výbušnin explozi při pokusu je zneškodnit? Výchozí: Ano
+ ¿Habilitar ciertos explosivos para estallar al desactivar? Por defecto: Sí
-
Moduł ten pozwala dostosować opcje związane z ładunkami wybuchowymi, ich podkładaniem oraz rozbrajaniem.
Dieses Modul erlaubt die Einstellungen für Sprengstoffe zu verändern.
Tento modul umoňuje přizpůsobit nastavení týkajících se výbušnin.
diff --git a/addons/hearing/CfgWeapons.hpp b/addons/hearing/CfgWeapons.hpp
index 11ad91f658..adcdb2217b 100644
--- a/addons/hearing/CfgWeapons.hpp
+++ b/addons/hearing/CfgWeapons.hpp
@@ -12,4 +12,39 @@ class CfgWeapons {
mass = 1;
};
};
+
+ class H_HelmetB;
+ class H_HelmetCrew_B: H_HelmetB {
+ GVAR(protection) = 1;
+ GVAR(lowerVolume) = 0.80;
+ };
+ class H_HelmetCrew_0: H_HelmetCrew_B {};
+ class H_HelmetCrew_I: H_HelmetCrew_B {};
+
+ class H_CrewHelmetHeli_B: H_HelmetB {
+ GVAR(protection) = 0.75;
+ GVAR(lowerVolume) = 0.70;
+ };
+ class H_CrewHelmetHeli_O: H_CrewHelmetHeli_B {};
+ class H_CrewHelmetHeli_I: H_CrewHelmetHeli_B {};
+
+ class H_PilotHelmetHeli_B: H_HelmetB {
+ GVAR(protection) = 0.75;
+ GVAR(lowerVolume) = 0.70;
+ };
+ class H_PilotHelmetHeli_O: H_PilotHelmetHeli_B {};
+ class H_PilotHelmetHeli_I: H_PilotHelmetHeli_B {};
+
+ class H_PilotHelmetFighter_B: H_HelmetB {
+ GVAR(protection) = 1;
+ GVAR(lowerVolume) = 0.80;
+ };
+ class H_PilotHelmetFighter_O: H_PilotHelmetFighter_B {};
+ class H_PilotHelmetFighter_I: H_PilotHelmetFighter_B {};
+
+ class H_Cap_headphones: H_HelmetB {
+ GVAR(protection) = 0.5;
+ GVAR(lowerVolume) = 0.60;
+ };
+ class H_Cap_marshal: H_Cap_headphones {};
};
diff --git a/addons/hearing/config.cpp b/addons/hearing/config.cpp
index 1007b2095d..5d130e589a 100644
--- a/addons/hearing/config.cpp
+++ b/addons/hearing/config.cpp
@@ -5,7 +5,7 @@ class CfgPatches {
units[] = {};
weapons[] = {"ACE_EarPlugs"};
requiredVersion = REQUIRED_VERSION;
- requiredAddons[] = {"ace_interaction"};
+ requiredAddons[] = {"ace_interaction", "A3_Characters_F", "A3_Characters_F_Kart"};
author[] = {"KoffeinFlummi", "esteldunedain", "HopeJ", "commy2", "Rocko", "Rommel", "Ruthberg"};
authorUrl = "https://github.com/KoffeinFlummi/";
VERSION_CONFIG;
diff --git a/addons/hearing/functions/fnc_addEarPlugs.sqf b/addons/hearing/functions/fnc_addEarPlugs.sqf
index 455de07fd9..62ed4518e2 100644
--- a/addons/hearing/functions/fnc_addEarPlugs.sqf
+++ b/addons/hearing/functions/fnc_addEarPlugs.sqf
@@ -15,9 +15,12 @@
*/
#include "script_component.hpp"
-private ["_unit", "_launcher"];
+PARAMS_1(_unit);
-_unit = _this select 0;
+// Exit if hearing is disabled or soldier has earplugs already in (persistence scenarios)
+if (!GVAR(enableCombatDeafness) || {[_unit] call FUNC(hasEarPlugsIn)}) exitWith {};
+
+private ["_launcher"];
// add earplugs if the soldier has a rocket launcher
_launcher = secondaryWeapon _unit;
diff --git a/addons/hearing/functions/fnc_earRinging.sqf b/addons/hearing/functions/fnc_earRinging.sqf
index 96482f5b79..ce85ac2a22 100644
--- a/addons/hearing/functions/fnc_earRinging.sqf
+++ b/addons/hearing/functions/fnc_earRinging.sqf
@@ -27,6 +27,15 @@ if (_unit getVariable ["ACE_hasEarPlugsin", false]) then {
_strength = _strength / 4;
};
+//headgear hearing protection
+if(headgear _unit != "") then {
+ private ["_protection"];
+ _protection = (getNumber (configFile >> "CfgWeapons" >> (headgear _unit) >> QGVAR(protection))) min 1;
+ if(_protection > 0) then {
+ _strength = _strength * (1 - _protection);
+ };
+};
+
_unit setVariable [QGVAR(dv), (_unit getVariable [QGVAR(dv), 0]) + _strength];
if (GVAR(earRingingPFH) != -1) exitWith {};
@@ -35,8 +44,8 @@ GVAR(earRingingPFH) = [{
EXPLODE_1_PVT(_this select 0,_unit);
private ["_prior"];
_prior = (_unit getvariable [QGVAR(dv), 0]) min 20;
-
- if (!alive _unit || _prior <= 0) exitWith {
+
+ if (!alive _unit || _prior <= 0 || GVAR(DisableEarRinging)) exitWith {
_unit setVariable [QGVAR(dv), 0];
_unit setVariable [QGVAR(prior), 0];
GVAR(beep) = false;
@@ -47,7 +56,7 @@ GVAR(earRingingPFH) = [{
GVAR(earRingingPFH) = -1;
[_this select 1] call cba_fnc_removePerFrameHandler;
};
-
+
if (((_unit getvariable [QGVAR(dv), 0]) - (_unit getvariable [QGVAR(prior), 0])) > 2) then {
if (ACE_time > GVAR(time3)) then {
GVAR(beep2) = false;
@@ -58,16 +67,16 @@ GVAR(earRingingPFH) = [{
GVAR(time3) = ACE_time + 5;
};
};
-
+
_unit setvariable [QGVAR(prior), _prior];
GVAR(volume) = (1 - (_prior / 20)) max 0;
-
+
if (_prior > 19.75) then {
_unit setvariable [QGVAR(deaf), true];
} else {
_unit setvariable [QGVAR(deaf), false];
};
-
+
if ((_unit getvariable [QGVAR(deaf), false]) && {ACE_time > GVAR(time4)}) then {
playSound "ACE_Combat_Deafness";
GVAR(beep2) = true;
@@ -77,7 +86,7 @@ GVAR(earRingingPFH) = [{
// Hearing takes longer to return to normal after it hits rock bottom
_unit setvariable [QGVAR(dv), _prior - (0.5 * (GVAR(volume) max 0.1))];
-
+
if (_prior > 10) then {
//check if the ringing is already being played
if (ACE_time > GVAR(time2)) then {
diff --git a/addons/hearing/functions/fnc_updateVolume.sqf b/addons/hearing/functions/fnc_updateVolume.sqf
index cfec318dc0..5502f38bf4 100644
--- a/addons/hearing/functions/fnc_updateVolume.sqf
+++ b/addons/hearing/functions/fnc_updateVolume.sqf
@@ -46,6 +46,15 @@ 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);
+ };
+};
+
// Reduce volume if player is unconscious
if (ACE_player getVariable ["ACE_isUnconscious", false]) then {
_volume = _volume min GVAR(UnconsciousnessVolume);
diff --git a/addons/huntir/stringtable.xml b/addons/huntir/stringtable.xml
index 79f9a778e1..7e7767f349 100644
--- a/addons/huntir/stringtable.xml
+++ b/addons/huntir/stringtable.xml
@@ -4,7 +4,7 @@
HuntIR Transport Box
HuntIR Transportkiste
- HuntIR Transport Box
+ Caja de transporte de HuntIR
Trasnportní bedna HuntIR
Ящик с HuntIR
HuntIR Transport Box
@@ -16,7 +16,7 @@
HuntIR Round
HuntIR Granate
- HuntIR Round
+ Proyectil HuntIR
HuntIR Round
HuntIR снаряд
HuntIR Round
@@ -28,7 +28,7 @@
HuntIR monitor
HuntIR Monitor
- HuntIR monitor
+ Monitor HuntIR
HuntIR monitor
HuntIR монитор
HuntIR monitor
@@ -40,7 +40,7 @@
Activate HuntIR monitor
HuntIR Monitor aktivieren
- Activate HuntIR monitor
+ Activar monitor HuntIR
Zapnout HuntIR monitor
Включить HuntIR монитор
Activate HuntIR monitor
@@ -52,7 +52,7 @@
Camera:
Kamera:
- Camera:
+ Camara:
Kamera:
Камера:
Camera:
@@ -64,7 +64,7 @@
Altitude:
Höhe:
- Altitude:
+ Altitud:
Výška:
Высота:
Altitude:
@@ -76,7 +76,7 @@
Recording Time:
Aufnahmezeit:
- Recording Time:
+ Tiempo de grabación:
Čas nahrávání:
Время записи:
Recording Time:
@@ -88,7 +88,7 @@
Press ESC to quit camera
Zum Verlassen ESC drücken
- Press ESC to quit camera
+ Pulsar ESC para salir de la camara
Stiskni ESC pro opustění kamery
Нажмите ESC чтобы выйти из режима камеры
Press ESC to quit camera
@@ -100,7 +100,7 @@
Help
Hilfe
- Help
+ Ayuda
Pomoc
Помощь
Help
@@ -112,7 +112,7 @@
A/D - Cycle zoom
A/D - Zoom
- A/D - Cycle zoom
+ A/D - Cambiar zoom
A/D - Změna přiblížení
A/D - Приближение
A/D - Cycle zoom
@@ -124,7 +124,7 @@
W/S - Select camera
W/S - Wähle Kamera
- W/S - Select camera
+ W/S - Seleccionar camara
W/S - Výběr kamery
W/S - Выбрать камеру
W/S - Select camera
@@ -136,7 +136,7 @@
Left/Right - Rotate camera
Links/Rechts - Rotiere Kamera
- Left/Right - Rotate camera
+ Left/Right - Rotar camara
Levá/Pravá - Rotace kamery
Влево/Вправо - Вращать камеру
Left/Right - Rotate camera
@@ -148,7 +148,7 @@
Up/Down - Elevate/lower camera
Hoch/Runter - Neige Kamera
- Up/Down - Elevate/lower camera
+ Up/Down - Subir/bajar camara
Nahoru/Dolu - Zvýšít/snížit úhel pohledu kamery
Вверх/Вниз - Поднять/Опустить камеру
Up/Down - Elevate/lower camera
@@ -160,7 +160,7 @@
N - Cycle IT modes
N - Sichtmodi
- N - Cycle IT modes
+ N - Cambiar modos de IT
N - Změna režimů kamery
N - Режимы камеры
N - Cycle IT modes
@@ -172,7 +172,7 @@
R - Reset camera
R - Reset
- R - Reset camera
+ R - Reiniciar camara
R - Reset kamery
R - Сбросить настройки камеры
R - Reset camera
@@ -184,7 +184,7 @@
Esc - Exit help
ESC - Hilfe verlassen
- Esc - Exit help
+ Esc - Salit de ayuda
Esc - Ukončit pomoc
Esc - Выйти из помощи
Esc - Exit help
diff --git a/addons/interact_menu/ACE_Settings.hpp b/addons/interact_menu/ACE_Settings.hpp
index e9e16f78f1..ea4d4699ed 100644
--- a/addons/interact_menu/ACE_Settings.hpp
+++ b/addons/interact_menu/ACE_Settings.hpp
@@ -76,4 +76,11 @@ class ACE_Settings {
displayName = CSTRING(background);
values[] = {"$STR_A3_OPTIONS_DISABLED", CSTRING(backgroundBlur), CSTRING(backgroundBlack)};
};
+ class GVAR(addBuildingActions) {
+ value = 0;
+ typeName = "BOOL";
+ isClientSettable = 1;
+ displayName = CSTRING(addBuildingActions);
+ description = CSTRING(addBuildingActionsDescription);
+ };
};
diff --git a/addons/interact_menu/XEH_clientInit.sqf b/addons/interact_menu/XEH_clientInit.sqf
index 02bc94688c..cbc28e66b4 100644
--- a/addons/interact_menu/XEH_clientInit.sqf
+++ b/addons/interact_menu/XEH_clientInit.sqf
@@ -3,6 +3,9 @@
if (!hasInterface) exitWith {};
+GVAR(cachedBuildingTypes) = [];
+GVAR(cachedBuildingActionPairs) = [];
+
GVAR(ParsedTextCached) = [];
//Setup text/shadow/size/color settings matrix
@@ -17,6 +20,9 @@ GVAR(ParsedTextCached) = [];
// Install the render EH on the main display
addMissionEventHandler ["Draw3D", DFUNC(render)];
+//Add Actions to Houses:
+["interactMenuOpened", {_this call FUNC(userActions_addHouseActions)}] call EFUNC(common,addEventHandler);
+
// This spawn is probably worth keeping, as pfh don't work natively on the briefing screen and IDK how reliable the hack we implemented for them is.
// The thread dies as soon as the mission start, so it's not really compiting for scheduler space.
[] spawn {
diff --git a/addons/interact_menu/XEH_preInit.sqf b/addons/interact_menu/XEH_preInit.sqf
index 1539f8e2aa..c656ab9056 100644
--- a/addons/interact_menu/XEH_preInit.sqf
+++ b/addons/interact_menu/XEH_preInit.sqf
@@ -25,6 +25,8 @@ PREP(renderMenu);
PREP(renderSelector);
PREP(setupTextColors);
PREP(splitPath);
+PREP(userActions_addHouseActions);
+PREP(userActions_getHouseActions);
// Event handlers for all interact menu controls
DFUNC(handleMouseMovement) = {
diff --git a/addons/interact_menu/config.cpp b/addons/interact_menu/config.cpp
index c1da3392e9..8909c3d685 100644
--- a/addons/interact_menu/config.cpp
+++ b/addons/interact_menu/config.cpp
@@ -21,5 +21,5 @@ class CfgPatches {
#include "ACE_Settings.hpp"
class ACE_Extensions {
- extensions[] += {"ace_break_line"};
+ extensions[] += {"ace_break_line", "ace_parse_imagepath"};
};
diff --git a/addons/interact_menu/functions/fnc_compileMenu.sqf b/addons/interact_menu/functions/fnc_compileMenu.sqf
index 8d68a34268..cf4db7aab1 100644
--- a/addons/interact_menu/functions/fnc_compileMenu.sqf
+++ b/addons/interact_menu/functions/fnc_compileMenu.sqf
@@ -90,7 +90,7 @@ _recurseFnc = {
[],
_position,
_distance,
- [_showDisabled,_enableInside,_canCollapse,_runOnHover],
+ [_showDisabled,_enableInside,_canCollapse,_runOnHover, false],
_modifierFunction
],
_children
diff --git a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf
index 27f841c505..a34c45f504 100644
--- a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf
+++ b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf
@@ -74,7 +74,7 @@ _recurseFnc = {
{},
[0,0,0],
10, //distace
- [_showDisabled,_enableInside,_canCollapse,_runOnHover],
+ [_showDisabled,_enableInside,_canCollapse,_runOnHover, true],
_modifierFunction
],
_children
diff --git a/addons/interact_menu/functions/fnc_createAction.sqf b/addons/interact_menu/functions/fnc_createAction.sqf
index b26cb186f3..6845683044 100644
--- a/addons/interact_menu/functions/fnc_createAction.sqf
+++ b/addons/interact_menu/functions/fnc_createAction.sqf
@@ -68,7 +68,7 @@ _distance = if (count _this > 8) then {
_params = if (count _this > 9) then {
_this select 9
} else {
- [false,false,false,false]
+ [false,false,false,false,false]
};
_modifierFunction = if (count _this > 10) then {
diff --git a/addons/interact_menu/functions/fnc_renderBaseMenu.sqf b/addons/interact_menu/functions/fnc_renderBaseMenu.sqf
index a844930a7c..5330bbebd2 100644
--- a/addons/interact_menu/functions/fnc_renderBaseMenu.sqf
+++ b/addons/interact_menu/functions/fnc_renderBaseMenu.sqf
@@ -44,7 +44,7 @@ if (GVAR(openedMenuType) == 0 && (vehicle ACE_player == ACE_player) && (isNull c
if (_actualDistance > _distance) exitWith {true};
- if (_actualDistance > 1.5) exitWith {
+ if ((_actualDistance > 1.5) && {!((_actionData select 9) select 4)}) exitWith {
// If distance to action is greater than 1.5 m, check LOS
_line = [_headPos call EFUNC(common,positionToASL), _pos call EFUNC(common,positionToASL), _object, ACE_player];
lineIntersects _line
diff --git a/addons/interact_menu/functions/fnc_userActions_addHouseActions.sqf b/addons/interact_menu/functions/fnc_userActions_addHouseActions.sqf
new file mode 100644
index 0000000000..9143db0d4d
--- /dev/null
+++ b/addons/interact_menu/functions/fnc_userActions_addHouseActions.sqf
@@ -0,0 +1,97 @@
+/*
+ * Author: PabstMirror
+ * Scans for nearby "Static" objects (buildings) and adds the UserActions to them.
+ * Called when interact_menu starts rendering (from "interact_keyDown" event)
+ *
+ * Arguments:
+ * 0: Interact Menu Type (0 - world, 1 - self)
+ *
+ * Return Value:
+ * Nothing
+ *
+ * Example:
+ * [0] call ace_interact_menu_fnc_addHouseActions
+ *
+ * Public: Yes
+ */
+#include "script_component.hpp"
+
+PARAMS_1(_interactionType);
+
+//Ignore if not enabled:
+if (!GVAR(addBuildingActions)) exitWith {};
+//Ignore self-interaction menu:
+if (_interactionType != 0) exitWith {};
+//Ignore when mounted:
+if ((vehicle ACE_player) != ACE_player) exitWith {};
+
+[{
+ private ["_nearBuidlings", "_typeOfHouse", "_houseBeingScaned", "_actionSet", "_memPoints", "_memPointsActions", "_helperPos", "_helperObject"];
+ PARAMS_2(_args,_pfID);
+ EXPLODE_4_PVT(_args,_setPosition,_addedHelpers,_housesScaned,_housesToScanForActions);
+
+ if (!EGVAR(interact_menu,keyDown)) then {
+ {deleteVehicle _x;} forEach _addedHelpers;
+ [_pfID] call CBA_fnc_removePerFrameHandler;
+ } else {
+ // Prevent Rare Error when ending mission with interact key down:
+ if (isNull ace_player) exitWith {};
+
+ //Make the common case fast (cursorTarget is looking at a door):
+ if ((!isNull cursorTarget) && {cursorTarget isKindOf "Static"} && {!(cursorTarget in _housesScaned)}) then {
+ if (((count (configFile >> "CfgVehicles" >> (typeOf cursorTarget) >> "UserActions")) > 0) || {(count (getArray (configFile >> "CfgVehicles" >> (typeOf cursorTarget) >> "ladders"))) > 0}) then {
+ _housesToScanForActions = [cursorTarget];
+ } else {
+ _housesScaned pushBack cursorTarget;
+ };
+ };
+
+ //For performance, we only do 1 thing per frame,
+ //-either do a wide scan and search for houses with actions
+ //-or scan one house at a time and add the actions for that house
+
+ if (_housesToScanForActions isEqualTo []) then {
+ //If player moved >2 meters from last pos, then rescan
+ if (((getPosASL ace_player) distance _setPosition) < 2) exitWith {};
+
+ _nearBuidlings = nearestObjects [ace_player, ["Static"], 30];
+ {
+ _typeOfHouse = typeOf _x;
+ if (((count (configFile >> "CfgVehicles" >> _typeOfHouse >> "UserActions")) == 0) && {(count (getArray (configFile >> "CfgVehicles" >> _typeOfHouse >> "ladders"))) == 0}) then {
+ _housesScaned pushBack _x;
+ } else {
+ _housesToScanForActions pushBack _x;
+ };
+ } forEach (_nearBuidlings - _housesScaned);
+
+ _args set [0, (getPosASL ace_player)];
+ } else {
+ _houseBeingScaned = _housesToScanForActions deleteAt 0;
+ _typeOfHouse = typeOf _houseBeingScaned;
+ //Skip this house for now if we are outside of it's radius
+ //(we have to scan far out for the big houses, but we don't want to waste time adding actions on every little shack)
+ if ((_houseBeingScaned != cursorTarget) && {((ACE_player distance _houseBeingScaned) - ((sizeOf _typeOfHouse) / 2)) > 4}) exitWith {};
+
+ _housesScaned pushBack _houseBeingScaned;
+
+ _actionSet = [_typeOfHouse] call FUNC(userActions_getHouseActions);
+ EXPLODE_2_PVT(_actionSet,_memPoints,_memPointsActions);
+
+ // systemChat format ["Add Actions for [%1] (count %2) @ %3", _typeOfHouse, (count _memPoints), diag_tickTime];
+ {
+ _helperPos = (_houseBeingScaned modelToWorld (_houseBeingScaned selectionPosition _x)) call EFUNC(common,positionToASL);
+ _helperObject = "Sign_Sphere25cm_F" createVehicleLocal _helperPos;
+ _addedHelpers pushBack _helperObject;
+ _helperObject setVariable [QGVAR(building), _houseBeingScaned];
+ _helperObject setPosASL _helperPos;
+ _helperObject hideObject true;
+ TRACE_3("Making New Helper",_helperObject,_x,_houseBeingScaned);
+
+ {
+ [_helperObject, 0, [], _x] call EFUNC(interact_menu,addActionToObject);
+ } forEach (_memPointsActions select _forEachIndex);
+
+ } forEach _memPoints;
+ };
+ };
+}, 0, [((getPosASL ace_player) vectorAdd [-100,0,0]), [], [], []]] call CBA_fnc_addPerFrameHandler;
diff --git a/addons/interact_menu/functions/fnc_userActions_getHouseActions.sqf b/addons/interact_menu/functions/fnc_userActions_getHouseActions.sqf
new file mode 100644
index 0000000000..0b3d4347c7
--- /dev/null
+++ b/addons/interact_menu/functions/fnc_userActions_getHouseActions.sqf
@@ -0,0 +1,137 @@
+/*
+ * Author: PabstMirror
+ * Scans the buidling type for UserActions and Ladder mount points.
+ *
+ * Arguments:
+ * 0: Building Classname
+ *
+ * Return Value:
+ * [[Array of MemPoints], [Array Of Actions]]
+ *
+ * Public: Yes
+ */
+#include "script_component.hpp"
+
+PARAMS_1(_typeOfBuilding);
+
+private["_action", "_actionDisplayName", "_actionDisplayNameDefault", "_actionMaxDistance", "_actionOffset", "_actionPath", "_actionPosition", "_building", "_configPath", "_endIndex", "_iconImage", "_index", "_ladders", "_memPointIndex", "_memPoints", "_memPointsActions", "_startIndex"];
+
+_searchIndex = GVAR(cachedBuildingTypes) find _typeOfBuilding;
+if (_searchIndex != -1) exitWith {GVAR(cachedBuildingActionPairs) select _searchIndex};
+
+_memPoints = [];
+_memPointsActions = [];
+
+//Get the offset for a memory point:
+_fnc_getMemPointOffset = {
+ PARAMS_1(_memoryPoint);
+ _memPointIndex = _memPoints find _memoryPoint;
+ _actionOffset = [0,0,0];
+ if (_memPointIndex == -1) then {
+ _memPoints pushBack _memoryPoint;
+ _memPointsActions pushBack [];
+ } else {
+ _actionOffset set [2, 0.0254 * (count (_memPointsActions select _memPointIndex))];
+ };
+ _actionOffset
+};
+
+// Add UserActions for the building:
+_fnc_userAction_Statement = {
+ PARAMS_3(_target,_player,_variable);
+ EXPLODE_2_PVT(_variable,_actionStatement,_actionCondition);
+ this = _target getVariable [QGVAR(building), objNull];
+ call _actionStatement;
+};
+_fnc_userAction_Condition = {
+ PARAMS_3(_target,_player,_variable);
+ EXPLODE_2_PVT(_variable,_actionStatement,_actionCondition);
+ this = _target getVariable [QGVAR(building), objNull];
+ if (isNull this) exitWith {false};
+ call _actionCondition;
+};
+
+_configPath = configFile >> "CfgVehicles" >> _typeOfBuilding >> "UserActions";
+for "_index" from 0 to ((count _configPath) - 1) do {
+ _actionPath = _configPath select _index;
+
+ _actionDisplayName = getText (_actionPath >> "displayName");
+ _actionDisplayNameDefault = getText (_actionPath >> "displayNameDefault");
+ _actionPosition = getText (_actionPath >> "position");
+ _actionCondition = getText (_actionPath >> "condition");
+ _actionStatement = getText (_actionPath >> "statement");
+ _actionMaxDistance = getNumber (_actionPath >> "radius");
+
+ if (_actionDisplayName == "") then {_actionDisplayName = (configName _x);};
+ if (_actionPosition == "") then {ERROR("Bad Position");};
+ if (_actionCondition == "") then {_actionCondition = "true";};
+ if (_actionStatement == "") then {ERROR("No Statement");};
+
+ _actionStatement = compile _actionStatement;
+ _actionCondition = compile _actionCondition;
+ _actionMaxDistance = _actionMaxDistance + 0.1; //increase range slightly
+ _iconImage = "";
+
+ //extension ~4x as fast:
+ _iconImage = "ace_parse_imagepath" callExtension _actionDisplayNameDefault;
+
+ _actionOffset = [_actionPosition] call _fnc_getMemPointOffset;
+ _memPointIndex = _memPoints find _actionPosition;
+
+ _action = [(configName _actionPath), _actionDisplayName, _iconImage, _fnc_userAction_Statement, _fnc_userAction_Condition, {}, [_actionStatement, _actionCondition], _actionOffset, _actionMaxDistance, [false,false,false,false,true]] call EFUNC(interact_menu,createAction);
+ (_memPointsActions select _memPointIndex) pushBack _action;
+};
+
+// Add Ladder Actions for the building:
+_fnc_ladder_ladderUp = {
+ PARAMS_3(_target,_player,_variable);
+ EXPLODE_1_PVT(_variable,_ladderIndex);
+ _building = _target getVariable [QGVAR(building), objNull];
+ TRACE_3("Ladder Action - UP",_player,_building,_ladderIndex);
+ _player action ["LadderUp", _building, _ladderIndex, 0];
+};
+_fnc_ladder_ladderDown = {
+ PARAMS_3(_target,_player,_variable);
+ EXPLODE_1_PVT(_variable,_ladderIndex);
+ _building = _target getVariable [QGVAR(building), objNull];
+ TRACE_3("Ladder Action - Down",_player,_building,_ladderIndex);
+ _player action ["LadderDown", _building, _ladderIndex, 1];
+};
+
+_fnc_ladder_conditional = {
+ PARAMS_2(_target,_player);
+ //(Check distance < 2) and (Don't show actions if on a ladder)
+ ((_target distance _player) < 2) && {((getNumber (configFile >> "CfgMovesMaleSdr" >> "States" >> (animationState _player) >> "onLadder")) == 0)}
+};
+
+_ladders = getArray (configFile >> "CfgVehicles" >> _typeOfBuilding >> "ladders");
+{
+ EXPLODE_2_PVT(_x,_ladderBottomMemPoint,_ladderTopMemPoint);
+
+ _actionMaxDistance = 3; //interact_menu will check head -> target's offset; leave this high and do a precice distance check in condition
+
+ _actionDisplayName = localize "str_action_ladderup";
+ _iconImage = "\A3\ui_f\data\igui\cfg\actions\ladderup_ca.paa";
+ //Ladder Up Action:
+ _actionOffset = [_ladderBottomMemPoint] call _fnc_getMemPointOffset;
+ _actionOffset = _actionOffset vectorAdd [0,0,1];
+ _memPointIndex = _memPoints find _ladderBottomMemPoint;
+ _action = [format ["LadderUp_%1", _forEachIndex], _actionDisplayName, _iconImage, _fnc_ladder_ladderUp, _fnc_ladder_conditional, {}, [_forEachIndex], _actionOffset, _actionMaxDistance, [false,false,false,false,true]] call EFUNC(interact_menu,createAction);
+ (_memPointsActions select _memPointIndex) pushBack _action;
+
+ _actionDisplayName = localize "str_action_ladderdown";
+ _iconImage = "\A3\ui_f\data\igui\cfg\actions\ladderdown_ca.paa";
+ //Ladder Down Action:
+ _actionOffset = [_ladderTopMemPoint] call _fnc_getMemPointOffset;
+ _actionOffset = _actionOffset vectorAdd [0,0,0.25];
+ _memPointIndex = _memPoints find _ladderTopMemPoint;
+ _action = [format ["LadderDown_%1", _forEachIndex], _actionDisplayName, _iconImage, _fnc_ladder_ladderDown, _fnc_ladder_conditional, {}, [_forEachIndex], _actionOffset, _actionMaxDistance, [false,false,false,false,true]] call EFUNC(interact_menu,createAction);
+ (_memPointsActions select _memPointIndex) pushBack _action;
+
+} forEach _ladders;
+
+GVAR(cachedBuildingTypes) pushBack _typeOfBuilding;
+GVAR(cachedBuildingActionPairs) pushBack [_memPoints, _memPointsActions];
+
+
+[_memPoints, _memPointsActions]
diff --git a/addons/interact_menu/stringtable.xml b/addons/interact_menu/stringtable.xml
index 054f17512c..5ab782803d 100644
--- a/addons/interact_menu/stringtable.xml
+++ b/addons/interact_menu/stringtable.xml
@@ -87,6 +87,9 @@
+
+ Open
+ Otwórz
+ Otevřít
+ Abrir
+
Interaction System
System interakcji
@@ -823,18 +829,7 @@
Die Gruppenverwaltung erlaubt die Zuweisung von Farben für Einheiten, die Kommandierung und das Beitreten/Verlassen einer Gruppe.
Správa týmu se skládá z: přidělení barev pro členy týmu, převzetí velení, připojení/odpojení.
O módulo de gestão de equipe é composto por: a atribuição de cores para os membros da equipe, comando das equipes, juntando-se / deixando equipes.
-
-
- Behaviour
-
-
- Careless
-
-
- Formation
-
-
- Speed Mode
+ La gestión del equipo permite la asignación de colores para los miembros del equipo, tomando el mando del equipo y uniendo/dejando equipos.
-
+
\ No newline at end of file
diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp
index 1fb4a0b622..ae1e1cb685 100644
--- a/addons/main/script_macros.hpp
+++ b/addons/main/script_macros.hpp
@@ -25,7 +25,7 @@
#ifndef STRING_MACROS_GUARD
#define STRING_MACROS_GUARD
#define LSTRING(var1) QUOTE(TRIPLES(STR,ADDON,var1))
- #define LESTRING(var1,var2) QUOTE(TRIPLES(STR,DOUBLES(PREFIX,var1),var2))
+ #define ELSTRING(var1,var2) QUOTE(TRIPLES(STR,DOUBLES(PREFIX,var1),var2))
#define CSTRING(var1) QUOTE(TRIPLES($STR,ADDON,var1))
#define ECSTRING(var1,var2) QUOTE(TRIPLES($STR,DOUBLES(PREFIX,var1),var2))
#endif
diff --git a/addons/map/XEH_postInitClient.sqf b/addons/map/XEH_postInitClient.sqf
index a3f377544b..52c904b1ce 100644
--- a/addons/map/XEH_postInitClient.sqf
+++ b/addons/map/XEH_postInitClient.sqf
@@ -18,7 +18,30 @@ call FUNC(determineZoom);
GVAR(lastStillTime) = ACE_time;
GVAR(isShaking) = false;
+ //Allow panning the lastStillPosition while mapShake is active
+ GVAR(rightMouseButtonLastPos) = [];
((findDisplay 12) displayCtrl 51) ctrlAddEventHandler ["Draw", {[] call FUNC(updateMapEffects);}];
+ ((findDisplay 12) displayCtrl 51) ctrlAddEventHandler ["MouseMoving", {
+ if (GVAR(isShaking) && {(count GVAR(rightMouseButtonLastPos)) == 2}) then {
+ private["_lastPos", "_newPos"];
+ _lastPos = (_this select 0) ctrlMapScreenToWorld GVAR(rightMouseButtonLastPos);
+ _newPos = (_this select 0) ctrlMapScreenToWorld (_this select [1,2]);
+ GVAR(lastStillPosition) set [0, (GVAR(lastStillPosition) select 0) + (_lastPos select 0) - (_newPos select 0)];
+ GVAR(lastStillPosition) set [1, (GVAR(lastStillPosition) select 1) + (_lastPos select 1) - (_newPos select 1)];
+ GVAR(rightMouseButtonLastPos) = _this select [1,2];
+ TRACE_3("Mouse Move",_lastPos,_newPos,GVAR(rightMouseButtonLastPos));
+ };
+ }];
+ ((findDisplay 12) displayCtrl 51) ctrlAddEventHandler ["MouseButtonDown", {
+ if ((_this select 1) == 1) then {
+ GVAR(rightMouseButtonLastPos) = _this select [2,2];
+ };
+ }];
+ ((findDisplay 12) displayCtrl 51) ctrlAddEventHandler ["MouseButtonUp", {
+ if ((_this select 1) == 1) then {
+ GVAR(rightMouseButtonLastPos) = [];
+ };
+ }];
};
["SettingsInitialized", {
diff --git a/addons/map/stringtable.xml b/addons/map/stringtable.xml
index 8e3ae52da5..9b7627e66e 100644
--- a/addons/map/stringtable.xml
+++ b/addons/map/stringtable.xml
@@ -74,7 +74,6 @@
Mostrar as coordenadas de grade no ponteiro do mouse?
-
Moduł ten pozwala dostosować opcje widoku ekranu mapy.
Dieses Modul erweitert die Kartenfunktionen.
Tento modul umožňuje přizpůsobit mapu s obrazem.
@@ -83,7 +82,7 @@
Blue Force Tracking
Blue Force Tracking
- Seguimiento de fuerzas amigas
+ Blue Force Tracking
Blue Force Tracking
Blue Force Tracking
Rastreio de forças azuis
@@ -91,10 +90,16 @@
BFT Enable
RFA ativo
+ Aktywuj BFT
+ Povolit BFT
+ Activar BFT
Enable Blue Force Tracking. Default: No
Ativa Rastreio de Forças Azuis. Padrão: Não
+ Aktywuj Blue Force Tracking. Domyślnie: Nie
+ Povolit Blue Force Tracking. Výchozí: Ne
+ Activar Blue Force Tracking. Por defecto: No
Interval
@@ -129,7 +134,6 @@
Esconder marcadores que pertencem ao grupo de IA?
-
Pozwala śledzić na mapie pozycje sojuszniczych jednostek za pomocą markerów BFT.
Dieses Modul ermöglicht es verbündete Einheiten mit dem BFT auf der Karte zu verfolgen.
Umožňuje sledovat přátelské jednokty na mapě v rámci BFT.
diff --git a/addons/medical/ACE_Medical_Treatments.hpp b/addons/medical/ACE_Medical_Treatments.hpp
index 8eacf39006..079ae40506 100644
--- a/addons/medical/ACE_Medical_Treatments.hpp
+++ b/addons/medical/ACE_Medical_Treatments.hpp
@@ -11,6 +11,7 @@ class ACE_Medical_Actions {
treatmentTimeSelfCoef = 1;
items[] = {{"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_quikclot"}};
condition = "";
+ patientStateCondition = 0;
itemConsumed = 1;
callbackSuccess = QUOTE(DFUNC(treatmentBasic_bandage));
@@ -107,6 +108,7 @@ class ACE_Medical_Actions {
// Item required for the action. Leave empty for no item required.
items[] = {"ACE_fieldDressing"};
condition = "";
+ patientStateCondition = 0;
// Callbacks
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_bandage));
callbackFailure = "";
@@ -206,6 +208,7 @@ class ACE_Medical_Actions {
items[] = {"ACE_surgicalKit"};
treatmentLocations[] = {QGVAR(useLocation_SurgicalKit)};
requiredMedic = QGVAR(medicSetting_SurgicalKit);
+ patientStateCondition = QGVAR(useCondition_SurgicalKit);
treatmentTime = "(count ((_this select 1) getVariable ['ACE_Medical_bandagedWounds', []]) * 5)";
callbackSuccess = "";
callbackProgress = QUOTE(DFUNC(treatmentAdvanced_surgicalKit_onProgress));
@@ -219,6 +222,7 @@ class ACE_Medical_Actions {
items[] = {"ACE_personalAidKit"};
treatmentLocations[] = {QGVAR(useLocation_PAK)};
requiredMedic = QGVAR(medicSetting_PAK);
+ patientStateCondition = QGVAR(useCondition_PAK);
treatmentTime = QUOTE((_this select 1) call FUNC(treatmentAdvanced_fullHealTreatmentTime));
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_fullHeal));
itemConsumed = QGVAR(consumeItem_PAK);
@@ -266,10 +270,10 @@ class ACE_Medical_Actions {
requiredMedic = 0;
treatmentTime = 15;
items[] = {};
- condition = "((_this select 1) getvariable ['ACE_medical_inCardiacArrest', false])";
+ condition = "!([(_this select 1)] call ace_common_fnc_isAwake)";
callbackSuccess = QUOTE(DFUNC(treatmentAdvanced_CPR));
callbackFailure = "";
- callbackProgress = "(((_this select 0) select 1) getvariable ['ACE_medical_inCardiacArrest', false])";
+ callbackProgress = "!([((_this select 0) select 1)] call ace_common_fnc_isAwake)";
animationPatient = "";
animationPatientUnconscious = "AinjPpneMstpSnonWrflDnon_rolltoback";
animationCaller = "AinvPknlMstpSlayWnonDnon_medic";
diff --git a/addons/medical/ACE_Settings.hpp b/addons/medical/ACE_Settings.hpp
index 2b28e91882..fcaba03aa0 100644
--- a/addons/medical/ACE_Settings.hpp
+++ b/addons/medical/ACE_Settings.hpp
@@ -133,6 +133,20 @@ class ACE_Settings {
value = 2;
values[] = {"Anywhere", "Medical vehicles", "Medical facility", "vehicle & facility", "Disabled"};
};
+ class GVAR(useCondition_PAK) {
+ displayName = CSTRING(AdvancedMedicalSettings_useCondition_PAK_DisplayName);
+ description = CSTRING(AdvancedMedicalSettings_useCondition_PAK_Description);
+ typeName = "SCALAR";
+ value = 0;
+ values[] = {"Anytime", "Stable"};
+ };
+ class GVAR(useCondition_SurgicalKit) {
+ displayName = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_DisplayName);
+ description = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_Description);
+ typeName = "SCALAR";
+ value = 0;
+ values[] = {"Anytime", "Stable"};
+ };
class GVAR(keepLocalSettingsSynced) {
typeName = "BOOL";
value = 1;
diff --git a/addons/medical/CfgVehicles.hpp b/addons/medical/CfgVehicles.hpp
index c8a4528ca5..66df5550fc 100644
--- a/addons/medical/CfgVehicles.hpp
+++ b/addons/medical/CfgVehicles.hpp
@@ -196,13 +196,21 @@ class CfgVehicles {
class consumeItem_PAK {
displayName = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_consumeItem_PAK_Description);
-
typeName = "NUMBER";
class values {
class keep { name = CSTRING(No); value = 0; };
class remove { name = CSTRING(Yes); value = 1; default = 1; };
};
};
+ class useCondition_PAK {
+ displayName = CSTRING(AdvancedMedicalSettings_useCondition_PAK_DisplayName);
+ description = CSTRING(AdvancedMedicalSettings_useCondition_PAK_Description);
+ typeName = "NUMBER";
+ class values {
+ class AnyTime { name = CSTRING(AnyTime); value = 0; };
+ class Stable { name = CSTRING(Stable); value = 1; default = 1; };
+ };
+ };
class useLocation_PAK {
displayName = CSTRING(AdvancedMedicalSettings_useLocation_PAK_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useLocation_PAK_Description);
@@ -227,15 +235,23 @@ class CfgVehicles {
displayName = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName);
description = CSTRING(AdvancedMedicalSettings_useLocation_SurgicalKit_Description);
};
+ class useCondition_SurgicalKit: useCondition_PAK {
+ displayName = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_DisplayName);
+ description = CSTRING(AdvancedMedicalSettings_useCondition_SurgicalKit_Description);
+ class values {
+ class AnyTime { name = CSTRING(AnyTime); value = 0; default = 1; };
+ class Stable { name = CSTRING(Stable); value = 1; };
+ };
+ };
class healHitPointAfterAdvBandage {
displayName = CSTRING(AdvancedMedicalSettings_healHitPointAfterAdvBandage_DisplayName);
- description = CSTRING(AdvancedMedicalSettings_healHitPointAfterAdvBandage_Description);
+ description = CSTRING(AdvancedMedicalSettings_healHitPointAfterAdvBandage_Description);
typeName = "BOOL";
defaultValue = 0;
};
class painIsOnlySuppressed {
displayName = CSTRING(AdvancedMedicalSettings_painIsOnlySuppressed_DisplayName);
- description = CSTRING(AdvancedMedicalSettings_painIsOnlySuppressed_Description);
+ description = CSTRING(AdvancedMedicalSettings_painIsOnlySuppressed_Description);
typeName = "BOOL";
defaultValue = 1;
};
diff --git a/addons/medical/XEH_postInit.sqf b/addons/medical/XEH_postInit.sqf
index 0b51f57165..f9f821eeb3 100644
--- a/addons/medical/XEH_postInit.sqf
+++ b/addons/medical/XEH_postInit.sqf
@@ -92,7 +92,7 @@ GVAR(effectTimeBlood) = ACE_time;
[{
private["_bleeding", "_blood"];
// Zeus interface is open or player is dead; disable everything
- if (!(isNull (findDisplay 312)) or !(alive ACE_player)) exitWith {
+ if (!(isNull curatorCamera) or !(alive ACE_player)) exitWith {
GVAR(effectUnconsciousCC) ppEffectEnable false;
GVAR(effectUnconsciousRB) ppEffectEnable false;
GVAR(effectBlindingCC) ppEffectEnable false;
@@ -174,52 +174,54 @@ GVAR(lastHeartBeatSound) = ACE_time;
if ((ACE_time > GVAR(lastHeartBeat) + _interval)) then {
GVAR(lastHeartBeat) = ACE_time;
- // Pain effect
- _strength = (_pain - (ACE_player getvariable [QGVAR(painSuppress), 0])) max 0;
- _strength = _strength * (ACE_player getVariable [QGVAR(painCoefficient), GVAR(painCoefficient)]);
- if (GVAR(painEffectType) == 1) then {
- GVAR(effectPainCC) ppEffectEnable false;
- if (_pain > (ACE_player getvariable [QGVAR(painSuppress), 0]) && {alive ACE_player}) then {
- _strength = _strength * 0.15;
- GVAR(effectPainCA) ppEffectEnable true;
- GVAR(effectPainCA) ppEffectAdjust [_strength, _strength, false];
- GVAR(effectPainCA) ppEffectCommit 0.01;
- [{
- GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
- GVAR(effectPainCA) ppEffectCommit (_this select 1);
- }, [_strength * 0.1, _interval * 0.2], _interval * 0.05, 0] call EFUNC(common,waitAndExecute);
- [{
- GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
+ // Pain effect, no pain effect in zeus camera
+ if (isNull curatorCamera) then {
+ _strength = (_pain - (ACE_player getvariable [QGVAR(painSuppress), 0])) max 0;
+ _strength = _strength * (ACE_player getVariable [QGVAR(painCoefficient), GVAR(painCoefficient)]);
+ if (GVAR(painEffectType) == 1) then {
+ GVAR(effectPainCC) ppEffectEnable false;
+ if (_pain > (ACE_player getvariable [QGVAR(painSuppress), 0]) && {alive ACE_player}) then {
+ _strength = _strength * 0.15;
+ GVAR(effectPainCA) ppEffectEnable true;
+ GVAR(effectPainCA) ppEffectAdjust [_strength, _strength, false];
GVAR(effectPainCA) ppEffectCommit 0.01;
- }, [_strength * 0.7], _interval * 0.3, 0] call EFUNC(common,waitAndExecute);
- [{
- GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
- GVAR(effectPainCA) ppEffectCommit (_this select 1);
- }, [_strength * 0.1, _interval * 0.55], _interval * 0.4, 0] call EFUNC(common,waitAndExecute);
+ [{
+ GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
+ GVAR(effectPainCA) ppEffectCommit (_this select 1);
+ }, [_strength * 0.1, _interval * 0.2], _interval * 0.05, 0] call EFUNC(common,waitAndExecute);
+ [{
+ GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
+ GVAR(effectPainCA) ppEffectCommit 0.01;
+ }, [_strength * 0.7], _interval * 0.3, 0] call EFUNC(common,waitAndExecute);
+ [{
+ GVAR(effectPainCA) ppEffectAdjust [(_this select 0), (_this select 0), false];
+ GVAR(effectPainCA) ppEffectCommit (_this select 1);
+ }, [_strength * 0.1, _interval * 0.55], _interval * 0.4, 0] call EFUNC(common,waitAndExecute);
+ } else {
+ GVAR(effectPainCA) ppEffectEnable false;
+ };
} else {
GVAR(effectPainCA) ppEffectEnable false;
- };
- } else {
- GVAR(effectPainCA) ppEffectEnable false;
- if (_pain > (ACE_player getvariable [QGVAR(painSuppress), 0]) && {alive ACE_player}) then {
- _strength = _strength * 0.9;
- GVAR(effectPainCC) ppEffectEnable true;
- GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - _strength,1 - _strength,0,0,0,0.2,2]];
- GVAR(effectPainCC) ppEffectCommit 0.01;
- [{
- GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
- GVAR(effectPainCC) ppEffectCommit (_this select 1);
- }, [_strength * 0.1, _interval * 0.2], _interval * 0.05, 0] call EFUNC(common,waitAndExecute);
- [{
- GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
+ if (_pain > (ACE_player getvariable [QGVAR(painSuppress), 0]) && {alive ACE_player}) then {
+ _strength = _strength * 0.9;
+ GVAR(effectPainCC) ppEffectEnable true;
+ GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - _strength,1 - _strength,0,0,0,0.2,2]];
GVAR(effectPainCC) ppEffectCommit 0.01;
- }, [_strength * 0.7], _interval * 0.3, 0] call EFUNC(common,waitAndExecute);
- [{
- GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
- GVAR(effectPainCC) ppEffectCommit (_this select 1);
- }, [_strength * 0.1, _interval * 0.55], _interval * 0.4, 0] call EFUNC(common,waitAndExecute);
- } else {
- GVAR(effectPainCC) ppEffectEnable false;
+ [{
+ GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
+ GVAR(effectPainCC) ppEffectCommit (_this select 1);
+ }, [_strength * 0.1, _interval * 0.2], _interval * 0.05, 0] call EFUNC(common,waitAndExecute);
+ [{
+ GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
+ GVAR(effectPainCC) ppEffectCommit 0.01;
+ }, [_strength * 0.7], _interval * 0.3, 0] call EFUNC(common,waitAndExecute);
+ [{
+ GVAR(effectPainCC) ppEffectAdjust [1,1,0, [1,1,1,1], [0,0,0,0], [1,1,1,1], [1 - (_this select 0),1 - (_this select 0),0,0,0,0.2,2]];
+ GVAR(effectPainCC) ppEffectCommit (_this select 1);
+ }, [_strength * 0.1, _interval * 0.55], _interval * 0.4, 0] call EFUNC(common,waitAndExecute);
+ } else {
+ GVAR(effectPainCC) ppEffectEnable false;
+ };
};
};
};
diff --git a/addons/medical/XEH_preInit.sqf b/addons/medical/XEH_preInit.sqf
index a932ee5c9d..b479383468 100644
--- a/addons/medical/XEH_preInit.sqf
+++ b/addons/medical/XEH_preInit.sqf
@@ -56,6 +56,7 @@ PREP(isInMedicalFacility);
PREP(isInMedicalVehicle);
PREP(isMedic);
PREP(isMedicalVehicle);
+PREP(isInStableCondition);
PREP(itemCheck);
PREP(modifyMedicalAction);
PREP(onMedicationUsage);
diff --git a/addons/medical/functions/fnc_canTreat.sqf b/addons/medical/functions/fnc_canTreat.sqf
index 062a696fcd..4795ccc561 100644
--- a/addons/medical/functions/fnc_canTreat.sqf
+++ b/addons/medical/functions/fnc_canTreat.sqf
@@ -16,7 +16,7 @@
#include "script_component.hpp"
-private ["_caller", "_target", "_selectionName", "_className", "_config", "_medicRequired", "_items", "_locations", "_return", "_condition"];
+private ["_caller", "_target", "_selectionName", "_className", "_config", "_medicRequired", "_items", "_locations", "_return", "_condition", "_patientStateCondition"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
@@ -44,7 +44,6 @@ if !([_caller, _medicRequired] call FUNC(isMedic)) exitwith {false};
_items = getArray (_config >> "items");
if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exitwith {false};
-_locations = getArray (_config >> "treatmentLocations");
_return = true;
if (getText (_config >> "condition") != "") then {
@@ -62,6 +61,14 @@ if (getText (_config >> "condition") != "") then {
};
if (!_return) exitwith {false};
+_patientStateCondition = if (isText(_config >> "patientStateCondition")) then {
+ missionNamespace getvariable [getText(_config >> "patientStateCondition"), 0]
+} else {
+ getNumber(_config >> "patientStateCondition")
+};
+if (_patientStateCondition == 1 && {!([_target] call FUNC(isInStableCondition))}) exitwith {false};
+
+_locations = getArray (_config >> "treatmentLocations");
if ("All" in _locations) exitwith {true};
private [ "_medFacility", "_medVeh"];
diff --git a/addons/medical/functions/fnc_getUnconsciousCondition.sqf b/addons/medical/functions/fnc_getUnconsciousCondition.sqf
index 83955f7bd1..19d3bdec1d 100644
--- a/addons/medical/functions/fnc_getUnconsciousCondition.sqf
+++ b/addons/medical/functions/fnc_getUnconsciousCondition.sqf
@@ -16,7 +16,6 @@
private ["_unit","_return"];
_unit = _this select 0;
-if (GVAR(level) == 1) exitwith {true};
if (isnil QGVAR(unconsciousConditions)) then {
GVAR(unconsciousConditions) = [];
};
diff --git a/addons/medical/functions/fnc_handleBandageOpening.sqf b/addons/medical/functions/fnc_handleBandageOpening.sqf
index a92bf9029c..a86077cb3b 100644
--- a/addons/medical/functions/fnc_handleBandageOpening.sqf
+++ b/addons/medical/functions/fnc_handleBandageOpening.sqf
@@ -58,10 +58,10 @@ if (isClass (_config >> _className)) then {
_bandagedWounds = _target getvariable [QGVAR(bandagedWounds), []];
_exist = false;
-_injuryId = _injury select 0;
+_injuryType = _injury select 1;
_bandagedInjury = [];
{
- if ((_x select 0) == _injuryId) exitwith {
+ if ((_x select 1) == _injuryType && (_x select 2) == (_injury select 2)) exitwith {
_exist = true;
_existingInjury = _x;
_existingInjury set [3, (_existingInjury select 3) + _impact];
@@ -73,16 +73,11 @@ _bandagedInjury = [];
if !(_exist) then {
// [ID, classID, bodypart, percentage treated, bloodloss rate]
- _bandagedInjury = [_injuryId, _injury select 1, _injury select 2, _impact, _injury select 4];
+ _bandagedInjury = [_injury select 0, _injury select 1, _injury select 2, _impact, _injury select 4];
_bandagedWounds pushback _bandagedInjury;
};
-_target setvariable [QGVAR(bandagedWounds), _bandagedWounds, !USE_WOUND_EVENT_SYNC];
-
-if (USE_WOUND_EVENT_SYNC) then {
- // sync _bandagedInjury
-
-};
+_target setvariable [QGVAR(bandagedWounds), _bandagedWounds, true];
// Check if we are ever going to reopen this
if (random(1) <= _reopeningChance) then {
@@ -95,22 +90,19 @@ if (random(1) <= _reopeningChance) then {
_injuryIndex = _this select 3;
_injury = _this select 4;
- if (alive _target) then {
+ //if (alive _target) then {
_openWounds = _target getvariable [QGVAR(openWounds), []];
if ((count _openWounds)-1 < _injuryIndex) exitwith {};
_selectedInjury = _openWounds select _injuryIndex;
- if (_selectedInjury select 0 == _injury select 0) then { // matching the IDs
+ if (_selectedInjury select 1 == _injury select 1 && (_selectedInjury select 2) == (_injury select 2)) then { // matching the IDs
_selectedInjury set [3, (_selectedInjury select 3) + _impact];
_openWounds set [_injuryIndex, _selectedInjury];
- _target setvariable [QGVAR(openWounds), _openWounds, !USE_WOUND_EVENT_SYNC];
- if (USE_WOUND_EVENT_SYNC) then {
- ["medical_propagateWound", [_target, _selectedInjury]] call EFUNC(common,globalEvent);
- };
+
_bandagedWounds = _target getvariable [QGVAR(bandagedWounds), []];
_exist = false;
- _injuryId = _injury select 0;
+ _injuryId = _injury select 1;
{
- if ((_x select 0) == _injuryId) exitwith {
+ if ((_x select 1) == _injuryId && (_x select 2) == (_injury select 2)) exitwith {
_exist = true;
_existingInjury = _x;
_existingInjury set [3, ((_existingInjury select 3) - _impact) max 0];
@@ -119,10 +111,11 @@ if (random(1) <= _reopeningChance) then {
}foreach _bandagedWounds;
if (_exist) then {
- _target setvariable [QGVAR(bandagedWounds), _bandagedWounds, !USE_WOUND_EVENT_SYNC];
+ _target setvariable [QGVAR(bandagedWounds), _bandagedWounds, true];
+ _target setvariable [QGVAR(openWounds), _openWounds, true];
};
};
// Otherwise something went wrong, we we don't reopen them..
- };
- }, [_target, _impact, _part, _injuryIndex, _injury], _delay, 0] call EFUNC(common,waitAndExecute);
+ //};
+ }, [_target, _impact, _part, _injuryIndex, +_injury], _delay, 0] call EFUNC(common,waitAndExecute);
};
diff --git a/addons/medical/functions/fnc_handleDamage.sqf b/addons/medical/functions/fnc_handleDamage.sqf
index ab6e6f2a68..aad69ee2fa 100644
--- a/addons/medical/functions/fnc_handleDamage.sqf
+++ b/addons/medical/functions/fnc_handleDamage.sqf
@@ -80,10 +80,10 @@ if (GVAR(level) < 2) then {
} else {
_damageReturn = _damageReturn min 0.89;
};
+
};
[_unit] call FUNC(addToInjuredCollection);
-
if (_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)]) exitWith {
if (vehicle _unit != _unit and {damage (vehicle _unit) >= 1}) then {
[_unit] call EFUNC(common,unloadPerson);
@@ -99,7 +99,7 @@ if (_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)]) exitW
if (_damageReturn >= 0.9 && {_selection in ["", "head", "body"]}) exitWith {
if (_unit getvariable ["ACE_isUnconscious", false]) exitwith {
[_unit] call FUNC(setDead);
- 0.89
+ 0.89;
};
if (_delayedUnconsicous) then {
[{
@@ -110,9 +110,9 @@ if (_unit getVariable [QGVAR(preventInstaDeath), GVAR(preventInstaDeath)]) exitW
[_this select 0, true] call FUNC(setUnconscious);
}, [_unit]] call EFUNC(common,execNextFrame);
};
- 0.89
+ 0.89;
};
- _damageReturn min 0.89;
+ 0.89;
};
if (((_unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)]) > 0) && {_damageReturn >= 0.9} && {_selection in ["", "head", "body"]}) exitWith {
@@ -120,8 +120,7 @@ if (((_unit getVariable [QGVAR(enableRevive), GVAR(enableRevive)]) > 0) && {_dam
[_unit] call EFUNC(common,unloadPerson);
};
[_unit] call FUNC(setDead);
-
- 0.89
+ 0.89;
};
-_damageReturn
+_damageReturn;
diff --git a/addons/medical/functions/fnc_handleDamage_advanced.sqf b/addons/medical/functions/fnc_handleDamage_advanced.sqf
index 9da0d065ed..e617738a90 100644
--- a/addons/medical/functions/fnc_handleDamage_advanced.sqf
+++ b/addons/medical/functions/fnc_handleDamage_advanced.sqf
@@ -39,8 +39,6 @@ _damageBodyParts = _unit getvariable [QGVAR(bodyPartStatus), [0,0,0,0,0,0]];
_damageBodyParts set [_part, (_damageBodyParts select _part) + _newDamage];
_unit setvariable [QGVAR(bodyPartStatus), _damageBodyParts, true];
-[_unit] call FUNC(handleDamage_advancedSetDamage);
-
_typeOfDamage = [_typeOfProjectile] call FUNC(getTypeOfDamage);
[_unit, _selectionName, _newDamage, _typeOfProjectile, _typeOfDamage] call FUNC(handleDamage_assignWounds);
diff --git a/addons/medical/functions/fnc_handleDamage_caching.sqf b/addons/medical/functions/fnc_handleDamage_caching.sqf
index 9760770d71..99816ee274 100644
--- a/addons/medical/functions/fnc_handleDamage_caching.sqf
+++ b/addons/medical/functions/fnc_handleDamage_caching.sqf
@@ -81,12 +81,17 @@ if (diag_frameno > (_unit getVariable [QGVAR(frameNo_damageCaching), -3]) + 2) t
_args = _this select 0;
if (diag_frameno > (_args select 1) + 2) then {
+ (_args select 0) setDamage 0;
+
_cache_params = (_args select 0) getVariable [QGVAR(cachedHandleDamageParams), []];
_cache_damages = (_args select 0) getVariable QGVAR(cachedDamages);
{
_params = _x + [_cache_damages select _foreachIndex];
_params call FUNC(handleDamage_advanced);
}foreach _cache_params;
+
+ [(_args select 0)] call FUNC(handleDamage_advancedSetDamage);
+
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
}, 0, [_unit, diag_frameno] ] call CBA_fnc_addPerFrameHandler;
diff --git a/addons/medical/functions/fnc_isInStableCondition.sqf b/addons/medical/functions/fnc_isInStableCondition.sqf
new file mode 100644
index 0000000000..f7c22ed085
--- /dev/null
+++ b/addons/medical/functions/fnc_isInStableCondition.sqf
@@ -0,0 +1,30 @@
+/*
+* Author: Glowbal
+* Check if a unit is in a stable condition
+*
+* Arguments:
+* 0: The patient
+*
+* Return Value:
+* Is in stable condition
+*
+* Public: No
+*/
+
+#include "script_component.hpp"
+
+private ["_unit"];
+_unit = _this select 0;
+
+if (GVAR(level) <= 1) exitwith {
+ ([_unit] call FUNC(getBloodloss)) == 0;
+};
+
+_totalBloodLoss = 0;
+_openWounds = _unit getvariable [QGVAR(openWounds), []];
+{
+ // total bleeding ratio * percentage of injury left
+ _totalBloodLoss = _totalBloodLoss + ((_x select 4) * (_x select 3));
+}foreach _openWounds;
+
+(_totalBloodLoss == 0);
diff --git a/addons/medical/functions/fnc_moduleAdvancedMedicalSettings.sqf b/addons/medical/functions/fnc_moduleAdvancedMedicalSettings.sqf
index 5263044583..2960c65b9d 100644
--- a/addons/medical/functions/fnc_moduleAdvancedMedicalSettings.sqf
+++ b/addons/medical/functions/fnc_moduleAdvancedMedicalSettings.sqf
@@ -33,5 +33,7 @@ if !(_activated) exitWith {};
[_logic, QGVAR(consumeItem_SurgicalKit), "consumeItem_SurgicalKit"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(useLocation_PAK), "useLocation_PAK"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(useLocation_SurgicalKit), "useLocation_SurgicalKit"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(useCondition_PAK), "useCondition_PAK"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(useCondition_SurgicalKit), "useCondition_SurgicalKit"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(healHitPointAfterAdvBandage), "healHitPointAfterAdvBandage"] call EFUNC(common,readSettingFromModule);
[_logic, QGVAR(painIsOnlySuppressed), "painIsOnlySuppressed"] call EFUNC(common,readSettingFromModule);
diff --git a/addons/medical/functions/fnc_setDead.sqf b/addons/medical/functions/fnc_setDead.sqf
index fe18ac581f..c29edcd5e3 100644
--- a/addons/medical/functions/fnc_setDead.sqf
+++ b/addons/medical/functions/fnc_setDead.sqf
@@ -49,7 +49,7 @@ if (((_reviveVal == 1 && {[_unit] call EFUNC(common,isPlayer)} || _reviveVal ==
_unit = _args select 0;
_startTime = _unit getvariable [QGVAR(reviveStartTime), 0];
- if (ACE_time - _startTime > GVAR(maxReviveTime)) exitwith {
+ if (GVAR(maxReviveTime) > 0 && {ACE_time - _startTime > GVAR(maxReviveTime)}) exitwith {
[(_this select 1)] call cba_fnc_removePerFrameHandler;
_unit setvariable [QGVAR(inReviveState), nil, true];
_unit setvariable [QGVAR(reviveStartTime), nil];
@@ -66,6 +66,11 @@ if (((_reviveVal == 1 && {[_unit] call EFUNC(common,isPlayer)} || _reviveVal ==
_unit setvariable [QGVAR(reviveStartTime), nil];
[(_this select 1)] call cba_fnc_removePerFrameHandler;
};
+ if (GVAR(level) >= 2) then {
+ if (_unit getvariable [QGVAR(heartRate), 60] > 0) then {
+ _unit setvariable [QGVAR(heartRate), 0];
+ };
+ };
}, 1, [_unit] ] call CBA_fnc_addPerFrameHandler;
false;
};
diff --git a/addons/medical/functions/fnc_setUnconscious.sqf b/addons/medical/functions/fnc_setUnconscious.sqf
index 3298c0a869..7e5cd8c1b7 100644
--- a/addons/medical/functions/fnc_setUnconscious.sqf
+++ b/addons/medical/functions/fnc_setUnconscious.sqf
@@ -6,10 +6,14 @@
* 0: The unit that will be put in an unconscious state
* 1: Set unconsciouns
* 2: Minimum unconscious ACE_time
+ * 3: Force AI Unconscious (skip random death chance)
*
* ReturnValue:
* nil
*
+ * Example:
+ * [bob, true] call ace_medical_fnc_setUnconscious;
+ *
* Public: yes
*/
diff --git a/addons/medical/functions/fnc_treatment.sqf b/addons/medical/functions/fnc_treatment.sqf
index 06cea8dfe3..18f3406df2 100644
--- a/addons/medical/functions/fnc_treatment.sqf
+++ b/addons/medical/functions/fnc_treatment.sqf
@@ -16,7 +16,7 @@
#include "script_component.hpp"
-private ["_caller", "_target", "_selectionName", "_className", "_config", "_medicRequired", "_items", "_locations", "_return", "_callbackProgress", "_treatmentTime", "_callerAnim", "_patientAnim", "_iconDisplayed", "_return", "_usersOfItems", "_consumeItems", "_condition", "_displayText", "_wpn", "_treatmentTimeConfig"];
+private ["_caller", "_target", "_selectionName", "_className", "_config", "_medicRequired", "_items", "_locations", "_return", "_callbackProgress", "_treatmentTime", "_callerAnim", "_patientAnim", "_iconDisplayed", "_return", "_usersOfItems", "_consumeItems", "_condition", "_displayText", "_wpn", "_treatmentTimeConfig", "_patientStateCondition"];
_caller = _this select 0;
_target = _this select 1;
_selectionName = _this select 2;
@@ -53,9 +53,6 @@ if !([_caller, _medicRequired] call FUNC(isMedic)) exitwith {false};
_items = getArray (_config >> "items");
if (count _items > 0 && {!([_caller, _target, _items] call FUNC(hasItems))}) exitwith {false};
-// Check allowed locations
-_locations = getArray (_config >> "treatmentLocations");
-
_return = true;
if (isText (_config >> "Condition")) then {
_condition = getText(_config >> "condition");
@@ -74,6 +71,16 @@ if (isText (_config >> "Condition")) then {
};
if (!_return) exitwith {false};
+_patientStateCondition = if (isText(_config >> "patientStateCondition")) then {
+ missionNamespace getvariable [getText(_config >> "patientStateCondition"), 0]
+} else {
+ getNumber(_config >> "patientStateCondition")
+};
+if (_patientStateCondition == 1 && {!([_target] call FUNC(isInStableCondition))}) exitwith {false};
+
+// Check allowed locations
+_locations = getArray (_config >> "treatmentLocations");
+
if ("All" in _locations) then {
_return = true;
} else {
diff --git a/addons/medical/functions/fnc_treatmentAdvanced_CPR.sqf b/addons/medical/functions/fnc_treatmentAdvanced_CPR.sqf
index 0a49420783..ade74a6ccb 100644
--- a/addons/medical/functions/fnc_treatmentAdvanced_CPR.sqf
+++ b/addons/medical/functions/fnc_treatmentAdvanced_CPR.sqf
@@ -23,7 +23,7 @@ _selectionName = _this select 2;
_className = _this select 3;
_items = _this select 4;
-// TODO replace by event system instead
-[[_caller, _target], QUOTE(DFUNC(treatmentAdvanced_CPRLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
-
+if (alive _target && {(_target getvariable [QGVAR(inCardiacArrest), false] || _target getvariable [QGVAR(inReviveState), false])}) then {
+ [[_caller, _target], QUOTE(DFUNC(treatmentAdvanced_CPRLocal)), _target] call EFUNC(common,execRemoteFnc); /* TODO Replace by event system */
+};
true;
diff --git a/addons/medical/functions/fnc_treatmentAdvanced_CPRLocal.sqf b/addons/medical/functions/fnc_treatmentAdvanced_CPRLocal.sqf
index 4bb14e1139..61723319a5 100644
--- a/addons/medical/functions/fnc_treatmentAdvanced_CPRLocal.sqf
+++ b/addons/medical/functions/fnc_treatmentAdvanced_CPRLocal.sqf
@@ -14,17 +14,15 @@
#include "script_component.hpp"
-private ["_caller","_target", "_n"];
+private ["_caller","_target", "_reviveStartTime"];
_caller = _this select 0;
_target = _this select 1;
-_n = _target getvariable [QEGVAR(common,ENABLE_REVIVE_COUNTER),0];
-if (_n > 0) then {
- _n = _n - random(20);
- if (_n < 0) then {
- _n = 0;
+if (_target getvariable [QGVAR(inReviveState), false]) exitwith {
+ _reviveStartTime = _target getvariable [QGVAR(reviveStartTime),0];
+ if (_reviveStartTime > 0) then {
+ _target setvariable [QGVAR(reviveStartTime), (_reviveStartTime + random(20)) min ACE_time];
};
- _target setvariable [QEGVAR(common,ENABLE_REVIVE_COUNTER), _n];
};
if (random(1)>= 0.6) exitwith {
diff --git a/addons/medical/functions/fnc_treatment_failure.sqf b/addons/medical/functions/fnc_treatment_failure.sqf
index 19352e5441..53fd03d2f3 100644
--- a/addons/medical/functions/fnc_treatment_failure.sqf
+++ b/addons/medical/functions/fnc_treatment_failure.sqf
@@ -60,4 +60,4 @@ if (isNil _callback) then {
_args call _callback;
-_args call FUNC(createLitter);
+// _args call FUNC(createLitter);
diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml
index e2fee86715..5ceb625f59 100644
--- a/addons/medical/stringtable.xml
+++ b/addons/medical/stringtable.xml
@@ -2918,11 +2918,15 @@
Remote Controlled AI
IA controlada remotamente
IA controlada remotamente
+ Zdalnie sterowane AI
+ Vzdáleně ovládané AI
Treat remote controlled units as AI not players?
¿Tratar unidades remotamente controladas como IA?
Tratar unidades remotamente controladas como IA?
+ Traktuj jednostki zdalnie sterowane (przez Zeusa) jako AI, nie jako graczy?
+ Ošetřit vzdáleně ovládané jednotky jako AI, ne jako hráče?
Disabled
@@ -3177,14 +3181,24 @@
Localizações do KPS
- Where can the personal aid kit be used?
+ Where can the Personal Aid Kit be used?
Где может использоваться аптечка?
Gdzie można korzystać z apteczek osobistych?
¿Dónde se puede utilizar el equipo de primeros auxilios?
Wo kann der Erstehilfekasten verwendet werden?
- Kde může být osobní lékárnička použita?
+ Kde může být použita osobní lékárnička?
Onde o kit de primeiros socorros pode ser utilizado?
+
+ Condition PAK
+ Podmínka osobní lékárničky
+ Condición EPA
+
+
+ When can the Personal Aid Kit be used?
+ Kde může být použita osobní lékárnička?
+ ¿Cuando se puede utilizar el Equipo de primeros auxilios?
+
Anywhere
Где угодно
@@ -3284,6 +3298,16 @@
Kde může být použita chirurgická souprava?
Onde o kit cirúrgico pode ser utilizado?
+
+ Condition Surgical kit (Adv)
+ Podmínka chirurgické soupravy (Pokr.)
+ Condición de equipo quirúrgico (Av)
+
+
+ When can the Surgical kit be used?
+ Kde může být použita chirurgická souprava?
+ ¿Cuando se puede utilizar el equipo quirúrgico?
+
Bloodstains
Blutflecken
@@ -3434,9 +3458,7 @@
É médico
-
-
-
+ Moduł ten pozwala przypisać klasę medyczną wybranym jednostkom.
Dieses Modul legt fest welche Einheit ein Sanitäter ist.
Tento modul určuje, která jednotka je zdravotník.
Este módulo determina qual unidade é um paramédico.
@@ -3609,5 +3631,15 @@
Não
No
+
+ Anytime
+ Kdykoli
+ Siempre
+
+
+ Stable
+ Stabilní
+ Estable
+
\ No newline at end of file
diff --git a/addons/modules/XEH_postInit.sqf b/addons/modules/XEH_postInit.sqf
index f7b652ab44..62d16f42ce 100644
--- a/addons/modules/XEH_postInit.sqf
+++ b/addons/modules/XEH_postInit.sqf
@@ -26,12 +26,8 @@
_function = missionNamespace getvariable _function;
};
- if (_isGlobal) then {
- [_logic, [], true] call _function;
- } else {
- if (isServer) then {
- [_logic, [], true] call _function;
- };
+ if (_isGlobal || isServer) then {
+ [_logic, (synchronizedObjects _logic), true] call _function;
};
if !(_isPersistent) then {
diff --git a/addons/nametags/functions/fnc_drawNameTagIcon.sqf b/addons/nametags/functions/fnc_drawNameTagIcon.sqf
index 7b6bbda138..021a4e2a0b 100644
--- a/addons/nametags/functions/fnc_drawNameTagIcon.sqf
+++ b/addons/nametags/functions/fnc_drawNameTagIcon.sqf
@@ -35,7 +35,7 @@ if ((_iconType == ICON_NAME_SPEAK) || (_iconType == ICON_SPEAK)) then {
_alpha = _alpha max 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);
+ _icon = format["\A3\Ui_f\data\GUI\Cfg\Ranks\%1_gs.paa",(toLower(rank _target))];
_size = 1;
};
};
diff --git a/addons/nametags/script_component.hpp b/addons/nametags/script_component.hpp
index da912b48c4..7bf0acbc4a 100644
--- a/addons/nametags/script_component.hpp
+++ b/addons/nametags/script_component.hpp
@@ -16,15 +16,3 @@
#define ICON_NAME_RANK 2
#define ICON_NAME_SPEAK 3
#define ICON_SPEAK 4
-
-//todo?: custom rank icons??
-#define TEXTURES_RANKS [ \
- "", \
- "\A3\Ui_f\data\GUI\Cfg\Ranks\private_gs.paa", \
- "\A3\Ui_f\data\GUI\Cfg\Ranks\corporal_gs.paa", \
- "\A3\Ui_f\data\GUI\Cfg\Ranks\sergeant_gs.paa", \
- "\A3\Ui_f\data\GUI\Cfg\Ranks\lieutenant_gs.paa", \
- "\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" \
- ]
\ No newline at end of file
diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml
index 7b4d88f61f..d1b6199413 100644
--- a/addons/optionsmenu/stringtable.xml
+++ b/addons/optionsmenu/stringtable.xml
@@ -347,11 +347,15 @@
ACE News
Noticias ACE
Notícias do ACE
+ Wiadomości ACE
+ ACE Novinky
Show News on Main Menu
Mostrar noticias en el menú principal
Mostrar notícias no menu principal
+ Pokazuj wiadomości ACE w menu głównym
+ Zobrazit novinky v hlavním menu
\ No newline at end of file
diff --git a/addons/reloadlaunchers/functions/fnc_load.sqf b/addons/reloadlaunchers/functions/fnc_load.sqf
index 745bb2a5cb..ce7b743df5 100644
--- a/addons/reloadlaunchers/functions/fnc_load.sqf
+++ b/addons/reloadlaunchers/functions/fnc_load.sqf
@@ -38,7 +38,7 @@ _onSuccess = {
};
_onFailure = {
- [localize LESTRING(common,ActionAborted)] call DEFUNC(common,displayTextStructured);
+ [localize ELSTRING(common,ActionAborted)] call DEFUNC(common,displayTextStructured);
};
_condition = {
diff --git a/addons/respawn/CfgAddons.hpp b/addons/respawn/CfgAddons.hpp
index 2793ac09da..111613615e 100644
--- a/addons/respawn/CfgAddons.hpp
+++ b/addons/respawn/CfgAddons.hpp
@@ -1,5 +1,5 @@
class CfgAddons {
class GVAR(Rallypoints) {
- list[] = { "ACE_Rallypoint_West", "ACE_Rallypoint_East", "ACE_Rallypoint_Independent", "ACE_RallypointExit_West", "ACE_RallypointExit_East", "ACE_RallypointExit_Independent" };
+ list[] = {"ACE_Rallypoint_West", "ACE_Rallypoint_East", "ACE_Rallypoint_Independent", "ACE_Rallypoint_West_Base", "ACE_Rallypoint_East_Base", "ACE_Rallypoint_Independent_Base"};
};
};
diff --git a/addons/respawn/config.cpp b/addons/respawn/config.cpp
index daed5e2ab0..4a23d1f650 100644
--- a/addons/respawn/config.cpp
+++ b/addons/respawn/config.cpp
@@ -3,7 +3,7 @@
class CfgPatches {
class ADDON {
units[] = {};
- weapons[] = { "ACE_Rallypoint_West", "ACE_Rallypoint_East", "ACE_Rallypoint_Independent", "ACE_RallypointExit_West", "ACE_RallypointExit_East", "ACE_RallypointExit_Independent" };
+ weapons[] = {"ACE_Rallypoint_West", "ACE_Rallypoint_East", "ACE_Rallypoint_Independent", "ACE_Rallypoint_West_Base", "ACE_Rallypoint_East_Base", "ACE_Rallypoint_Independent_Base"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = { "ace_common" };
author[] = { "bux578", "commy2" };
diff --git a/addons/respawn/functions/fnc_moveRallypoint.sqf b/addons/respawn/functions/fnc_moveRallypoint.sqf
index 5a0472cf5b..d512c23886 100644
--- a/addons/respawn/functions/fnc_moveRallypoint.sqf
+++ b/addons/respawn/functions/fnc_moveRallypoint.sqf
@@ -26,10 +26,12 @@ private ["_rallypoint", "_position"];
_rallypoint = [
objNull,
missionNamespace getVariable ["ACE_Rallypoint_West", objNull],
- missionNamespace getVariable ["ACE_RallypointExit_East", objNull],
- missionNamespace getVariable ["ACE_RallypointExit_Independent", objNull]
+ missionNamespace getVariable ["ACE_Rallypoint_East", objNull],
+ missionNamespace getVariable ["ACE_Rallypoint_Independent", objNull]
] select ([west, east, independent] find _side) + 1;
+TRACE_3("moving rally",_unit, _rallypoint, (typeOf _rallypoint));
+
if (isNull _rallypoint) exitWith {};
_position = getPosATL _unit;
diff --git a/addons/safemode/XEH_postInit.sqf b/addons/safemode/XEH_postInit.sqf
index 7ab283f6b6..c7132dd76c 100644
--- a/addons/safemode/XEH_postInit.sqf
+++ b/addons/safemode/XEH_postInit.sqf
@@ -14,7 +14,7 @@ if (!hasInterface) exitWith {};
// Conditions: canInteract
if !([ACE_player, objNull, ["isNotEscorting"]] call EFUNC(common,canInteractWith)) exitWith {false};
// Conditions: specific
- if !([ACE_player] call EFUNC(common,canUseWeapon)) exitWith {false};
+ if !([ACE_player] call EFUNC(common,canUseWeapon) && {currentWeapon ACE_player != binocular ACE_player}) exitWith {false};
// Statement
[ACE_player, currentWeapon ACE_player, currentMuzzle ACE_player] call FUNC(lockSafety);
diff --git a/addons/sandbag/stringtable.xml b/addons/sandbag/stringtable.xml
index 70dde0da56..5576add969 100644
--- a/addons/sandbag/stringtable.xml
+++ b/addons/sandbag/stringtable.xml
@@ -6,7 +6,7 @@
Sandsack
Мешок с песком
Worek z piaskiem
- Sandbag
+ Saco de arena
Sac de sable
Pytel s pískem
Sacco di Sabbia
@@ -18,7 +18,7 @@
Sandsack (leer)
Мешок с песком (пустой)
Worek na piasek
- Sandbag (empty)
+ Saco de arena (vacio)
Sac de sable (vide)
Pytel na písek (prázdný)
Sacco di Sabbia (Vuoto)
@@ -30,7 +30,7 @@
Nicht möglich
Установка на этом месте невозможна
Nie można tu budować
- Cannot build here
+ No se puede construir aqui
Impossible de construire ici
Zde nelze postavit
Impossibile costruire qui
@@ -42,7 +42,7 @@
Sandsack abbauen
Взять мешок с песком
Zabierz worek
- Pick up sandbag
+ Coger saco de arena
Prendre sac de sable
Zvednout pytel
Prendi Sacco di Sabbia
@@ -54,7 +54,7 @@
Sandsack tragen
Нести мешок с песком
Przenieś worek
- Carry sandbag
+ Portar saco de arena
Porter sac de sable
Nést pytel
Trasporta Sacco di Sabbia
@@ -66,7 +66,7 @@
Tragen beenden
Завершить переноску
Zostaw worek
- End carrying
+ Dejar de portar
Arreter de porter
Položit
Fine Trasporto
@@ -78,7 +78,7 @@
Sandsack ablegen
Положить мешок
Upuść worek
- Drop sandbag
+ Soltar saco de arena
Lacher sac de sable
Odložit pytel
Lascia Sacco di Sabbia
@@ -90,7 +90,7 @@
Aufbauen
Подтвердить установку
Potwierdź rozłożenie
- Confirm Deployment
+ Confirmar despliegue
Confirmer Déploiement
Potvrdit Položení
Conferma Posizionamento
@@ -102,7 +102,7 @@
Abbrechen
Отменить установку
Anuluj rozłożenie
- Cancel Deployment
+ Cancelar despliegue
Annuler Déploiement
Zrušit Položení
Cancella Posizionamento
@@ -114,7 +114,7 @@
Sandsack aufbauen
Установить мешок с песком
Rozłóż worek z piaskiem
- Deploy sandbag
+ Desplegar saco de arena
Deployer sac de sable
Umístit pytel
Posiziona Sacco di Sabbia
@@ -126,7 +126,7 @@
Sandsack Kiste
Ящик мешков с песком
Skrzynia worków na piasek
- Sandbag box
+ Caja de sacos de arena
Caisse de sacs de sable
Bedna na pytle s pískem
Contenitore Sacchi di Sabbia
@@ -138,7 +138,7 @@
Hier gibt es keinen Sand
Здесь нет песка
Tu nie ma piasku
- Here is no sand
+ Aqui no hay arena
Pas de sable ici
Tady není písek
Qui non cè Sabbia
diff --git a/addons/sitting/CfgVehicles.hpp b/addons/sitting/CfgVehicles.hpp
index c915750d02..5fbcdab06e 100644
--- a/addons/sitting/CfgVehicles.hpp
+++ b/addons/sitting/CfgVehicles.hpp
@@ -63,7 +63,7 @@ class CfgVehicles {
GVAR(sitRotation) = 10;
};
// Camping Chair
- class Land_CampingChair_V2_F: ThingX {
+ class Land_CampingChair_V2_F: ThingX {
XEH_ENABLED;
MACRO_SEAT_ACTION
GVAR(canSit) = 1;
@@ -71,44 +71,8 @@ class CfgVehicles {
GVAR(sitPosition[]) = {0, -0.1, -0.45};
GVAR(sitRotation) = 45;
};
- // Chair (Plastic)
- class Land_ChairPlastic_F: ThingX {
- XEH_ENABLED;
- MACRO_SEAT_ACTION
- GVAR(canSit) = 1;
- GVAR(sitDirection) = 90;
- GVAR(sitPosition[]) = {0, 0, -0.5};
- GVAR(sitRotation) = 5;
- };
- // Chair (Wooden)
- class Land_ChairWood_F: ThingX {
- XEH_ENABLED;
- MACRO_SEAT_ACTION
- GVAR(canSit) = 1;
- GVAR(sitDirection) = 180;
- GVAR(sitPosition[]) = {0, -0.05, 0};
- GVAR(sitRotation) = 75;
- };
- // Office Chair
- class Land_OfficeChair_01_F: ThingX {
- XEH_ENABLED;
- MACRO_SEAT_ACTION
- GVAR(canSit) = 1;
- GVAR(sitDirection) = 180;
- GVAR(sitPosition[]) = {0, 0, -0.6};
- GVAR(sitRotation) = 15;
- };
- // Rattan Chair
- class Land_RattanChair_01_F: ThingX {
- XEH_ENABLED;
- MACRO_SEAT_ACTION
- GVAR(canSit) = 1;
- GVAR(sitDirection) = 180;
- GVAR(sitPosition[]) = {0, -0.1, -1}; // Z must be -1 due to chair's geometry (magic floating seat point)
- GVAR(sitRotation) = 2;
- };
// Field Toilet
- class Land_FieldToilet_F: ThingX {
+ class Land_FieldToilet_F: ThingX {
XEH_ENABLED;
MACRO_SEAT_ACTION
GVAR(canSit) = 1;
@@ -117,7 +81,7 @@ class CfgVehicles {
GVAR(sitRotation) = 10;
};
// Toiletbox
- class Land_ToiletBox_F: ThingX {
+ class Land_ToiletBox_F: ThingX {
XEH_ENABLED;
MACRO_SEAT_ACTION
GVAR(canSit) = 1;
@@ -125,4 +89,42 @@ class CfgVehicles {
GVAR(sitPosition[]) = {0, 0.75, -1.1};
GVAR(sitRotation) = 10;
};
+
+ class Furniture_base_F;
+ // Chair (Plastic)
+ class Land_ChairPlastic_F: Furniture_base_F {
+ XEH_ENABLED;
+ MACRO_SEAT_ACTION
+ GVAR(canSit) = 1;
+ GVAR(sitDirection) = 90;
+ GVAR(sitPosition[]) = {0, 0, -0.5};
+ GVAR(sitRotation) = 5;
+ };
+ // Chair (Wooden)
+ class Land_ChairWood_F: Furniture_base_F {
+ XEH_ENABLED;
+ MACRO_SEAT_ACTION
+ GVAR(canSit) = 1;
+ GVAR(sitDirection) = 180;
+ GVAR(sitPosition[]) = {0, -0.05, 0};
+ GVAR(sitRotation) = 75;
+ };
+ // Office Chair
+ class Land_OfficeChair_01_F: Furniture_base_F {
+ XEH_ENABLED;
+ MACRO_SEAT_ACTION
+ GVAR(canSit) = 1;
+ GVAR(sitDirection) = 180;
+ GVAR(sitPosition[]) = {0, 0, -0.6};
+ GVAR(sitRotation) = 15;
+ };
+ // Rattan Chair
+ class Land_RattanChair_01_F: Furniture_base_F {
+ XEH_ENABLED;
+ MACRO_SEAT_ACTION
+ GVAR(canSit) = 1;
+ GVAR(sitDirection) = 180;
+ GVAR(sitPosition[]) = {0, -0.1, -1}; // Z must be -1 due to chair's geometry (magic floating seat point)
+ GVAR(sitRotation) = 2;
+ };
};
diff --git a/addons/sitting/stringtable.xml b/addons/sitting/stringtable.xml
index 5565da1e11..443c34c360 100644
--- a/addons/sitting/stringtable.xml
+++ b/addons/sitting/stringtable.xml
@@ -5,23 +5,36 @@
Sit Down
Usiądź
Sentar
+ Sednout si
+ Sentarse
Stand Up
Wstań
Levantar
+ Vstát
+ Levantarse
Enable Sitting
Habilitar opção para sentar
+ Aktywuj siadanie
+ Povolit sezení
+ Acivar asiento
Sitting
Sentado
+ Siadanie
+ Sedící
+ Sentarse
This module allows you to disable the ability to sit on chairs and toilets.
Este módulo permite que você desabilite a capacidade de sentar-se em cadeiras e banheiros.
+ Moduł ten pozwala na włączenie lub wyłączenie możliwości siadania na krzesłach i toaletach.
+ Tento modul dovoluje zakázat možnost sedět na židlých a toaletách.
+ Este módulo te permite desactivar la capacidad de sentarte en sillas y aseos.
\ No newline at end of file
diff --git a/addons/spectator/$PBOPREFIX$ b/addons/spectator/$PBOPREFIX$
new file mode 100644
index 0000000000..42fe4034e9
--- /dev/null
+++ b/addons/spectator/$PBOPREFIX$
@@ -0,0 +1 @@
+z\ace\addons\spectator
\ No newline at end of file
diff --git a/addons/spectator/ACE_Settings.hpp b/addons/spectator/ACE_Settings.hpp
new file mode 100644
index 0000000000..88f4ebfad6
--- /dev/null
+++ b/addons/spectator/ACE_Settings.hpp
@@ -0,0 +1,26 @@
+class ACE_Settings {
+ class GVAR(enabled) {
+ value = 0;
+ typeName = "BOOL";
+ };
+ class GVAR(limitSide) {
+ value = 0;
+ typeName = "BOOL";
+ };
+ class GVAR(AI) {
+ value = 0;
+ typeName = "BOOL";
+ };
+ class GVAR(tracking) {
+ value = 0;
+ typeName = "BOOL";
+ };
+ class GVAR(modulePos) {
+ value = 0;
+ typeName = "BOOL";
+ };
+ class GVAR(endMission) {
+ value = 0;
+ typeName = "BOOL";
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/CfgEventHandlers.hpp b/addons/spectator/CfgEventHandlers.hpp
new file mode 100644
index 0000000000..e75956f440
--- /dev/null
+++ b/addons/spectator/CfgEventHandlers.hpp
@@ -0,0 +1,11 @@
+class Extended_PreInit_EventHandlers {
+ class ADDON {
+ init = QUOTE(call COMPILE_FILE(XEH_preInit));
+ };
+};
+
+class Extended_PostInit_EventHandlers {
+ class ADDON {
+ init = QUOTE(call COMPILE_FILE(XEH_postInit));
+ };
+};
diff --git a/addons/spectator/CfgVehicles.hpp b/addons/spectator/CfgVehicles.hpp
new file mode 100644
index 0000000000..8faee1dca7
--- /dev/null
+++ b/addons/spectator/CfgVehicles.hpp
@@ -0,0 +1,53 @@
+class CfgVehicles {
+ class ACE_Module;
+ class ACE_ModuleSpectator: ACE_Module {
+ author = ECSTRING(common,ACETeam);
+ category = "ACE";
+ displayName = CSTRING(Module_DisplayName);
+ function = QFUNC(moduleSpectator);
+ scope = 2;
+ isGlobal = 1;
+ icon = PATHTOF(UI\Icon_Module_Spectator_ca.paa);
+ class Arguments {
+ class SpectatorEnabled {
+ displayName = CSTRING(Enabled_DisplayName);
+ description = CSTRING(Enabled_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ class SpectatorPlayerSide {
+ displayName = CSTRING(PlayerSide_DisplayName);
+ description = CSTRING(PlayerSide_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ class SpectatorAI {
+ displayName = CSTRING(AI_DisplayName);
+ description = CSTRING(AI_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ class SpectatorTracking {
+ displayName = CSTRING(Tracking_DisplayName);
+ description = CSTRING(Tracking_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ class SpectatorPos {
+ displayName = CSTRING(Pos_DisplayName);
+ description = CSTRING(Pos_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ class SpectatorEnd {
+ displayName = CSTRING(End_DisplayName);
+ description = CSTRING(End_Description);
+ typeName = "BOOL";
+ defaultValue = 0;
+ };
+ };
+ class ModuleDescription {
+ description = CSTRING(Module_Description);
+ };
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/README.md b/addons/spectator/README.md
new file mode 100644
index 0000000000..180f21c57c
--- /dev/null
+++ b/addons/spectator/README.md
@@ -0,0 +1,10 @@
+ace_spectator
+=======
+
+Spectator. Includes features from Splendid Cam, and much more.
+
+## Maintainers
+
+The people responsible for merging changes to this component or answering potential questions.
+
+- [voiper](https://github.com/voiperr)
\ No newline at end of file
diff --git a/addons/spectator/UI.hpp b/addons/spectator/UI.hpp
new file mode 100644
index 0000000000..eec38066f9
--- /dev/null
+++ b/addons/spectator/UI.hpp
@@ -0,0 +1,640 @@
+#define PIXEL_X (safeZoneWAbs / (getResolution select 0))
+#define PIXEL_Y (safeZoneH / (getResolution select 1))
+#define XHAIR RESUNITS_X * 4
+#define COMPASS_W RESUNITS_X * 20
+#define COMPASS_H COMPASS_W / 15
+#define COMPASS_X RESCENTRE_X - COMPASS_W / 2
+#define HELP_W RESUNITS_X * 75
+#define HELP_H RESUNITS_Y * 75
+
+class ace_spectator_overlay {
+
+ idd = 12200;
+ enableSimulation = 1;
+ movingEnable = 1;
+ enableDisplay = 1;
+ onLoad = "uiNamespace setVariable ['ace_spectator_overlay', _this select 0]; ['Init', _this] call ace_spectator_fnc_overlay";
+
+ class controls {
+
+ class Unitlist {
+
+ access = 0;
+ idc = 0;
+ type = CT_TREE;
+ style = ST_LEFT;
+ default = 0;
+ blinkingPeriod = 0;
+
+ x = QUOTE(safeZoneX);
+ y = QUOTE(safeZoneY + RESUNITS_X * 4/3);
+ w = QUOTE(RESUNITS_X * 30);
+ h = QUOTE(RESUNITS_Y * 50);
+
+ colorBorder[] = {1,1,1,1};
+
+ colorBackground[] = {0.1,0.1,0.1,1};
+ colorSelect[] = {1,0.5,0,1};
+ colorMarked[] = {1,0.5,0,0.5};
+ colorMarkedSelected[] = {1,0.5,0,1};
+
+ sizeEx = QUOTE(RESUNITS_Y * 2);
+ font = GUI_FONT_NORMAL;
+ shadow = 1;
+ colorText[] = {1,1,1,1};
+ colorSelectText[] = {1,1,1,1};
+ colorMarkedText[] = {1,1,1,1};
+
+ tooltip = "";
+ tooltipColorShade[] = {0,0,0,1};
+ tooltipColorText[] = {1,1,1,1};
+ tooltipColorBox[] = {1,1,1,1};
+
+ multiselectEnabled = 0;
+ expandOnDoubleclick = 0;
+ hiddenTexture = "A3\ui_f\data\gui\rsccommon\rsctree\hiddenTexture_ca.paa";
+ expandedTexture = "A3\ui_f\data\gui\rsccommon\rsctree\expandedTexture_ca.paa";
+ maxHistoryDelay = 1;
+
+ class ScrollBar {
+ width = 0;
+ height = 0;
+ scrollSpeed = 0.01;
+
+ arrowEmpty = "\A3\ui_f\data\gui\cfg\scrollbar\arrowEmpty_ca.paa";
+ arrowFull = "\A3\ui_f\data\gui\cfg\scrollbar\arrowFull_ca.paa";
+ border = "\A3\ui_f\data\gui\cfg\scrollbar\border_ca.paa";
+ thumb = "\A3\ui_f\data\gui\cfg\scrollbar\thumb_ca.paa";
+
+ color[] = {1,1,1,1};
+ };
+
+ colorDisabled[] = {0,0,0,0};
+ colorArrow[] = {0,0,0,0};
+
+ onDestroy = QUOTE(GVAR(mouseBusy) = false; false);
+ onMouseEnter = QUOTE(GVAR(mouseBusy) = true; false);
+ onMouseExit = QUOTE(GVAR(mouseBusy) = false; false);
+
+ onTreeDblClick = "['Select', _this] call ace_spectator_fnc_overlay; false";
+ };
+ };
+};
+
+class ace_spectator_vd {
+ idd = 12201;
+ enableSimulation = 1;
+ enableDisplay = 0;
+ movingEnable = 0;
+
+ onLoad = "uiNamespace setVariable ['ace_spectator_vd', _this select 0]; ['Init', _this] call ace_spectator_fnc_viewDistance";
+
+ class Controls {
+
+ class BG: vip_rsc_box {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ y = QUOTE(safeZoneY + COMPASS_H);
+ w = QUOTE(RESUNITS_X * 30);
+ h = QUOTE(COMPASS_H);
+ colorBackground[] = {0.1,0.1,0.1,1};
+ onDestroy = QUOTE(GVAR(mouseBusy) = false; false);
+ };
+
+ class TitleFrame: vip_rsc_frame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ y = QUOTE(safeZoneY + COMPASS_H);
+ w = QUOTE(RESUNITS_X * 8);
+ h = QUOTE(COMPASS_H);
+ shadow = 2;
+ colorText[]={1,1,1,1};
+ };
+
+ class Title: vip_rsc_text {
+ style = ST_CENTER;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ y = QUOTE(safeZoneY + COMPASS_H);
+ w = QUOTE(RESUNITS_X * 8);
+ h = QUOTE(COMPASS_H);
+ sizeEx = QUOTE(RESUNITS_Y * 2);
+ font = GUI_FONT_NORMAL;
+ shadow = 2;
+ colorText[]={1,1,1,1};
+ text = CSTRING(VD_Title);
+ };
+
+ class DistanceFrame: TitleFrame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5);
+ w = QUOTE(RESUNITS_X * 5);
+ };
+
+ class Distance: Title {
+ idc = 1;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5);
+ w = QUOTE(RESUNITS_X * 5);
+ text = "";
+ };
+
+ class ButtonExit: vip_rsc_button {
+ idc = 0;
+ style = ST_CENTER;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5);
+ y = QUOTE(safeZoneY + COMPASS_H);
+ w = QUOTE(RESUNITS_X * 5);
+ h = QUOTE(COMPASS_H);
+
+ colorBackground[] = {1,1,1,1};
+ sizeEx = QUOTE(RESUNITS_Y * 2);
+ font = GUI_FONT_NORMAL;
+
+ text = CSTRING(VD_Button);
+
+ onButtonClick = "closeDialog 0; false";
+ onMouseButtonDown = QUOTE(GVAR(mouseBusy) = true; false);
+ onMouseButtonUp = QUOTE(GVAR(mouseBusy) = false; false);
+ };
+
+ class Slider {
+ idc = 2;
+
+ type = CT_XSLIDER;
+ style = SL_HORZ;
+ shadow = 2;
+
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5);
+ y = QUOTE(safeZoneY + COMPASS_H);
+ w = QUOTE(RESUNITS_X * 9.5);
+ h = QUOTE(COMPASS_H);
+ color[] = {1,1,1,1};
+ colorActive[] = {1,1,1,1};
+ colorDisabled[] = {1,1,1,0.2};
+ arrowEmpty = "\A3\ui_f\data\gui\cfg\slider\arrowEmpty_ca.paa";
+ arrowFull = "\A3\ui_f\data\gui\cfg\slider\arrowFull_ca.paa";
+ border = "\A3\ui_f\data\gui\cfg\slider\border_ca.paa";
+ thumb = "\A3\ui_f\data\gui\cfg\slider\thumb_ca.paa";
+
+ text = "";
+ onSliderPosChanged = "['Slider', _this] call ace_spectator_fnc_viewDistance";
+ onMouseButtonDown = QUOTE(GVAR(mouseBusy) = true; false);
+ onMouseButtonUp = QUOTE(GVAR(mouseBusy) = false; false);
+ };
+ };
+};
+
+class ace_spectator_map {
+
+ idd = 12202;
+ enableSimulation = 1;
+ enableDisplay = 0;
+ onLoad = "uiNameSpace setVariable ['ace_spectator_map', _this select 0]; ['Init', _this select 0] call ace_spectator_fnc_map";
+ onUnload = "['Close', _this select 0] call ace_spectator_fnc_map";
+ onKeyDown = "['KeyDown', _this] call ace_spectator_fnc_map";
+
+ class controls {
+ //changes stolen from ACE_map
+ class Map {
+ access = 0;
+ idc = 1;
+ type = CT_MAP_MAIN;
+ style = ST_PICTURE;
+ default = 0;
+ blinkingPeriod = 0;
+
+ x = safeZoneXAbs;
+ y = safeZoneY;
+ w = safeZoneWAbs;
+ h = safeZoneH;
+
+ sizeEx = GUI_GRID_CENTER_H;
+ font = GUI_FONT_NORMAL;
+ colorText[] = {0,0,0,1};
+ text = "#(argb,8,8,3)color(1,1,1,1)";
+
+ moveOnEdges = 1;
+
+ ptsPerSquareSea = 5;
+ ptsPerSquareTxt = 20;
+ ptsPerSquareCLn = 10;
+ ptsPerSquareExp = 10;
+ ptsPerSquareCost = 10;
+
+ ptsPerSquareFor = 9;
+ ptsPerSquareForEdge = 9;
+ ptsPerSquareRoad = 6;
+ ptsPerSquareObj = 9;
+
+ scaleMin = 0.001;
+ scaleMax = 1.0;
+ scaleDefault = 0.16;
+
+ alphaFadeStartScale = 2;
+ alphaFadeEndScale = 2;
+ maxSatelliteAlpha = 0.5;
+
+ colorBackground[] = {0.929412, 0.929412, 0.929412, 1.0};
+ colorOutside[] = {0.929412, 0.929412, 0.929412, 1.0};
+ colorSea[] = {0.4,0.6,0.8,0.5};
+ colorForest[] = {0.6, 0.8, 0.2, 0.25};
+ colorForestBorder[] = {0.6,0.8,0.4,1};
+ colorRocks[] = {0.50, 0.50, 0.50, 0.50};
+ colorRocksBorder[] = {0,0,0,1};
+ colorLevels[] = {0.0, 0.0, 0.0, 1.0};
+ colorMainCountlines[] = {0.858824, 0, 0,1};
+ colorCountlines[] = {0.647059, 0.533333, 0.286275, 1};
+ colorMainCountlinesWater[] = {0.5,0.6,0.7,0.6};
+ colorCountlinesWater[] = {0.5,0.6,0.7,0.3};
+ colorPowerLines[] = {0.1,0.1,0.1,1};
+ colorRailWay[] = {0.8,0.2,0,1};
+ colorNames[] = {1.1,0.1,1.1,0.9};
+ colorInactive[] = {1,1,0,0.5};
+ colorTracks[] = {0.2,0.13,0,1};
+ colorTracksFill[] = {1,0.88,0.65,0.3};
+ colorRoads[] = {0.2,0.13,0,1};
+ colorRoadsFill[] = {1,0.88,0.65,1};
+ colorMainRoads[] = {0.0,0.0,0.0,1};
+ colorMainRoadsFill[] = {0.94,0.69,0.2,1};
+ colorGrid[] = {0.05,0.1,0,0.6};
+ colorGridMap[] = {0.05,0.1,0,0.4};
+
+ fontLabel="PuristaMedium";
+ sizeExLabel="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontGrid="TahomaB";
+ sizeExGrid = 0.032;
+ fontUnits="TahomaB";
+ sizeExUnits="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontNames="EtelkaNarrowMediumPro";
+ sizeExNames="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8) * 2";
+ fontInfo="PuristaMedium";
+ sizeExInfo="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontLevel="TahomaB";
+ sizeExLevel=0.03;
+ showCountourInterval = 1;
+
+ class Task {
+ icon = "#(argb,8,8,3)color(1,1,1,1)";
+ color[] = {1,1,0,1};
+
+ iconCreated = "#(argb,8,8,3)color(1,1,1,1)";
+ colorCreated[] = {0,0,0,1};
+
+ iconCanceled = "#(argb,8,8,3)color(1,1,1,1)";
+ colorCanceled[] = {0,0,0,0.5};
+
+ iconDone = "#(argb,8,8,3)color(1,1,1,1)";
+ colorDone[] = {0,1,0,1};
+
+ iconFailed = "#(argb,8,8,3)color(1,1,1,1)";
+ colorFailed[] = {1,0,0,1};
+
+ size = 8;
+ importance = 1;
+ coefMin = 1;
+ coefMax = 1;
+ };
+ class ActiveMarker { //includes icons spawned by drawIcon
+ color[] = {0,0,0,1};
+ size = 2;
+ coefMin = 1; //make sure icon doesnt scale
+ };
+ class Waypoint {
+ coefMax = 1;
+ coefMin = 4;
+ color[] = {0,0,0,1};
+ icon = "#(argb,8,8,3)color(0,0,0,1)";
+ importance = 1;
+ size = 2;
+ };
+ class WaypointCompleted: Waypoint{};
+ class CustomMark: Waypoint{};
+ class Command: Waypoint{};
+ class Bush {
+ icon = "";
+ color[] = {0.450000, 0.640000, 0.330000, 0.0};
+ size = 14;
+ importance = "0.2 * 14 * 0.05";
+ coefMin = 0.250000;
+ coefMax = 4;
+ };
+ class Rock: Waypoint{color[]={0.45,0.64,0.33,0.4}; importance="0.5 * 12 * 0.05";};
+ class SmallTree {
+ icon = "";
+ color[] = {0.450000, 0.640000, 0.330000, 0.0};
+ size = 12;
+ importance = "0.6 * 12 * 0.05";
+ coefMin = 0.250000;
+ coefMax = 4;
+ };
+ class Tree {
+ icon = "";
+ color[] = {0.450000, 0.640000, 0.330000, 0.0};
+ size = 12;
+ importance = "0.9 * 16 * 0.05";
+ coefMin = 0.250000;
+ coefMax = 4;
+ };
+ class Legend {
+ x = SafeZoneX+SafeZoneW-.340;
+ y = SafeZoneY+SafeZoneH-.152;
+ font = "PuristaMedium";
+ w = .340;
+ h = .152;
+ sizeEx = 0.039210;
+ colorBackground[] = {0.906000, 0.901000, 0.880000, 0.5};
+ color[] = {0, 0, 0, 0.75};
+ };
+ class BusStop: Waypoint{};
+ class FuelStation: Waypoint{};
+ class Hospital: Waypoint{};
+ class Church: Waypoint{};
+ class Lighthouse: Waypoint{};
+ class Power: Waypoint{};
+ class PowerSolar: Waypoint{};
+ class PowerWave: Waypoint{};
+ class PowerWind: Waypoint{};
+ class Quay: Waypoint{};
+ class Transmitter: Waypoint{};
+ class Watertower: Waypoint{};
+ class Cross: Waypoint{};
+ class Chapel: Waypoint{};
+ class Shipwreck: Waypoint{};
+ class Bunker: Waypoint{};
+ class Fortress: Waypoint{};
+ class Fountain: Waypoint{};
+ class Ruin: Waypoint{};
+ class Stack: Waypoint{};
+ class Tourism: Waypoint{};
+ class ViewTower: Waypoint{};
+ };
+ };
+};
+
+class RscTitles {
+ class ace_spectator_crosshair {
+
+ onLoad = "uiNamespace setVariable ['ace_spectator_crosshair', _this select 0]";
+
+ idd=-1;
+ movingEnable=0;
+ fadein=0;
+ fadeout=0;
+ duration=1e+011;
+
+ class controls {
+
+ class X: vip_rsc_picture {
+ idc = 0;
+ x = QUOTE(RESCENTRE_X - XHAIR / 2);
+ y = QUOTE(RESCENTRE_Y - XHAIR * 4/3 / 2);
+ w = QUOTE(XHAIR);
+ h = QUOTE(XHAIR * 4/3);
+ text = "\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa";
+ colorText[] = {1,1,1,0.8};
+ };
+ };
+ };
+
+ class ace_spectator_status {
+
+ onLoad = "uiNamespace setVariable ['ace_spectator_status', _this select 0]; [_this select 0] call ace_spectator_fnc_status";
+ idd = -1;
+ movingEnable=0;
+ fadein=0;
+ fadeout=0;
+ duration=1e+011;
+
+ class controls {
+
+ class BGRight: vip_rsc_box {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(RESUNITS_X * 30);
+ h = QUOTE(COMPASS_H);
+ colorBackground[] = {0.1,0.1,0.1,1};
+ };
+
+ class BGLeft: BGRight {
+ x = QUOTE(safeZoneX);
+ };
+
+ class SpeedFrame: vip_rsc_frame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(RESUNITS_X * 5);
+ h = QUOTE(COMPASS_H);
+ shadow = 2;
+ colorText[]={1,1,1,1};
+ };
+
+ class Speed: vip_rsc_text {
+ idc = 0;
+ style = ST_CENTER;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(RESUNITS_X * 5);
+ h = QUOTE(COMPASS_H);
+ colorText[]={1,1,1,1};
+ sizeEx = QUOTE(RESUNITS_Y * 2);
+ font = GUI_FONT_NORMAL;
+ text = "";
+ };
+
+ class FovFrame: SpeedFrame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5);
+ };
+
+ class Fov: Speed {
+ idc = 4;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5);
+ };
+
+ class TimeAccFrame: SpeedFrame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5);
+ };
+
+ class TimeAcc: Speed {
+ idc = 5;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5);
+ };
+
+ class FocusFrame: SpeedFrame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 16);
+ };
+
+ class Focus: Speed {
+ idc = 6;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 16);
+ };
+
+ class NameFrame: SpeedFrame {
+ x = QUOTE(safeZoneX);
+ w = QUOTE(RESUNITS_X * 24.5);
+ };
+
+ class Name: Speed {
+ idc = 1;
+ x = QUOTE(safeZoneX);
+ w = QUOTE(RESUNITS_X * 24.5);
+ };
+
+ class ModeFrame: SpeedFrame {
+ x = QUOTE(safeZoneX + RESUNITS_X * 25);
+ };
+
+ class Mode: Speed {
+ idc = 2;
+ x = QUOTE(safeZoneX + RESUNITS_X * 25);
+ };
+
+ class TimeFrame: SpeedFrame {
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ w = QUOTE(RESUNITS_X * 8);
+ };
+
+ class Time: Speed {
+ idc = 3;
+ x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30);
+ w = QUOTE(RESUNITS_X * 8);
+ };
+ };
+ };
+
+ class ace_spectator_compass {
+
+ onLoad = "uiNamespace setVariable ['ace_spectator_compass', _this select 0]";
+ onUnload = "";
+ idd=-1;
+ movingEnable=0;
+ fadein=0;
+ fadeout=0;
+ duration=1e+011;
+
+ class controls {
+
+ class BG: vip_rsc_box {
+ x = QUOTE(COMPASS_X);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(COMPASS_W);
+ h = QUOTE(COMPASS_H);
+ colorBackground[] = {0.1,0.1,0.1,1};
+ };
+
+ class 0_90: vip_rsc_picture {
+ idc = 1;
+ x = QUOTE(RESCENTRE_X);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(COMPASS_W / 2);
+ h = QUOTE(COMPASS_H);
+ text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture180_ca.paa";
+ };
+
+ class 90_180: 0_90 {
+ idc = 2;
+ x = QUOTE(RESCENTRE_X + COMPASS_W / 2);
+ text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture270_ca.paa";
+ };
+
+ class 180_270: 0_90 {
+ idc = 3;
+ x = QUOTE(RESCENTRE_X + COMPASS_W);
+ text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture0_ca.paa";
+ };
+
+ class 270_0: 0_90 {
+ idc = 4;
+ x = QUOTE(RESCENTRE_X + COMPASS_W * 1.5);
+ text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture90_ca.paa";
+ };
+
+ class Post: vip_rsc_box {
+ x = QUOTE(COMPASS_X + COMPASS_W / 2);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(PIXEL_X * 2);
+ h = QUOTE(COMPASS_H);
+ colorBackground[]={1,0,0,1};
+ };
+
+ class LeftBlocker: vip_rsc_box {
+ x = QUOTE(COMPASS_X - COMPASS_W / 2);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(COMPASS_W / 2);
+ h = QUOTE(COMPASS_H);
+ colorBackground[] = {0.1,0.1,0.1,1};
+ };
+
+ class RightBlocker: LeftBlocker {
+ x = QUOTE(COMPASS_X + COMPASS_W);
+ };
+
+ class Frame: vip_rsc_frame {
+ x = QUOTE(COMPASS_X);
+ y = QUOTE(safeZoneY);
+ w = QUOTE(COMPASS_W);
+ h = QUOTE(COMPASS_H);
+ shadow=2;
+ colorText[]={1,1,1,1};
+ };
+ };
+ };
+
+ class ace_spectator_help {
+
+ onLoad = "uiNamespace setVariable ['ace_spectator_help', _this select 0]; ['Help', _this select 0] call ace_spectator_fnc_camera";
+ idd = -1;
+ movingEnable=0;
+ fadein=0;
+ fadeout=0;
+ duration=1e+011;
+
+ class controls {
+
+ class BG: vip_rsc_box {
+ idc = -1;
+ x = QUOTE(RESCENTRE_X - HELP_W / 2);
+ y = QUOTE(RESCENTRE_Y - HELP_H / 2);
+ w = QUOTE(HELP_W);
+ h = QUOTE(HELP_H);
+ colorBackground[] = {0.1,0.1,0.1,1};
+ };
+
+ class Title: vip_rsc_text {
+ idc = 0;
+ style = ST_CENTER;
+ x = QUOTE(RESCENTRE_X - RESUNITS_X * 25);
+ y = QUOTE(RESCENTRE_Y - (HELP_H / 2) + RESUNITS_Y * 3);
+ w = QUOTE(RESUNITS_X * 50);
+ h = QUOTE(RESUNITS_Y * 4);
+ colorText[]={1,1,1,1};
+ sizeEx = QUOTE(RESUNITS_Y * 4);
+ font = GUI_FONT_NORMAL;
+ text = "ACE Spectator Controls";
+ };
+
+ class LeftColumn1 {
+ idc = 1;
+ type = CT_STRUCTURED_TEXT;
+ style = ST_LEFT;
+ x = QUOTE(RESCENTRE_X - HELP_W / 2 + RESUNITS_X * 3);
+ y = QUOTE(RESCENTRE_Y - (HELP_H / 2) + RESUNITS_Y * 10);
+ w = QUOTE(RESUNITS_X * 16.75);
+ h = QUOTE(RESUNITS_Y * 63);
+ text = "";
+ size = QUOTE(RESUNITS_Y * 2.5);
+ colorBackground[] = {0,0,0,0};
+ };
+
+ class LeftColumn2: LeftColumn1 {
+ idc = 2;
+ x = QUOTE(RESCENTRE_X - HELP_W / 2 + RESUNITS_X * 19.75);
+ };
+
+ class RightColumn1: LeftColumn1 {
+ idc = 3;
+ x = QUOTE(RESCENTRE_X + HELP_W / 2 - RESUNITS_X * 3 - RESUNITS_X * 29.5);
+ };
+
+ class RightColumn2: LeftColumn1 {
+ idc = 4;
+ x = QUOTE(RESCENTRE_X + HELP_W / 2 - RESUNITS_X * 3 - RESUNITS_X * 11.75);
+ };
+ };
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/UI/Icon_Module_Spectator_ca.paa b/addons/spectator/UI/Icon_Module_Spectator_ca.paa
new file mode 100644
index 0000000000..a4d784cea6
Binary files /dev/null and b/addons/spectator/UI/Icon_Module_Spectator_ca.paa differ
diff --git a/addons/spectator/XEH_postInit.sqf b/addons/spectator/XEH_postInit.sqf
new file mode 100644
index 0000000000..b57d08ac7b
--- /dev/null
+++ b/addons/spectator/XEH_postInit.sqf
@@ -0,0 +1,96 @@
+/*
+ Author:
+ voiper
+*/
+
+#include "script_component.hpp"
+
+["SettingsInitialized", {
+ if !GVAR(enabled) exitWith {};
+
+ //check if respawn is set up properly
+ _fail = if (getNumber (missionConfigFile >> "respawn") != 3 && getText (missionConfigFile >> "respawn") != "Base") then {true} else {false};
+ if (_fail) exitWith {
+ _text = "[ACE_Spectator] ERROR: This mission does not have respawn set up properly. Add 'respawn=3' or 'respawn=""BASE""' to description.ext.";
+ systemChat _text;
+ diag_log text _text;
+ };
+
+ if GVAR(endMission) then {
+ [{
+ if (player distance GVAR(penPos) < 200) then {
+ if ({isPlayer _x && alive _x && (_x distance GVAR(penPos)) > 200} count allUnits == 0) then {
+ [["endDeath", false], "BIS_fnc_endMission"] call BIS_fnc_MP;
+ [_this select 1] call CBA_fnc_removePerFrameHandler;
+ };
+ };
+ }, 2] call CBA_fnc_addPerFrameHandler;
+ };
+
+ if (isDedicated) exitWith {};
+
+ call FUNC(penPos);
+
+ {
+ if (getMarkerPos _x isEqualTo [0,0,0]) then {
+ _marker = createMarkerLocal [_x, [0,0]];
+ _marker setMarkerShapeLocal "ICON";
+ };
+
+ _x setMarkerPosLocal GVAR(penPos);
+ } forEach ["respawn_west", "respawn_east", "respawn_guerrila", "respawn_civilian"];
+
+ GVAR(playerSide) = side (group player);
+
+ if GVAR(tracking) then {
+ [FUNC(checkUnits), 2] call CBA_fnc_addPerFrameHandler;
+ [FUNC(trackUnits), 20] call CBA_fnc_addPerFrameHandler;
+ };
+
+ player addEventHandler ["Killed", {
+ [player] joinSilent grpNull;
+ if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then {EGVAR(hearing,disableVolumeUpdate) = true};
+ _delay = getNumber (missionConfigFile >> "respawnDelay");
+ _delay fadeSound 0;
+ 999999 cutText ["", "BLACK", _delay];
+ }];
+
+ player addEventHandler ["Respawn", {
+ if (!isNil QGVAR(cam)) then {["Exit"] call FUNC(camera)};
+ if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then {EGVAR(hearing,disableVolumeUpdate) = true};
+ if (isClass (configFile >> "CfgPatches" >> "acre_sys_radio")) then {[true] call acre_api_fnc_setSpectator};
+ if (isClass (configFile >> "CfgPatches" >> "task_force_radio")) then {[player, true] call TFAR_fnc_forceSpectator};
+
+ if !GVAR(modulePos) then {
+ _corpse = _this select 1;
+ if (!isNil "_corpse") then {
+ if (!isNull _corpse) then {
+ GVAR(startingPos) = getPosATL _corpse;
+ };
+ };
+ };
+
+ player addEventHandler ["HandleDamage", {0}];
+ [player] joinSilent grpNull;
+ removeAllWeapons player;
+ removeAllItems player;
+ removeAllAssignedItems player;
+ removeUniform player;
+ removeVest player;
+ player linkItem "ItemMap";
+ player linkItem "ItemRadio";
+ hideObjectGlobal player;
+
+ if (surfaceisWater GVAR(penPos)) then {
+ player forceAddUniform "U_B_Wetsuit";
+ player addVest "V_RebreatherB";
+ };
+
+ player setPosATL GVAR(penPos);
+
+ 0 fadeSound 0;
+ 999999 cutText ["", "BLACK FADED", 0];
+ ["Init", [true]] call FUNC(camera);
+ }];
+
+}] call EFUNC(common,addEventHandler);
\ No newline at end of file
diff --git a/addons/spectator/XEH_preInit.sqf b/addons/spectator/XEH_preInit.sqf
new file mode 100644
index 0000000000..41b24e8fcc
--- /dev/null
+++ b/addons/spectator/XEH_preInit.sqf
@@ -0,0 +1,31 @@
+#include "script_component.hpp"
+
+ADDON = false;
+
+PREP(camera);
+PREP(cameraIntro);
+PREP(canSpectateUnit);
+PREP(checkUnits);
+PREP(compass);
+PREP(crosshair);
+PREP(draw3D);
+PREP(drawMines2D);
+PREP(drawMines3D);
+PREP(drawTracks2D);
+PREP(drawUnits2D);
+PREP(drawUnits3D);
+PREP(killed);
+PREP(map);
+PREP(moduleSpectator);
+PREP(overlay);
+PREP(penPos);
+PREP(respawn);
+PREP(sideColour);
+PREP(status);
+PREP(trackUnits);
+PREP(unitInfo);
+PREP(unitSide);
+PREP(unitVar);
+PREP(viewDistance);
+
+ADDON = true;
\ No newline at end of file
diff --git a/addons/spectator/config.cpp b/addons/spectator/config.cpp
new file mode 100644
index 0000000000..89b0b814b5
--- /dev/null
+++ b/addons/spectator/config.cpp
@@ -0,0 +1,19 @@
+#include "script_component.hpp"
+
+class CfgPatches {
+ class ADDON {
+ units[] = {};
+ weapons[] = {};
+ requiredVersion = REQUIRED_VERSION;
+ requiredAddons[] = {"ace_common"};
+ author[] = {"voiper"};
+ authorUrl = "https://github.com/voiperr/";
+ VERSION_CONFIG;
+ };
+};
+
+#include "ACE_Settings.hpp"
+#include "CfgEventHandlers.hpp"
+#include "CfgVehicles.hpp"
+#include "rsc_defines.hpp"
+#include "UI.hpp"
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_camera.sqf b/addons/spectator/functions/fnc_camera.sqf
new file mode 100644
index 0000000000..bc4cea88cc
--- /dev/null
+++ b/addons/spectator/functions/fnc_camera.sqf
@@ -0,0 +1,1081 @@
+/*
+ Author:
+ voiper, derived in part from BIS_fnc_camera by Karel Moricky
+
+ Description:
+ Spectator camera and UI.
+
+ Arguments:
+ 0: Mode: "Init" is the only mission relevant one
+ 1: (optional):
+ 0: Whether player can escape from camera (false for MP spectator; true for SP photography)
+
+ Example:
+ ["Init", [false]] call ace_spectator_fnc_camera;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+#include "\a3\editor_f\Data\Scripts\dikCodes.h"
+
+disableSerialization;
+_mode = _this select 0;
+_this = _this select 1;
+
+switch _mode do {
+
+ case "Init": {
+
+ GVAR(noEscape) = if (count _this > 0) then {_this select 0} else {false};
+
+ call FUNC(penPos);
+
+ _camPos = if (!isNil QGVAR(startingPos)) then {
+ GVAR(startingPos)
+ } else {
+ getPos cameraOn
+ };
+
+ _camDir = if (!isNil QGVAR(startingDir)) then {
+ GVAR(startingDir)
+ } else {
+ 0
+ };
+
+ _camPos set [2, (_camPos select 2) + 2];
+ _cam = "camera" camCreate _camPos;
+ _cam setDir _camDir;
+ _cam cameraEffect ["internal", "back"];
+ _cam camSetFocus [-1, -1];
+ _cam camCommit 0;
+ showCinemaBorder false;
+ cameraEffectEnableHUD true;
+ setViewDistance 3000;
+
+ //variables
+ GVAR(cam) = _cam;
+ GVAR(LMB) = false;
+ GVAR(RMB) = false;
+ GVAR(vector) = [_camDir, 0, 0];
+ GVAR(fov) = 0.7;
+ GVAR(vision) = 0;
+ GVAR(moveScale) = 0.1;
+ GVAR(cameraOn) = true;
+ GVAR(focus) = [-1, -1];
+ GVAR(lock) = [-1];
+ GVAR(attach) = objNull;
+ GVAR(unit) = objNull;
+ GVAR(mouseBusy) = false;
+ GVAR(markers) = 3;
+ GVAR(accTime) = 1;
+ GVAR(third) = false;
+
+ //define only if doesn't exist (to preserve saved spots from a previous camera)
+ if (isNil QGVAR(savedSpots)) then {
+ GVAR(savedSpots) = [];
+ for "_i" from 0 to 11 do {GVAR(savedSpots) set [_i, []]};
+ };
+
+ if (isNil QGVAR(savedUnits)) then {
+ GVAR(savedUnits) = [];
+ for "_i" from 0 to 9 do {GVAR(savedUnits) set [_i, objNull]};
+ };
+
+ GVAR(keys) = [];
+ _DIKcodes = true call BIS_fnc_keyCode;
+ _DIKlast = _DIKcodes select (count _DIKcodes - 1);
+ for "_i" from 0 to (_DIKlast - 1) do {
+ GVAR(keys) set [_i, false];
+ };
+
+ _display = findDisplay 46;
+
+ GVAR(ehDraw3D) = addMissionEventhandler ["Draw3D", {['Draw3D', _this] call FUNC(draw3D)}];
+ addMissionEventHandler ["Ended", {if (!isNil QGVAR(cam)) then {["Exit"] call FUNC(camera)}}];
+ GVAR(ehKeyDown) = _display displayAddEventHandler ["keyDown", {['KeyDown', _this] call FUNC(camera)}];
+ GVAR(ehKeyUp) = _display displayAddEventHandler ["keyUp", {['KeyUp', _this] call FUNC(camera)}];
+ GVAR(ehMouseButtonDown) = _display displayAddEventHandler ["mouseButtonDown", {['MouseButtonDown', _this] call FUNC(camera)}];
+ GVAR(ehMouseButtonUp) = _display displayAddEventHandler ["mouseButtonUp", {['MouseButtonUp',_this] call FUNC(camera)}];
+ GVAR(ehMouseZChanged) = _display displayAddEventHandler ["mouseZChanged", {['MouseZChanged',_this] call FUNC(camera)}];
+ GVAR(ehMouseMoving) = _display displayAddEventHandler ["mouseMoving", {['Mouse',_this] call FUNC(camera)}];
+ GVAR(ehMouseHolding) =_display displayAddEventHandler ["mouseHolding", {['Mouse',_this] call FUNC(camera)}];
+
+ //remove mission layer
+ _displayMission = call (uiNamespace getVariable "BIS_fnc_displayMission");
+ _control = _displayMission displayCtrl 11400;
+ _control ctrlSetFade 1;
+ _control ctrlCommit 0;
+
+ //kill layers
+ cutText ["", "Plain"];
+ _layers = missionNamespace getVariable ["BIS_fnc_rscLayer_list", []];
+ for "_i" from 1 to (count _layers - 1) step 2 do {
+ (_layers select _i) cutText ["", "Plain"];
+ };
+
+ clearRadio;
+
+ //crosshair
+ _layer = [QGVAR(crosshair)] call BIS_fnc_rscLayer;
+ _layer cutRsc [QGVAR(crosshair), "PLAIN", 2, true];
+
+ //compass
+ _layer = [QGVAR(compass)] call BIS_fnc_rscLayer;
+ _layer cutRsc [QGVAR(compass), "PLAIN", 2, true];
+
+ //status
+ _layer = [QGVAR(status)] call BIS_fnc_rscLayer;
+ _layer cutRsc [QGVAR(status), "PLAIN", 2, true];
+
+ //help
+ _layer = [QGVAR(help)] call BIS_fnc_rscLayer;
+ preloadTitleRsc [QGVAR(help), "PLAIN", 0, true];
+
+ if (isClass (configFile >> "CfgPatches" >> "ace_nametags")) then {
+ GVAR(tags) = [EGVAR(nametags,showPlayerNames), EGVAR(nametags,showNamesForAI)];
+ EGVAR(nametags,showPlayerNames) = 0;
+ EGVAR(nametags,showNamesForAI) = false;
+ };
+
+ if (isClass (configFile >> "CfgPatches" >> "ace_interact_menu")) then {
+ [QGVAR(interactCondition), {false}] call EFUNC(common,addCanInteractWithCondition);
+ };
+
+ //add unit check, since if tracking were on it would already be present
+ if !GVAR(tracking) then {
+ [FUNC(checkUnits), 2] call CBA_fnc_addPerFrameHandler
+ };
+
+ [FUNC(cameraIntro), 1] call CBA_fnc_addPerFrameHandler;
+ };
+
+ //////////////////////////////////////////
+ case "Mouse": {
+ _mapOn = uiNamespace getVariable QGVAR(map);
+ if (!isNull _mapOn) exitWith {};
+
+ _keys = GVAR(keys);
+ _cam = GVAR(cam);
+ _dir = GVAR(vector) select 0;
+ _pitch = GVAR(vector) select 1;
+ _bank = GVAR(vector) select 2;
+ _camPos = getPosASL _cam;
+ _coef = (GVAR(moveScale) * (((getPosATL _cam) select 2) / 2)) min 50 max 0.001;
+
+ _move = {
+ _inPos = _this;
+ if !GVAR(cameraOn) exitWith {};
+ if (_inPos select 2 > 20000) then {_inPos set [2, 20000]};
+ _obj = GVAR(attach);
+ if !(isNull _obj) then {
+ if ((GVAR(lock) select 0) < 0) then {
+ _modelPos = _obj worldToModel (ASLtoATL _inPos);
+ _cam attachTo [_obj, _modelPos];
+ };
+ } else {
+ _cam setPosASL _inPos;
+ };
+ };
+
+ if (GVAR(LMB) || GVAR(RMB)) then {
+ if GVAR(mouseBusy) exitWith {};
+ _mX = (_this select 1) * (GVAR(accTime) max 0.05);
+ _mY = (_this select 2) * (GVAR(accTime) max 0.05);
+
+ if GVAR(RMB) then {
+
+ _dX = _mX;
+ _dY = -_mY;
+
+ _camPos = [_camPos, _dY, getDir _cam] call BIS_fnc_relPos;
+ _camPos = [_camPos, _dX, getDir _cam + 90] call BIS_fnc_relPos;
+
+ _camPos call _move;
+
+ } else {
+ if (GVAR(lock) select 0 > -1) exitWith {};
+ _dX = _mX / 50 * 180 * GVAR(fov);
+ _dY = -_mY / 50 * 180 * GVAR(fov);
+
+ if (_keys select DIK_LSHIFT) then {
+ _pitch = (_pitch + _dY) max -180 min 180;
+ _bank = (_bank + _dX) max -181 min 181;
+ if (_bank <= -181) then {_bank = 180} else {if (_bank >= 181) then {_bank = -180}};
+ } else {
+ _dir = _dir + _dX;
+ _pitch = (_pitch + _dY) max -90 min 90;
+ };
+ GVAR(vector) = [_dir, _pitch, _bank];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+ };
+
+ _camMove = {
+ _dX = _this select 0;
+ _dY = _this select 1;
+ _dZ = _this select 2;
+ _pos = getPosASL _cam;
+ _moveDir = (getDir _cam) + _dX * 90;
+ _camPos = [
+ (_pos select 0) + ((sin (_moveDir)) * _coef * _dY),
+ (_pos select 1) + ((cos (_moveDir)) * _coef * _dY),
+ (_pos select 2) + _dZ * _coef / 1.5
+ ];
+ //for some reason, at visual height = 0, cameras report 10cm higher than they actually are
+ _camPos set [2, (_camPos select 2) max (getTerrainHeightASL _camPos + 0.1)];
+
+ _camPos call _move;
+ };
+
+ _camRotate = {
+ if ((GVAR(lock) select 0) > -1) exitWith {};
+ _dX = (_this select 0) * GVAR(fov) * _rotMod;
+ _dY = (_this select 1) * GVAR(fov) * _rotMod;
+ _pitch = ((GVAR(vector) select 1) + _dY) max -90 min 90;
+ _bank = GVAR(vector) select 2;
+ _dir = _dir + _dX;
+ GVAR(vector) = [_dir, _pitch, _bank];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+
+ _camBank = {
+ if ((GVAR(lock) select 0) > -1) exitWith {};
+ _dZ = (_this select 0) * _rotMod;
+ _pitch = GVAR(vector) select 1;
+ _bank = ((GVAR(vector) select 2) + _dZ) max -181 min 181;
+ if (_bank == -181) then {_bank = 180} else {if (_bank == 181) then {_bank = -180}};
+ GVAR(vector) = [_dir, _pitch, _bank];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+
+ _numPad0 = _keys select DIK_NUMPAD0;
+ _numPadDel = _keys select DIK_DECIMAL;
+ _rotMod = if (_numPad0 && !_numPadDel) then {
+ 5
+ } else {
+ if (!_numPad0 && _numPadDel) then {0.1} else {1};
+ };
+
+ if (_keys select DIK_W) then {[0,1,0] call _camMove};
+ if (_keys select DIK_S) then {[0,-1,0] call _camMove};
+ if (_keys select DIK_A) then {[-1,1,0] call _camMove};
+ if (_keys select DIK_D) then {[1,1,0] call _camMove};
+
+ if (_keys select DIK_Q) then {[0,0,1] call _camMove};
+ if (_keys select DIK_Z) then {[0,0,-1] call _camMove};
+
+ if (_keys select DIK_NUMPAD1) then {[-1,-1,0] call _camRotate};
+ if (_keys select DIK_NUMPAD2) then {[+0,-1,0] call _camRotate};
+ if (_keys select DIK_NUMPAD3) then {[+1,-1,0] call _camRotate};
+ if (_keys select DIK_NUMPAD4) then {[-1,+0,0] call _camRotate};
+ if (_keys select DIK_NUMPAD6) then {[+1,+0,0] call _camRotate};
+ if (_keys select DIK_NUMPAD7) then {[-1,+1,0] call _camRotate};
+ if (_keys select DIK_NUMPAD8) then {[+0,+1,0] call _camRotate};
+ if (_keys select DIK_NUMPAD9) then {[+1,+1,0] call _camRotate};
+ if (_keys select DIK_DIVIDE) then {[-1] call _camBank};
+ if (_keys select DIK_MULTIPLY) then {[+1] call _camBank};
+
+ if (_keys select DIK_ADD) then {
+ GVAR(fov) = GVAR(fov) - (GVAR(fov) / 50 * _rotMod) max 0.01;
+ _cam camPrepareFOV GVAR(fov);
+ _cam camCommitPrepared 0;
+ };
+ if (_keys select DIK_SUBTRACT) then {
+ GVAR(fov) = GVAR(fov) + (GVAR(fov) / 50 * _rotMod) min 2;
+ _cam camPrepareFOV GVAR(fov);
+ _cam camCommitPrepared 0;
+ };
+
+ if (_keys select DIK_NUMPADENTER) then {
+ GVAR(fov) = 0.7;
+ _cam camPrepareFOV GVAR(fov);
+ _cam camCommitPrepared 0;
+ };
+
+ if (_keys select DIK_MINUS) then {
+ _cur = GVAR(focus) select 0;
+ if (_cur < 0) then {_cur = 1};
+ _cur = _cur - (_cur / 25) max 0.25;
+ GVAR(focus) = [_cur, 1.5];
+ _cam camSetFocus GVAR(focus);
+ _cam camCommit 0;
+ };
+
+ if (_keys select DIK_EQUALS) then {
+ _cur = GVAR(focus) select 0;
+ if (_cur < 0) then {_cur = 1};
+ _cur = _cur + (_cur / 25) min 5000;
+ GVAR(focus) = [_cur, 1.5];
+ _cam camSetFocus GVAR(focus);
+ _cam camCommit 0;
+ };
+
+ if (_keys select DIK_LBRACKET)then {
+ if (!isMultiplayer) then {
+ _cur = GVAR(accTime);
+ _cur = _cur - (_cur / 25) max 0;
+ GVAR(accTime) = _cur;
+ setAccTime GVAR(accTime);
+ };
+ };
+
+ if (_keys select DIK_RBRACKET)then {
+ if (!isMultiplayer) then {
+ _cur = GVAR(accTime);
+ _cur = _cur + (_cur / 25) min 4;
+ GVAR(accTime) = _cur;
+ setAccTime GVAR(accTime);
+ };
+ };
+ };
+
+ //////////////////////////////////////////
+ case "MouseButtonDown": {
+ _mapOn = uiNamespace getVariable QGVAR(map);
+ if (!isNull _mapOn) exitWith {};
+
+ _button = _this select 1;
+ _mX = _this select 2;
+ _mY = _this select 3;
+ _shift = _this select 4;
+ _ctrl = _this select 5;
+ _alt = _this select 6;
+
+ switch (_button) do {
+ case 0: {GVAR(LMB) = true};
+ case 1: {GVAR(RMB) = true};
+ };
+ };
+
+ //////////////////////////////////////////
+ case "MouseButtonUp": {
+ _mapOn = uiNamespace getVariable QGVAR(map);
+ if (!isNull _mapOn) exitWith {};
+
+ _button = _this select 1;
+ switch (_button) do {
+ case 0: {GVAR(LMB) = false};
+ case 1: {GVAR(RMB) = false};
+ };
+ };
+
+ //////////////////////////////////////////
+ case "MouseZChanged": {
+ _mapOn = uiNamespace getVariable QGVAR(map);
+ if (!isNull _mapOn) exitWith {};
+
+ _diff = _this select 1;
+ if (_diff > 0) then {
+ GVAR(moveScale) = GVAR(moveScale) + (GVAR(moveScale) / 10) min 1;
+ } else {
+ GVAR(moveScale) = GVAR(moveScale) - (GVAR(moveScale) / 10) max 0.001;
+ };
+ };
+
+ //////////////////////////////////////////
+ case "KeyDown": {
+ _key = _this select 1;
+ _shift = _this select 2;
+ _ctrl = _this select 3;
+ _alt = _this select 4;
+ _return = false;
+
+ GVAR(keys) set [_key, true];
+
+ _cam = GVAR(cam);
+ _camOn = GVAR(cameraOn);
+ _unit = GVAR(unit);
+ _lock = GVAR(lock) select 0;
+
+ _camPos = [getPos _cam, GVAR(vector), GVAR(fov), GVAR(focus)];
+
+ _camSaveSpot = {
+ _num = _this select 0;
+ if (!isNull GVAR(attach)) then {
+ _vector = _camPos select 1;
+ _dir = _vector select 0;
+ _vector set [0, _dir - (getDir GVAR(attach))];
+ _camPos set [1, _vector];
+ };
+ GVAR(savedSpots) set [_num, _camPos];
+ };
+
+ _camLoadSpot = {
+ _num = _this select 0;
+ _arr = GVAR(savedSpots) select _num;
+ if (count (_arr) > 0) then {
+ if (!_camOn) then {
+ ["Camera", ["Free"]] call FUNC(camera)
+ };
+ call _detach;
+ _cam setPos (_arr select 0);
+ _vector = _arr select 1;
+ [_cam, _vector] call BIS_fnc_setObjectRotation;
+ _cam camPrepareFOV (_arr select 2);
+ _cam camPrepareFocus (_arr select 3);
+ _cam camCommitPrepared 0;
+ GVAR(vector) = _vector;
+ };
+ };
+
+ _camSaveUnit = {
+ _num = _this select 0;
+
+ if (!isNull _unit) then {
+ _alreadySaved = GVAR(savedUnits) find _unit;
+ if (_alreadySaved > -1) then {
+ GVAR(savedUnits) set [_alreadySaved, objNull];
+ };
+ GVAR(savedUnits) set [_num, _unit]
+ };
+ };
+
+ _camLoadUnit = {
+ _num = _this select 0;
+ _unit = GVAR(savedUnits) select _num;
+ if (!isNull _unit) then {
+ if (_lock > -1) then {
+ ["Camera", ["Lock"]] call FUNC(camera)
+ };
+ if (GVAR(unit) == _unit) then {
+ call _detach;
+ if (_camOn) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ ["Camera", ["SwitchUnit"]] call FUNC(camera);
+ };
+ } else {
+ GVAR(unit) = _unit;
+ if ((GVAR(lock) select 0) > -1) then {["Camera", ["Lock"]] call FUNC(camera)};
+ if (!_camOn) then {
+ call _detach;
+ ["Camera", ["SwitchUnit"]] call FUNC(camera);
+ };
+ };
+ };
+ };
+
+ _detach = {
+ if (!isNull GVAR(attach)) then {
+ ["Camera", ["Attach"]] call FUNC(camera);
+ };
+ };
+
+ switch (_key) do {
+
+ case (DIK_F1): {if (_ctrl) then {[0] call _camSaveSpot} else {[0] call _camLoadSpot}; _return = true};
+ case (DIK_F2): {if (_ctrl) then {[1] call _camSaveSpot} else {[1] call _camLoadSpot}; _return = true};
+ case (DIK_F3): {if (_ctrl) then {[2] call _camSaveSpot} else {[2] call _camLoadSpot}; _return = true};
+ case (DIK_F4): {if (_ctrl) then {[3] call _camSaveSpot} else {[3] call _camLoadSpot}; _return = true};
+ case (DIK_F5): {if (_ctrl) then {[4] call _camSaveSpot} else {[4] call _camLoadSpot}; _return = true};
+ case (DIK_F6): {if (_ctrl) then {[5] call _camSaveSpot} else {[5] call _camLoadSpot}; _return = true};
+ case (DIK_F7): {if (_ctrl) then {[6] call _camSaveSpot} else {[6] call _camLoadSpot}; _return = true};
+ case (DIK_F8): {if (_ctrl) then {[7] call _camSaveSpot} else {[7] call _camLoadSpot}; _return = true};
+ case (DIK_F9): {if (_ctrl) then {[8] call _camSaveSpot} else {[8] call _camLoadSpot}; _return = true};
+ case (DIK_F10): {if (_ctrl) then {[9] call _camSaveSpot} else {[9] call _camLoadSpot}; _return = true};
+ case (DIK_F11): {if (_ctrl) then {[10] call _camSaveSpot} else {[10] call _camLoadSpot}; _return = true};
+ case (DIK_F12): {if (_ctrl) then {[11] call _camSaveSpot} else {[11] call _camLoadSpot}; _return = true};
+
+ case (DIK_1): {if (_ctrl) then {[0] call _camSaveUnit} else {[0] call _camLoadUnit}; _return = true};
+ case (DIK_2): {if (_ctrl) then {[1] call _camSaveUnit} else {[1] call _camLoadUnit}; _return = true};
+ case (DIK_3): {if (_ctrl) then {[2] call _camSaveUnit} else {[2] call _camLoadUnit}; _return = true};
+ case (DIK_4): {if (_ctrl) then {[3] call _camSaveUnit} else {[3] call _camLoadUnit}; _return = true};
+ case (DIK_5): {if (_ctrl) then {[4] call _camSaveUnit} else {[4] call _camLoadUnit}; _return = true};
+ case (DIK_6): {if (_ctrl) then {[5] call _camSaveUnit} else {[5] call _camLoadUnit}; _return = true};
+ case (DIK_7): {if (_ctrl) then {[6] call _camSaveUnit} else {[6] call _camLoadUnit}; _return = true};
+ case (DIK_8): {if (_ctrl) then {[7] call _camSaveUnit} else {[7] call _camLoadUnit}; _return = true};
+ case (DIK_9): {if (_ctrl) then {[8] call _camSaveUnit} else {[8] call _camLoadUnit}; _return = true};
+ case (DIK_0): {if (_ctrl) then {[9] call _camSaveUnit} else {[9] call _camLoadUnit}; _return = true};
+
+ case (DIK_NUMPAD5): {
+ _dir = getDir _cam;
+ if (!isNull GVAR(attach)) then {_dir = _dir - getDir GVAR(attach)};
+ GVAR(vector) = [_dir, 0, 0];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ GVAR(fov) = 0.7;
+ _cam camPrepareFOV GVAR(fov);
+ _cam camCommitPrepared 0;
+ };
+
+ case (DIK_NUMPADENTER): {_return = true};
+
+ case (DIK_NUMPAD0): {_return = true};
+
+ case (DIK_DECIMAL): {_return = true};
+
+ case (DIK_BACKSPACE): {
+ GVAR(focus) = if (!_shift) then {
+ [-1, 1];
+ } else {
+ [-1, -1];
+ };
+ _cam camPrepareFocus GVAR(focus);
+ _cam camCommitPrepared 0;
+ _return = true;
+ };
+
+ case (DIK_BACKSLASH): {
+ if (!isMultiplayer) then {
+ GVAR(accTime) = 1;
+ setAccTime GVAR(accTime);
+ };
+ };
+
+ case (DIK_GRAVE): {_return = true};
+
+ case (DIK_SPACE): {
+ if (!_camOn) exitWith {};
+ if (_ctrl) then {
+ ["Camera", ["Attach"]] call FUNC(camera);
+ } else {
+ ["Camera", ["Lock"]] call FUNC(camera);
+ };
+ };
+
+ case (DIK_LEFT): {
+ ["Camera", ["NewUnit", -1]] call FUNC(camera)
+ };
+
+ case (DIK_RIGHT): {
+ ["Camera", ["NewUnit", 1]] call FUNC(camera)
+ };
+
+ case (DIK_UP): {
+ if (isNull GVAR(unit)) exitWith {};
+ if (_lock > -1) then {["Camera", ["Lock"]] call FUNC(camera)};
+ call _detach;
+ if (_camOn) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ if GVAR(third) then {
+ ["Camera", ["First"]] call FUNC(camera);
+ };
+ };
+ };
+
+ case (DIK_DOWN): {
+ if (isNull GVAR(unit)) exitWith {};
+ if (_lock > -1) then {["Camera", ["Lock"]] call FUNC(camera)};
+ call _detach;
+ if (!_camOn) then {
+ if !GVAR(third) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ ["Camera", ["Free"]] call FUNC(camera);
+ };
+ };
+ };
+
+ case (DIK_T): {
+ GVAR(markers) = GVAR(markers) + 1;
+ if (GVAR(markers) > 3) then {GVAR(markers) = 0};
+ if (GVAR(markers) == 0) then {clearRadio};
+ };
+
+ case (DIK_U): {
+ _map = uiNameSpace getVariable [QGVAR(map), findDisplay 12202];
+ if (!isNull _map) exitWith {};
+
+ _overlay = uiNamespace getVariable [QGVAR(overlay), findDisplay 12200];
+ if (isNull _overlay) then {
+ createDialog QGVAR(overlay);
+ } else {
+ closeDialog 0;
+ };
+ };
+
+ case (DIK_X): {
+ _layer = [QGVAR(crosshair)] call BIS_fnc_rscLayer;
+ _xhair = uiNamespace getVariable QGVAR(crosshair);
+ if (isNull _xhair) then {
+ _layer cutRsc [QGVAR(crosshair), "PLAIN", 0, true];
+ call FUNC(crosshair);
+ } else {
+ _layer cutText ["", "PLAIN"];
+ };
+ };
+
+ case (DIK_C): {
+ _layer = [QGVAR(compass)] call BIS_fnc_rscLayer;
+ if (isNull (uiNamespace getVariable QGVAR(compass))) then {
+ _layer cutRsc [QGVAR(compass), "PLAIN", 0, true];
+ } else {
+ _layer cutText ["", "PLAIN"];
+ };
+
+ _layer = [QGVAR(status)] call BIS_fnc_rscLayer;
+ if (isNull (uiNamespace getVariable QGVAR(status))) then {
+ _layer cutRsc [QGVAR(status), "PLAIN", 0, true];
+ } else {
+ _layer cutText ["", "PLAIN"];
+ };
+ };
+
+ case (DIK_G): {
+ _vd = uiNamespace getVariable [QGVAR(vd), findDisplay 12201];
+ if (isNull _vd) then {
+ createDialog QGVAR(vd);
+ } else {
+ closeDialog 0;
+ }
+ };
+
+ case (DIK_H): {
+ _layer = [QGVAR(help)] call BIS_fnc_rscLayer;
+ if (isNull (uiNamespace getVariable QGVAR(help))) then {
+ _layer cutRsc [QGVAR(help), "PLAIN", 0, true];
+ } else {
+ _layer cutText ["", "PLAIN"];
+ };
+ };
+
+ case (DIK_M): {
+ _map = uiNameSpace getVariable [QGVAR(map), findDisplay 12202];
+ if (isNull _map) then {
+ createDialog QGVAR(map);
+ } else {
+ closeDialog 0;
+ };
+ };
+
+ case (DIK_N): {
+ GVAR(vision) = GVAR(vision) + 1;
+ if (GVAR(vision) > 4) then {GVAR(vision) = 0};
+ switch GVAR(vision) do {
+ case 0: {
+ camUseNVG false;
+ false SetCamUseTi 0;
+ };
+ case 1: {
+ camUseNVG true;
+ false SetCamUseTi 0;
+ };
+ case 2: {
+ camUseNVG false;
+ true SetCamUseTi 0;
+ };
+ case 3: {
+ camUseNVG false;
+ true SetCamUseTi 1;
+ };
+
+ case 4: {
+ camUseNVG false;
+ true SetCamUseTi 4;
+ };
+ };
+ };
+
+ case (DIK_ESCAPE): {
+ if !GVAR(noEscape) then {
+ _return = true;
+ _this spawn {
+ disableSerialization;
+ _display = _this select 0;
+ _message = ["Do you want to exit spectator?", "ACE Spectator", nil, true, _display] call BIS_fnc_guiMessage;
+ if (_message) then {["Exit"] call FUNC(camera)};
+ };
+ };
+ };
+ default {};
+ };
+
+ _return
+ };
+
+ //////////////////////////////////////////
+ case "KeyUp": {
+ GVAR(keys) set [_this select 1, false];
+ };
+
+ //////////////////////////////////////////
+ case "Camera": {
+
+ _mode = _this select 0;
+
+ _cam = GVAR(cam);
+ _camOn = GVAR(cameraOn);
+ _unit = GVAR(unit);
+ _lock = GVAR(lock) select 0;
+
+ _findTarget = {
+
+ _ret = [];
+ _screenPos = screenToWorld [0.5,0.5];
+ _camPosASL = getPosASL _cam;
+ _camPosReal = getPos _cam;
+ _endPosASL = [_screenPos select 0, _screenPos select 1, getTerrainHeightASL _screenPos];
+ _endPosReal = if (surfaceIsWater _endPosASL) then {_endPosASL} else {ASLtoATL _endPosASL};
+ _objs = lineIntersectsWith [_camPosASL, _endPosASL, objNull, objNull, true];
+
+ if (count _objs > 0) then { //if vehicle/object found
+ _obj = _objs select (count _objs - 1);
+ _ret = _obj;
+ } else { //check for units near endpoint instead
+ _units = allUnits;
+ if (count _units > 0) then {
+ _nearestUnit = _units select 0;
+ {if (_endPosReal distance _x < _endPosReal distance _nearestUnit) then {_nearestUnit = _x}} forEach _units;
+ _intersect = [_nearestUnit, "FIRE"] intersect [_camPosReal, _endPosReal];
+ if (count (_intersect) > 0) then {
+ _ret = _nearestUnit;
+ } else { //check for units near camera instead
+ _nearestUnit = _units select 0;
+ {if (_cam distance _x < _cam distance _nearestUnit) then {_nearestUnit = _x}} forEach _units;
+ _intersect = [_nearestUnit, "FIRE"] intersect [_camPosReal, _endPosReal];
+ if (count _intersect > 0) then {
+ _ret = _nearestUnit;
+ } else { //if nothing else, point at ground position
+ _ret = _endPosReal;
+ };
+ };
+ };
+ };
+ _ret
+ };
+
+ switch (_mode) do {
+
+ case "Free": {
+ GVAR(cameraOn) = true;
+ GVAR(third) = false;
+ detach _cam;
+ player switchCamera "Internal";
+ _cam cameraEffect ["Internal", "Back"];
+ cameraEffectEnableHUD true;
+ _dir = getDir _unit;
+ _pos = [_unit, -5, _dir] call BIS_fnc_relPos;
+ _pos set [2, ((getPos _unit) select 2) + 2];
+ _cam setPos _pos;
+ GVAR(vector) set [0, _dir];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+
+ case "First": {
+ if (_unit == player) exitWith {};
+ GVAR(cameraOn) = false;
+ GVAR(third) = false;
+ _cam attachTo [vehicle _unit, [0,0.1,0]];
+ _cam cameraEffect ["Terminate", "Back"];
+ vehicle _unit switchCamera "Internal";
+ };
+
+ case "Third": {
+ if (_unit == player) exitWith {};
+ GVAR(third) = true;
+ GVAR(cameraOn) = false;
+ if (!difficultyEnabled "3rdPersonView") then {
+ player switchCamera "Internal";
+ _cam cameraEffect ["Internal", "Back"];
+ cameraEffectEnableHUD true;
+ if (vehicle _unit == _unit) then {
+ _cam attachTo [_unit, [0.1, -2.4, 0.6], "head"];
+ } else {
+ _cam attachTo [vehicle _unit, [0, -7, 1.5]];
+ };
+ } else {
+ _cam attachTo [vehicle _unit, [0,0.1,0]];
+ _cam cameraEffect ["Terminate", "Back"];
+ vehicle _unit switchCamera "External";
+ };
+ };
+
+ case "NewUnit": {
+
+ _increment = _this select 1;
+ _units = [];
+ {
+ if (alive _x) then {_units pushBack _x};
+ } forEach GVAR(units);
+
+ _count = count _units;
+
+ if (_count > 0) then {
+
+ _index = _units find _unit;
+ _index = _index + _increment;
+ if (_index < 0) then {_index = _count - 1};
+ if (_index > (_count - 1)) then {_index = 0};
+
+ GVAR(unit) = _units select _index;
+ if (!_camOn) then {["Camera", ["SwitchUnit"]] call FUNC(camera)};
+ };
+ };
+
+ case "SwitchUnit": {
+ if !GVAR(third) then {
+ ["Camera", ["First"]] call FUNC(camera);
+ } else {
+ ["Camera", ["Third"]] call FUNC(camera);
+ };
+ };
+
+ case "Lock": {
+ if (_lock < 0) then {
+
+ _target = call _findTarget;
+
+ if (typeName _target == "OBJECT") then {
+ GVAR(lock) = [1, _target];
+ } else {
+ if (count _target > 0) then {
+ GVAR(lock) = [1, _target];
+ };
+ };
+
+ _cam camPrepareTarget (GVAR(lock) select 1);
+ _cam camCommitPrepared 0;
+ call FUNC(crosshair);
+ } else {
+
+ _dir = getDir _cam;
+ _pitchBank = _cam call BIS_fnc_getPitchBank;
+ GVAR(lock) = [-1];
+ _cam cameraEffect ["Terminate", "Back"];
+ camDestroy _cam;
+ _cam = "camera" camCreate (_camPos select 0);
+ [_cam, _camPos select 1] call BIS_fnc_setObjectRotation;
+ _cam camPrepareFOV (_camPos select 2);
+ _cam camPrepareFocus GVAR(focus);
+ _cam camCommitPrepared 0;
+ _cam cameraEffect ["Internal", "Back"];
+ cameraEffectEnableHUD true;
+ GVAR(cam) = _cam;
+ _obj = GVAR(attach);
+ if !(isNull _obj) then {
+ _modelPos = _obj worldToModel (_camPos select 0);
+ _cam attachTo [_obj, _modelPos];
+ _dir = _dir - getDir _obj;
+ };
+ GVAR(vector) = [_dir, _pitchBank select 0, 0];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ call FUNC(crosshair);
+ };
+ };
+
+ case "Attach": {
+ _dir = getDir _cam;
+ _pitchBank = _cam call BIS_fnc_getPitchBank;
+ if (isNull GVAR(attach)) then {
+ _target = call _findTarget;
+ if (typeName _target == "OBJECT") then {
+ if (_target isKindOf "AllVehicles") then {
+ _dir = _dir - getDir _target;
+ _cam attachTo [_target];
+ GVAR(attach) = _target;
+ call FUNC(crosshair);
+ };
+ };
+ } else {
+ detach _cam;
+ GVAR(attach) = objNull;
+ call FUNC(crosshair);
+ };
+ GVAR(vector) = [_dir, _pitchBank select 0, _pitchBank select 1];
+ [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+ };
+
+ call FUNC(crosshair);
+ };
+
+ //////////////////////////////////////////
+ case "Help": {
+
+ _dialog = _this;
+
+_c1Action = parseText "
+Camera:
+
+Move
+Pitch, Yaw
+Roll
+Slide
+Speed Multiplier
+Camera Mode
+Track Pos or Object
+Lock to Object
+Save Pos
+Recall Pos
+Optic Mode
+Focus
+Autofocus
+Disable Focus
+Pitch and Yaw
+Roll
+Pitch/Roll Reset
+Zoom
+Reset Zoom
+Pitch/Yaw/Roll/Zoom Fast
+Pitch/Yaw/Roll/Zoom Slow
+
+";
+
+_c1Control = parseText "
+
+
+W, A, S, D
+LMB + Mouse
+Shift + LMB + Mouse
+RMB + Mouse
+MouseWheel Up, Down
+Arrow Up, Down
+Space
+Ctrl + Space
+Ctrl + F1...F12
+F1...F12
+N
+Keyboard - and +
+Backspace
+Shift + Backspace
+Numpad 1...9
+Numpad / and *
+Numpad 5
+Numpad - and +
+Numpad Enter
+Numpad 0
+Numpad Decimal
+
+";
+
+_c2Action = parseText "
+Units:
+
+Cycle Unit
+Save Unit
+Recall Unit
+Unit List
+
+Display:
+
+Toggle Crosshair
+Toggle Status Bar
+View Distance Dialog
+Cycle Marker Mode
+Toggle Help
+
+";
+
+_c2Control = parseText "
+
+
+Arrow Left, Right
+Ctrl + 1...10
+1...10
+U
+
+
+
+X
+C
+G
+T
+H
+
+";
+
+if (!isMultiplayer) then {
+
+_add1 = parseText "
+
+Time:
+
+Faster, Slower
+Reset
+
+";
+
+_add2 = parseText "
+
+
+
+[ and ]
+\
+
+";
+
+ _c2Action = composeText [_c2Action, _add1];
+ _c2Control = composeText [_c2Control, _add2];
+};
+
+ (_dialog displayCtrl 1) ctrlSetStructuredText _c1Action;
+ (_dialog displayCtrl 2) ctrlSetStructuredText _c1Control;
+ (_dialog displayCtrl 3) ctrlSetStructuredText _c2Action;
+ (_dialog displayCtrl 4) ctrlSetStructuredText _c2Control;
+ };
+
+ //////////////////////////////////////////
+ case "Exit": {
+
+ if (isClass (configFile >> "CfgPatches" >> "ace_nametags")) then {
+ EGVAR(nametags,showPlayerNames) = GVAR(tags) select 0;
+ EGVAR(nametags,showNamesForAI) = GVAR(tags) select 1;
+ GVAR(tags) = nil;
+ };
+
+ if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then {
+ EGVAR(hearing,disableVolumeUpdate) = false;
+ };
+
+ if (isClass (configFile >> "CfgPatches" >> "ace_interact_menu")) then {
+ [QGVAR(interactCondition)] call EFUNC(common,removeCanInteractWithCondition);
+ };
+
+ GVAR(cam) cameraEffect ["terminate", "back"];
+ camUseNVG false;
+ false SetCamUseTi 0;
+ camDestroy GVAR(cam);
+ clearRadio;
+
+ GVAR(noEscape) = nil;
+ GVAR(cam) = nil;
+ GVAR(LMB) = nil;
+ GVAR(RMB) = nil;
+ GVAR(vector) = nil;
+ GVAR(fov) = nil;
+ GVAR(vision) = nil;
+ GVAR(moveScale) = nil;
+ GVAR(cameraOn) = nil;
+ GVAR(focus) = nil;
+ GVAR(lock) = nil;
+ GVAR(attach) = nil;
+ GVAR(unit) = nil;
+ GVAR(mouseBusy) = nil;
+ GVAR(markers) = nil;
+ GVAR(keys) = nil;
+ GVAR(accTime) = nil;
+
+ _display = findDisplay 46;
+
+ removeMissionEventHandler ["Draw3D", GVAR(ehDraw3D)];
+ _display displayRemoveEventHandler ["keyDown", GVAR(ehKeyDown)];
+ _display displayRemoveEventHandler ["keyUp", GVAR(ehKeyUp)];
+ _display displayRemoveEventHandler ["mouseButtonDown", GVAR(ehMouseButtonDown)];
+ _display displayRemoveEventHandler ["mouseButtonUp", GVAR(ehMouseButtonUp)];
+ _display displayRemoveEventHandler ["mouseZChanged", GVAR(ehMouseZChanged)];
+ _display displayRemoveEventHandler ["mouseMoving", GVAR(ehMouseMoving)];
+ _display displayRemoveEventHandler ["mouseHolding", GVAR(ehMouseHolding)];
+ GVAR(ehDraw3D) = nil;
+ GVAR(ehKeyDown) = nil;
+ GVAR(ehKeyUp) = nil;
+ GVAR(ehMouseButtonDown) = nil;
+ GVAR(ehMouseButtonUp) = nil;
+ GVAR(ehMouseZChanged) = nil;
+ GVAR(ehMouseMoving) = nil;
+ GVAR(ehMouseHolding) = nil;
+
+ _layers = missionNamespace getVariable ["BIS_fnc_rscLayer_list", []];
+
+ for "_i" from 1 to (count _layers - 1) step 2 do {
+ (_layers select _i) cutText ["", "Plain"];
+ };
+
+ if (!isMultiplayer) then {setAccTime 1};
+ ACE_player switchCamera "Internal";
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_cameraIntro.sqf b/addons/spectator/functions/fnc_cameraIntro.sqf
new file mode 100644
index 0000000000..22bfa27d57
--- /dev/null
+++ b/addons/spectator/functions/fnc_cameraIntro.sqf
@@ -0,0 +1,28 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Curtain, sound, and text intro when camera starts.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_camIntro;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+999999 cutText ["", "BLACK IN", 2];
+2 fadeSound 1;
+
+["Press H for spectator controls", 2] call EFUNC(common,displaytextstructured);
+
+[_this select 1] call CBA_fnc_removePerFrameHandler;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_canSpectateUnit.sqf b/addons/spectator/functions/fnc_canSpectateUnit.sqf
new file mode 100644
index 0000000000..1ce9f32d97
--- /dev/null
+++ b/addons/spectator/functions/fnc_canSpectateUnit.sqf
@@ -0,0 +1,30 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Check if a unit is suitable to spectate.
+
+ Arguments:
+ 0: Unit to check
+
+ Example:
+ [unit] call ace_spectator_canSpectateUnit;
+
+ Return Value:
+ Whether is suitable to spectate
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_unit = _this select 0;
+
+if (_unit distance GVAR(penPos) < 200) exitWith {false};
+if (_unit distance [0,0,0] < 100) exitWith {false};
+if (!GVAR(AI) && !isPlayer _unit) exitWith {false};
+if (GVAR(limitSide) && (([_unit] call FUNC(unitSide)) != GVAR(playerSide))) exitWith {false};
+
+true
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_checkUnits.sqf b/addons/spectator/functions/fnc_checkUnits.sqf
new file mode 100644
index 0000000000..5d62aeed12
--- /dev/null
+++ b/addons/spectator/functions/fnc_checkUnits.sqf
@@ -0,0 +1,37 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Compile array of units to spectate.
+
+ Arguments:
+ None.
+
+ Example:
+ call ace_spectator_fnc_checkUnits;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_units = allUnits;
+_units append allDead;
+GVAR(units) = [];
+
+{
+ _listed = _x getVariable [QGVAR(listed), false];
+ if (!_listed) then {
+ [_x] call FUNC(unitVar);
+ _x addEventHandler ["Killed", {_this call FUNC(killed)}];
+ _x addEventHandler ["Respawn", {_this call FUNC(respawn)}];
+ _x setVariable [QGVAR(listed), true];
+ };
+
+ if ([_x] call FUNC(canSpectateUnit)) then {GVAR(units) pushback _x};
+} forEach _units;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_compass.sqf b/addons/spectator/functions/fnc_compass.sqf
new file mode 100644
index 0000000000..4120cd996f
--- /dev/null
+++ b/addons/spectator/functions/fnc_compass.sqf
@@ -0,0 +1,59 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Orient and set compass.
+
+ Arguments:
+ 0: Compass
+
+ Example:
+ [display] call ace_spectator_fnc_compass;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+#define RESUNITS_X safeZoneW / 100
+#define CENTRE safeZoneX + safeZoneW / 2
+#define COMPASS_W RESUNITS_X * 20
+#define COMPASS_X CENTRE - COMPASS_W / 2
+#define ARC_W COMPASS_W / 2
+#define DEGUNIT COMPASS_W / 180
+
+_dialog = _this select 0;
+
+_Q1 = _dialog displayCtrl 1;
+_Q2 = _dialog displayCtrl 2;
+_Q3 = _dialog displayCtrl 3;
+_Q4 = _dialog displayCtrl 4;
+_qOrder = [];
+
+_dir = if GVAR(cameraOn) then {getDir GVAR(cam)} else {getDir GVAR(unit)};
+_angleFromCentre = _dir - floor(_dir / 90) * 90;
+_leftEdgePos = _angleFromCentre * DEGUNIT;
+
+_positions = [
+ [CENTRE - _leftEdgePos - ARC_W, safeZoneY],
+ [CENTRE - _leftEdgePos, safeZoneY],
+ [CENTRE - _leftEdgePos + ARC_W, safeZoneY],
+ [0, safeZoneY - 1]
+];
+
+_qOrder = switch (true) do {
+ case ((_dir >= 0) && (_dir < 90)): {[_Q4, _Q1, _Q2, _Q3]};
+ case ((_dir >= 90) && (_dir < 180)): {[_Q1, _Q2, _Q3, _Q4]};
+ case ((_dir >= 180) && (_dir < 270)): {[_Q2, _Q3, _Q4, _Q1]};
+ case (_dir >= 270): {[_Q3, _Q4, _Q1, _Q2]};
+};
+
+{
+ _x ctrlSetPosition (_positions select _forEachIndex);
+ _x ctrlCommit 0;
+} forEach _qOrder;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_crosshair.sqf b/addons/spectator/functions/fnc_crosshair.sqf
new file mode 100644
index 0000000000..80a12cd668
--- /dev/null
+++ b/addons/spectator/functions/fnc_crosshair.sqf
@@ -0,0 +1,29 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Automatically set crosshair colour.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_crosshair;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_xhair = uiNamespace getVariable QGVAR(crosshair);
+if (!isNull _xhair) then {
+ _colour = if ((GVAR(lock) select 0) > -1) then {[1,0,0,0.8]} else {
+ if (!isNull GVAR(attach)) then {[1,1,0,0.8]} else {[1,1,1,0.8]};
+ };
+ (_xhair displayCtrl 0) ctrlSetTextColor _colour;
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_draw3D.sqf b/addons/spectator/functions/fnc_draw3D.sqf
new file mode 100644
index 0000000000..26eb319f73
--- /dev/null
+++ b/addons/spectator/functions/fnc_draw3D.sqf
@@ -0,0 +1,34 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw3D EH for spectator.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_draw3D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_map = uiNameSpace getVariable QGVAR(map);
+if (!isNull _map) exitWith {};
+
+_compass = uiNamespace getVariable QGVAR(compass);
+_status = uiNamespace getVariable QGVAR(status);
+if (!isNull _compass) then {[_compass] call FUNC(compass)};
+if (!isNull _status) then {[_status] call FUNC(status)};
+
+if (GVAR(markers) > 0) then {
+ call FUNC(drawMines3D);
+ call FUNC(drawUnits3D);
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_drawMines2D.sqf b/addons/spectator/functions/fnc_drawMines2D.sqf
new file mode 100644
index 0000000000..c77c589529
--- /dev/null
+++ b/addons/spectator/functions/fnc_drawMines2D.sqf
@@ -0,0 +1,43 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw mines on spectator map.
+
+ Arguments:
+ 0: Map control
+ 1: Zoom level
+
+ Example:
+ [map, zoomlevel] call ace_spectator_fnc_drawMines2D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+#define SCALE 5 * safeZoneH / 100
+#define MIN 300 * SCALE
+#define TEXTURE "\A3\ui_f\data\map\markers\military\triangle_CA.paa"
+
+_map = _this select 0;
+_zoom = _this select 1;
+
+_size = SCALE / _zoom;
+_textSize = ((1/4 * _size) max (SCALE / 2) min (SCALE / 1.5)) / 2;
+_iconSize = (20 * _size) max SCALE min MIN;
+_showText = (GVAR(markers) > 1);
+
+{
+ _name = "";
+ if (_showText) then {
+ _magName = getText (configFile >> "CfgAmmo" >> (typeOf _x) >> "defaultMagazine");
+ _name = getText (configFile >> "CfgMagazines" >> _magName >> "displayName");
+ };
+ _map drawIcon [TEXTURE, [1,0.5,0,1], getPos _x, _iconSize, _iconSize, getDir _x, _name, 1, _textSize, "PuristaMedium"];
+} forEach allMines;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_drawMines3D.sqf b/addons/spectator/functions/fnc_drawMines3D.sqf
new file mode 100644
index 0000000000..7183db574f
--- /dev/null
+++ b/addons/spectator/functions/fnc_drawMines3D.sqf
@@ -0,0 +1,55 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw mines in 3D.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_drawMines3D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+#define SCALE safeZoneH / 100
+#define TEXTMAX (1.5 * SCALE)
+#define TEXTMIN 6 * SCALE
+#define ICONMAX (30 * SCALE)
+#define ICONMIN (120 * SCALE)
+#define TEXTURE "\A3\ui_f\data\map\markers\military\triangle_CA.paa"
+
+_cam = GVAR(cam);
+_showText = (GVAR(markers) > 1);
+
+{
+ _pos = getPos _x;
+ _dist = (_cam distance _pos) + 0.1;
+
+ if (_dist < 2000) then {
+
+ _distScaled = SCALE / sqrt(_dist);
+ _iconScale = 300 * _distScaled;
+ //_iconSize = (20 * _size) max _scale min _min;
+ _iconSize = _iconScale max ICONMAX min ICONMIN;
+ _textSize = 0;
+
+ if (_showText) then {
+ _textScale = 10 * _distScaled;
+ _textSize = _textScale max TEXTMAX min TEXTMIN;
+ };
+
+ _magName = getText (configFile >> "CfgAmmo" >> (typeOf _x) >> "defaultMagazine");
+ _name = getText (configFile >> "CfgMagazines" >> _magName >> "displayName");
+
+ drawIcon3D [TEXTURE, [1,0.5,0,1], _pos, _iconSize, _iconSize, 0, _name, 1, _textSize, "PuristaMedium"];
+ };
+} forEach allMines;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_drawTracks2D.sqf b/addons/spectator/functions/fnc_drawTracks2D.sqf
new file mode 100644
index 0000000000..32b6d58ae8
--- /dev/null
+++ b/addons/spectator/functions/fnc_drawTracks2D.sqf
@@ -0,0 +1,56 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw unit tracks in spectator map.
+
+ Arguments:
+ 0: Map control
+ 1: Zoom level
+
+ Example:
+ [map, zoomlevel] call ace_spectator_fnc_drawTracks2D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_map = _this select 0;
+_zoom = _this select 1;
+
+{
+ _unit = _x select 0;
+
+ _info = [_unit] call FUNC(unitInfo);
+ _colour = _info select 2;
+
+ if (_unit == GVAR(unit)) then {_colour = [1,1,0,_colour select 3]};
+
+ _positions = _x select 1;
+ _count = count _positions;
+ _step = floor (10 * _zoom) min 3 max 1;
+ _lastIndex = 0;
+
+ if (_count > 1) then {
+ for "_i" from 0 to (_count - 1) step _step do {;
+ if (_i > 0 && _i < _count) then {
+ _pos1 = _positions select _i;
+ _pos2 = _positions select (_i - _step);
+ _lastIndex = _i;
+ _map drawLine [_pos1, _pos2, _colour];
+ };
+ };
+ };
+
+ //((_count - _step + _count mod _step) max 0)
+ if (alive _unit) then {
+ _map drawLine [_positions select _lastIndex, getPosVisual _unit, _colour];
+ };
+
+} forEach GVAR(trackingArray);
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_drawUnits2D.sqf b/addons/spectator/functions/fnc_drawUnits2D.sqf
new file mode 100644
index 0000000000..858b418c2f
--- /dev/null
+++ b/addons/spectator/functions/fnc_drawUnits2D.sqf
@@ -0,0 +1,81 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw unit icons on spectator map.
+
+ Arguments:
+ 0: Map control
+ 1: Zoom level
+
+ Example:
+ [map, zoomlevel] call ace_spectator_fnc_drawUnits2D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+#define SCALE 5 * safeZoneH / 100
+#define MIN 300 * SCALE
+
+_map = _this select 0;
+_zoom = _this select 1;
+
+_topIcon = [];
+
+_size = SCALE / _zoom;
+_showText = (GVAR(markers) > 1);
+_textSize = (0.25 * _size) max (SCALE / 2) min (SCALE / 1.5);
+
+{
+ _unit = _x;
+ _isTarget = (_unit == GVAR(unit));
+
+ if (true) then {
+
+ _veh = vehicle _unit;
+ _inVeh = (_veh != _unit);
+ if (!_isTarget && _inVeh && !(_unit == ((crew _veh) select 0))) exitWith {};
+ if (!_isTarget && _inVeh && (GVAR(unit) in (crew _veh))) exitWith {};
+
+ _obj = if (_inVeh) then {_veh} else {_unit};
+ _pos = getPosVisual _obj;
+ _dir = getDir _obj;
+
+ _info = [_unit] call FUNC(unitInfo);
+ _name = _info select 0;
+ _colour = _info select 2;
+
+ _icon = getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "Icon");
+ _iconSize = 0;
+ _iconText = "";
+
+ if (_inVeh) then {
+ _iconSize = (50 * _size) max SCALE min (MIN * 2);
+ if (_showText) then {
+ _iconText = "[" + (getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "displayName")) + "] " + _name;
+ };
+ } else {
+ _iconSize = (50 * _size) max SCALE min MIN;
+ if (_showText) then {
+ _iconText = _name;
+ };
+ };
+
+ if (_isTarget) exitWith {
+ _topIcon = [_icon, [1,1,0,1], _pos, _iconSize, _iconSize, _dir, _iconText, 1, _textSize, "PuristaBold", "RIGHT"];
+ };
+
+ _map drawIcon [_icon, _colour, _pos, _iconSize, _iconSize, _dir, _iconText, 1, _textSize, "PuristaMedium", "RIGHT"]
+ };
+} forEach GVAR(units);
+
+if (count _topIcon > 0) then {
+ _map drawIcon _topIcon;
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_drawUnits3D.sqf b/addons/spectator/functions/fnc_drawUnits3D.sqf
new file mode 100644
index 0000000000..709e7d8fff
--- /dev/null
+++ b/addons/spectator/functions/fnc_drawUnits3D.sqf
@@ -0,0 +1,97 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Draw unit icons in 3D.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_drawUnits3D;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+#define SCALE safeZoneH / 100
+#define TEXTMAX (1.5 * SCALE)
+#define TEXTMIN 6 * SCALE
+#define ICONMAX (30 * SCALE)
+#define ICONMIN (120 * SCALE)
+
+_cam = GVAR(cam);
+_showText = (GVAR(markers) > 1);
+_topIcon = [];
+
+{
+ _unit = _x;
+
+ if (true) then {
+ _veh = vehicle _unit;
+ _inVeh = (_veh != _unit);
+ _cmdr = if (_inVeh && (_unit == ((crew _veh) select 0))) then {true} else {false};
+
+ _obj = if (_inVeh && _cmdr) then {_veh} else {_unit};
+ _pos = if (surfaceIsWater getPos _obj) then {getPosASLVisual _obj} else {getPosATLVisual _obj};
+ _dist = (_cam distance _pos) + 0.1;
+
+ _isTarget = (_unit == GVAR(unit));
+
+ //exit if too far
+ if (_dist > 2000 && !_isTarget) exitWith {};
+
+ //exit if target not on screen
+ if ((count (worldToScreen _pos) < 1) && !_isTarget) exitWith {};
+
+ _info = [_unit] call FUNC(unitInfo);
+ _name = _info select 0;
+ _colour = _info select 2;
+
+ _pos set [2, (_pos select 2) + 3];
+ _distScaled = SCALE / sqrt(_dist);
+
+ _icon = "";
+ _iconScale = 300 * _distScaled;
+ _iconSize = _iconScale max ICONMAX min ICONMIN;
+
+ _text = if (_showText) then {_name} else {""};
+ _textScale = 10 * _distScaled;
+ _textSize = _textScale max TEXTMAX min TEXTMIN;
+
+ if (_inVeh) then {
+ if (_cmdr) then {
+ _icon = getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "Icon");
+ _text = if (_showText) then {
+ "[" + (getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "displayName")) + "] " + _text
+ } else {""};
+ _pos set [2, (_pos select 2) + 3];
+ } else {
+ _iconSize = 0;
+ _textSize = if (_dist < 25) then {_textSize / 1.5} else {0};
+ };
+ } else {
+ _icon = getText (configFile >> "CfgVehicles" >> (typeOf _unit) >> "Icon");
+ };
+
+ if (GVAR(markers) > 2) then {
+ _text = _text + " [" + str ceil(_dist) + "]";
+ };
+
+ if (_isTarget) exitWith {
+ _topIcon = [_icon, [1,1,0,1], _pos, _iconSize, _iconSize, 0, _text, 2, _textSize, "PuristaBold", "CENTER", true];
+ };
+
+ drawIcon3D [_icon, _colour, _pos, _iconSize, _iconSize, 0, _text, 2, _textSize, "PuristaMedium"];
+ };
+} forEach GVAR(units);
+
+if ((count _topIcon > 0) && GVAR(cameraOn)) then {
+ drawIcon3D _topIcon;
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_killed.sqf b/addons/spectator/functions/fnc_killed.sqf
new file mode 100644
index 0000000000..4774476be4
--- /dev/null
+++ b/addons/spectator/functions/fnc_killed.sqf
@@ -0,0 +1,65 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Killed EH for remote units.
+
+ Arguments:
+ 0: Unit
+ 1: Killer
+
+ Example:
+ [unit, killer] call ace_spectator_fnc_killed;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_unit = _this select 0;
+_killer = _this select 1;
+
+if (isNil "_unit") exitWith {};
+if (isNil QGVAR(cam)) exitWith {};
+if (isNull _unit) exitWith {};
+
+if (!isNull _killer) then {
+ if (GVAR(markers) > 2 && !difficultyEnabled "deathMessages") then {
+ _nameUnit = name _unit;
+ _nameKiller = name _killer;
+
+ _text = if (_killer == _unit) then {
+ format ["%1 died", _nameUnit]
+ } else {
+ format ["%2 killed by %1", _nameUnit, _nameKiller]
+ };
+ systemChat _text;
+ };
+};
+
+if (_unit == GVAR(unit) && !GVAR(cameraOn)) then {
+ ["Camera", ["Free"]] call FUNC(camera);
+ GVAR(unit) = objNull;
+};
+
+_savedUnit = GVAR(savedUnits) find _unit;
+if (_savedUnit > -1) then {
+ GVAR(savedUnits) set [_savedUnit, objNull];
+};
+
+if (!isNil QGVAR(trackingArray)) then {
+ _pos = getPos _unit;
+ _pos resize 2;
+ _index = -1;
+ {if ((_x select 0) == _unit) then {_index = _forEachIndex}} forEach GVAR(trackingArray);
+ _unitArray = GVAR(trackingArray) select _index;
+ _tracks = _unitArray select 1;
+ _tracks pushBack _pos;
+ _unitArray set [1, _tracks];
+ GVAR(trackingArray) set [_index, _unitArray];
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_map.sqf b/addons/spectator/functions/fnc_map.sqf
new file mode 100644
index 0000000000..b58fa8ce2b
--- /dev/null
+++ b/addons/spectator/functions/fnc_map.sqf
@@ -0,0 +1,156 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Manage spectator map.
+
+ Arguments:
+ 0: Mode
+ 1: Elements (depending on situation)
+
+ Example:
+ ["Init", [map]] call ace_spectator_fnc_map;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+#include "\a3\editor_f\Data\Scripts\dikCodes.h"
+
+_mode = _this select 0;
+_this = _this select 1;
+
+switch _mode do {
+
+ case "Init": {
+ _map = _this displayCtrl 1;
+
+ if (isNil QGVAR(mapPos)) then {
+ GVAR(mapPos) = [(GVAR(penPos) select 0) / 4, (GVAR(penPos) select 1) / 4];
+ };
+
+ if (isNil QGVAR(mapZoom)) then {
+ GVAR(mapZoom) = 0.75;
+ };
+
+ _map ctrlMapAnimAdd [0, GVAR(mapZoom), GVAR(mapPos)];
+ ctrlMapAnimCommit _map;
+ setMousePosition [0.5, 0.5];
+
+ _map ctrlAddEventHandler ["Draw", {['Draw', _this] call FUNC(map)}];
+ _map ctrlAddEventHandler ["MouseButtonDblClick", {['Click', _this] call FUNC(map)}];
+ };
+
+ case "Close": {
+ _map = _this displayCtrl 1;
+ GVAR(mapPos) = _map ctrlMapScreenToWorld [0.5,0.5];
+ GVAR(mapZoom) = ctrlMapScale _map;
+ };
+
+ case "Draw": {
+ _map = _this select 0;
+ _zoom = ctrlMapScale _map;
+
+ if (GVAR(markers) > 0) then {
+ if ((GVAR(markers) > 2) && GVAR(tracking)) then {
+ [_map, _zoom] call FUNC(drawTracks2D);
+ };
+ [_map, _zoom] call FUNC(drawMines2D);
+ [_map, _zoom] call FUNC(drawUnits2D);
+ };
+
+ if (GVAR(cameraOn)) then {
+ _scale = 5 * safeZoneH / 100;
+ _map drawIcon ["\A3\ui_f\data\gui\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa", [1,1,1,1], getPos GVAR(cam), 500 * _scale, 500 * _scale, getDir GVAR(cam), "", 0, 0, "PuristaMedium"];
+ };
+ };
+
+ case "Click": {
+ _map = _this select 0;
+ _button = _this select 1;
+ _shift = _this select 4;
+ _mapPos = _map ctrlMapScreenToWorld [_this select 2, _this select 3];
+
+ if (_shift) then {
+ if (GVAR(cameraOn)) then {
+ _dir = [getPos GVAR(cam), _mapPos] call BIS_fnc_dirTo;
+ GVAR(vector) set [0, _dir];
+ [GVAR(cam), GVAR(vector)] call BIS_fnc_setObjectRotation;
+ };
+ } else {
+
+ _newUnit = objNull;
+
+ _scale = ctrlMapScale _map;
+ _radius = _scale * 250;
+ _units = [];
+
+ //find units near spot, ignoring height (necessary since nearestObjects takes height into account)
+ {
+ if (alive _x) then {
+ _pos = getPos _x;
+ _pos set [2, 0];
+ if (_pos distance _mapPos <= _radius) then {
+ _units pushBack _x;
+ };
+ };
+ } forEach GVAR(units);
+
+ //find closest unit to spot
+ if (count _units > 0) then {
+ _nearest = 0;
+ for "_i" from 1 to (count _units - 1) do {
+ if (((_units select _i) distance _mapPos) < ((_units select _nearest) distance _mapPos)) then {
+ _nearest = _i;
+ };
+ };
+ _newUnit = _units select _nearest;
+ };
+
+ if (!isNull _newUnit) then {
+
+ if (vehicle _newUnit != _newUnit) then {
+ _crew = crew (vehicle _newUnit);
+ _newUnit = _crew select 0;
+ };
+
+ GVAR(unit) = _newUnit;
+ if (GVAR(cameraOn)) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ if (GVAR(third)) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ ["Camera", ["First"]] call FUNC(camera);
+ };
+ };
+ } else {
+
+ if (!GVAR(cameraOn)) then {
+ ["Camera", ["Free"]] call FUNC(camera);
+ };
+ _mapPos set [2, 10];
+ GVAR(cam) setPosATL _mapPos;
+ };
+ };
+ };
+
+ case "KeyDown": {
+ _key = _this select 1;
+ _shift = _this select 2;
+ _ctrl = _this select 3;
+ _alt = _this select 4;
+ _return = false;
+
+ switch (_key) do {
+ case (DIK_DELETE): {_return = true};
+ };
+
+ _return
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_moduleSpectator.sqf b/addons/spectator/functions/fnc_moduleSpectator.sqf
new file mode 100644
index 0000000000..a371327b23
--- /dev/null
+++ b/addons/spectator/functions/fnc_moduleSpectator.sqf
@@ -0,0 +1,28 @@
+/*
+ * Author: esteldunedain
+ * Initializes the addon module.
+ *
+ * Arguments:
+ * Whatever the module provides.
+ *
+ * Return Value:
+ * None
+ */
+
+#include "script_component.hpp"
+
+PARAMS_3(_logic,_units,_activated);
+
+if !(_activated) exitWith {};
+
+[_logic, QGVAR(enabled), "SpectatorEnabled"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(limitSide), "SpectatorPlayerSide"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(AI), "SpectatorAI"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(tracking), "SpectatorTracking"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(modulePos), "SpectatorPos"] call EFUNC(common,readSettingFromModule);
+[_logic, QGVAR(endMission), "SpectatorEnd"] call EFUNC(common,readSettingFromModule);
+
+if GVAR(modulePos) then {
+ GVAR(startingPos) = getPosATL _logic;
+ GVAR(startingDir) = getDir _logic;
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_overlay.sqf b/addons/spectator/functions/fnc_overlay.sqf
new file mode 100644
index 0000000000..d998b9a3b2
--- /dev/null
+++ b/addons/spectator/functions/fnc_overlay.sqf
@@ -0,0 +1,106 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Spectator unit list.
+
+ Arguments:
+ 0: Specific function to use
+ 1: Function params
+
+ Example:
+ ["Init", [display]] call ace_spectator_fnc_overlay;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_mode = _this select 0;
+_this = _this select 1;
+
+switch _mode do {
+
+ case "Init": {
+
+ _display = _this select 0;
+ _ctrl = _display displayCtrl 0;
+ _count = _ctrl tvCount [];
+ for "_i" from 0 to _count do {
+ _ctrl tvDelete [_x];
+ };
+
+ _ctrl tvAdd [[], "Blufor"];
+ _ctrl tvAdd [[], "Opfor"];
+ _ctrl tvAdd [[], "Independent"];
+ _ctrl tvAdd [[], "Civilian"];
+
+ _unitList = [];
+
+ {
+ _units = units _x;
+ private ["_groupNum"];
+ {
+ if ((GVAR(units) find _x > -1) && alive _x) then {
+ _info = [_x] call FUNC(unitInfo);
+ _text = _info select 0;
+ _team = _info select 1;
+ _side = switch (_team) do {
+ case BLUFOR: {0};
+ case OPFOR: {1};
+ case INDEPENDENT: {2};
+ case CIVILIAN: {3};
+ };
+
+ _icon = getText (configFile >> "CfgVehicles" >> (typeOf _x) >> "Icon");
+ _picture = "\a3\ui_f\data\map\VehicleIcons\" + _icon + "_ca.paa";
+ _treeIndex = [];
+ _unitList pushBack _x;
+
+ _savedUnit = GVAR(savedUnits) find _x;
+ if (_savedUnit > -1) then {_text = _text + " (#" + str (_savedUnit + 1) + ")"};
+
+ if (_forEachIndex == 0) then {
+ _groupNum = _ctrl tvAdd [[_side], _text];
+ _treeIndex = [_side, _groupNum];
+ } else {
+ _num = _ctrl tvAdd [[_side, _groupNum], _text];
+ _treeIndex = [_side, _groupNum, _num];
+ };
+
+ _ctrl tvSetPicture [_treeIndex, _picture];
+ _ctrl tvSetData [_treeIndex, [_x] call FUNC(unitVar)];
+ _unitList pushBack _treeIndex;
+ };
+ } forEach _units;
+ } forEach allGroups;
+
+ if (!isNull GVAR(unit)) then {
+ if (alive GVAR(unit)) then {
+ _treeIndex = _unitList select ((_unitList find GVAR(unit)) + 1);
+ _ctrl tvSetCurSel _treeIndex;
+ };
+ };
+ };
+
+ case "Select": {
+
+ _ctrl = _this select 0;
+ _selection = _this select 1;
+ if (count _selection < 2) exitWith {};
+
+ _str = _ctrl tvData _selection;
+ _unit = missionNamespace getVariable _str;
+ GVAR(unit) = _unit;
+ if (GVAR(cameraOn)) then {
+ ["Camera", ["Third"]] call FUNC(camera);
+ } else {
+ ["Camera", ["SwitchUnit"]] call FUNC(camera);
+ };
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_penPos.sqf b/addons/spectator/functions/fnc_penPos.sqf
new file mode 100644
index 0000000000..a176d3e811
--- /dev/null
+++ b/addons/spectator/functions/fnc_penPos.sqf
@@ -0,0 +1,33 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Determine spec pen position.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_penPos;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_mapSize = (configFile >> "CfgWorlds" >> worldName >> "mapSize");
+_worldEdge = if (isNumber _mapSize) then {getNumber _mapSize} else {32768};
+_pos = [_worldEdge * 2, _worldEdge * 2];
+
+if (surfaceisWater _pos) then {
+ _pos set [2, -1.4];
+ GVAR(penPos) = ASLtoATL _pos;
+} else {
+ _pos set [2, 0];
+ GVAR(penPos) = _pos;
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_respawn.sqf b/addons/spectator/functions/fnc_respawn.sqf
new file mode 100644
index 0000000000..dba2f6a850
--- /dev/null
+++ b/addons/spectator/functions/fnc_respawn.sqf
@@ -0,0 +1,25 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Respawn EH for remote clients.
+
+ Arguments:
+ 0: Unit
+
+ Example:
+ ["Init", [false]] call ace_spectator_fnc_camera;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_unit = _this select 0;
+_unit setVariable [QGVAR(name), name _unit, true];
+//_unit setVariable [QGVAR(listed), false];
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_sideColour.sqf b/addons/spectator/functions/fnc_sideColour.sqf
new file mode 100644
index 0000000000..1262ae5b07
--- /dev/null
+++ b/addons/spectator/functions/fnc_sideColour.sqf
@@ -0,0 +1,66 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Determine side colour for spectator GUI.
+
+ Arguments:
+ 0: Side
+
+ Example:
+ [0 call ace_spectator_fnc_sideColour;
+
+ Return Value:
+ Colour
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+#define FACTOR 1.3
+#define GETCOLOUR(a,b) (profileNameSpace getVariable [QUOTE(a), b])
+
+PARAMS_1(_side);
+
+_colour = switch _side do {
+ case BLUFOR: {
+ [
+ GETCOLOUR('Map_BLUFOR_R', 0),
+ GETCOLOUR('Map_BLUFOR_G', 0.3),
+ GETCOLOUR('Map_BLUFOR_B', 0.6)
+ ]
+ };
+
+ case OPFOR: {
+ [
+ GETCOLOUR('Map_OPFOR_R', 0.5),
+ GETCOLOUR('Map_OPFOR_G', 0),
+ GETCOLOUR('Map_OPFOR_B', 0)
+ ]
+ };
+
+ case INDEPENDENT: {
+ [
+ GETCOLOUR('Map_Independent_R', 0),
+ GETCOLOUR('Map_Independent_G', 0.5),
+ GETCOLOUR('Map_Independent_B', 0)
+ ]
+ };
+
+ case CIVILIAN: {
+ [
+ GETCOLOUR('Map_Civilian_R', 0.4),
+ GETCOLOUR('Map_Civilian_G', 0),
+ GETCOLOUR('Map_Civilian_B', 0.5)
+ ]
+ };
+};
+
+_colour set [0, (_colour select 0) * FACTOR];
+_colour set [1, (_colour select 1) * FACTOR];
+_colour set [2, (_colour select 2) * FACTOR];
+_colour set [3, 1];
+
+_colour
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_status.sqf b/addons/spectator/functions/fnc_status.sqf
new file mode 100644
index 0000000000..4207ef9c00
--- /dev/null
+++ b/addons/spectator/functions/fnc_status.sqf
@@ -0,0 +1,60 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Render status.
+
+ Arguments:
+ 0: Status element
+
+ Example:
+ [display] call ace_spectator_fnc_status;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_display = _this select 0;
+
+_speedText = (str ([GVAR(moveScale), 4] call BIS_fnc_cutDecimals)) + "v";
+(_display displayCtrl 0) ctrlSetText _speedText;
+
+_name = "";
+_colour = [1,1,1,1];
+
+if (!isNull GVAR(unit)) then {
+ _info = [GVAR(unit)] call FUNC(unitInfo);
+ _name = _info select 0;
+ _side = _info select 1;
+ _colour = _info select 2;
+ _colour set [3, 1];
+};
+(_display displayCtrl 1) ctrlSetText _name;
+(_display displayCtrl 1) ctrlSetTextColor _colour;
+
+_mode = if (GVAR(cameraOn)) then {
+ if (isNull GVAR(attach)) then {"FREE"} else {"ATTACH"};
+} else {
+ if (GVAR(third)) then {"THIRD"} else {"FIRST"};
+};
+(_display displayCtrl 2) ctrlSetText _mode;
+
+_timeText = [dayTime] call BIS_fnc_timeToString;
+(_display displayCtrl 3) ctrlSetText _timeText;
+
+_fovText = (str ([GVAR(fov), 3] call BIS_fnc_cutDecimals)) + "a";
+(_display displayCtrl 4) ctrlSetText _fovText;
+
+_timeAccText = (str ([GVAR(accTime), 4] call BIS_fnc_cutDecimals)) + "x";
+(_display displayCtrl 5) ctrlSetText _timeAccText;
+
+_focusDist = [GVAR(focus) select 0, 1] call BIS_fnc_cutDecimals;
+_focusBlur = GVAR(focus) select 1;
+_focusText = if (_focusDist == -1 && _focusBlur == 1) then {"Auto"} else {if (_focusDist < 0) then {toString [8734]} else {str _focusDist + "m"}};
+(_display displayCtrl 6) ctrlSetText _focusText;
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_trackUnits.sqf b/addons/spectator/functions/fnc_trackUnits.sqf
new file mode 100644
index 0000000000..28da75a554
--- /dev/null
+++ b/addons/spectator/functions/fnc_trackUnits.sqf
@@ -0,0 +1,54 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Check and record tracking for all units.
+
+ Arguments:
+ None
+
+ Example:
+ call ace_spectator_fnc_trackUnits;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+if (isNil QGVAR(trackingArray)) then {
+ GVAR(trackingArray) = [];
+};
+
+if (count GVAR(units) < 1) exitWith {};
+
+{
+ _unit = _x;
+ _pos = getPos _unit;
+ _pos resize 2;
+
+ _index = -1;
+
+ {if ((_x select 0) == _unit) then {_index = _forEachIndex}} forEach GVAR(trackingArray);
+ if (_index == -1) then {
+ GVAR(trackingArray) pushBack [_unit, [_pos]]
+ } else {
+ _unitArray = GVAR(trackingArray) select _index;
+ _trackingArray = _unitArray select 1;
+ _latestIndex = (count _trackingArray) - 1;
+ _latestPos = _trackingArray select _latestIndex;
+ _diffX = abs((_latestPos select 0) - (_pos select 0));
+ _diffY = abs((_latestPos select 1) - (_pos select 1));
+
+ if !((_diffX < 20) && (_diffY < 20)) then {
+ _trackingArray pushBack _pos;
+ _unitArray set [1, _trackingArray];
+ GVAR(trackingArray) set [_index, _unitArray];
+ };
+ };
+
+} forEach GVAR(units);
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_unitInfo.sqf b/addons/spectator/functions/fnc_unitInfo.sqf
new file mode 100644
index 0000000000..a377cabf31
--- /dev/null
+++ b/addons/spectator/functions/fnc_unitInfo.sqf
@@ -0,0 +1,34 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Retrieve unit name, side, and colour.
+
+ Arguments:
+ 0: Unit
+
+ Example:
+ [player] call ace_spectator_fnc_unitInfo;
+
+ Return Value:
+ Name , Side , Colour
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+PARAMS_1(_unit);
+
+_name = [_unit] call EFUNC(common,getName);
+_side = [_unit] call FUNC(unitSide);
+_colour = [_side] call FUNC(sideColour);
+
+if (!alive _unit) then {
+ {_colour set [_forEachIndex, _x / 2.5]} forEach _colour;
+ _colour set [3, 0.8];
+};
+
+[_name, _side, _colour]
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_unitSide.sqf b/addons/spectator/functions/fnc_unitSide.sqf
new file mode 100644
index 0000000000..d33520d5ec
--- /dev/null
+++ b/addons/spectator/functions/fnc_unitSide.sqf
@@ -0,0 +1,39 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ Retrieve unit's side, even after they join grpNull.
+
+ Arguments:
+ 0: Unit to check
+
+ Example:
+ [unit] call ace_spectator_unitSide;
+
+ Return Value:
+ Side
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+PARAMS_1(_unit);
+
+private ["_side"];
+
+if (alive _unit) then {
+ _side = side (group _unit);
+} else {
+ _sideNum = getNumber (configFile >> "CfgVehicles" >> (typeOf _unit) >> "side");
+ _side = switch _sideNum do {
+ case 0: {OPFOR};
+ case 1: {BLUFOR};
+ case 2: {INDEPENDENT};
+ case 3: {CIVILIAN};
+ };
+};
+
+_side
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_unitVar.sqf b/addons/spectator/functions/fnc_unitVar.sqf
new file mode 100644
index 0000000000..6d072ae171
--- /dev/null
+++ b/addons/spectator/functions/fnc_unitVar.sqf
@@ -0,0 +1,38 @@
+/*
+ Author: Karel Moricky, modified by voiper
+
+ Description:
+ Set or return an unique object variable (client only).
+
+ Arguments:
+ 0: Unit
+
+ Returns:
+ Variable
+*/
+
+#include "script_component.hpp"
+
+private ["_object","_var"];
+
+_object = [_this, 0, objnull, [objnull]] call BIS_fnc_param;
+
+if (isNull _object) exitwith {""};
+
+_var = _object getVariable [QGVAR(objectVar), ""];
+
+if (_var == "") then {
+ _var = vehicleVarname _object;
+
+ if (_var == "") then {
+ _var = [_this, 1, QGVAR(obj), [""]] call BIS_fnc_param;
+ _varID = [_var, 1] call BIS_fnc_counter;
+ _var = _var + str _varID;
+ };
+
+ _object setVariable [QGVAR(objectVar), _var];
+ missionNamespace setVariable [_var, _object];
+ _object setVehicleVarname _var;
+};
+
+_var
\ No newline at end of file
diff --git a/addons/spectator/functions/fnc_viewDistance.sqf b/addons/spectator/functions/fnc_viewDistance.sqf
new file mode 100644
index 0000000000..4112ed2a62
--- /dev/null
+++ b/addons/spectator/functions/fnc_viewDistance.sqf
@@ -0,0 +1,47 @@
+/*
+ Author:
+ voiper
+
+ Description:
+ View distance dialog.
+
+ Arguments:
+ 0: Mode
+ 1: Arguemnts
+
+ Example:
+ ["Init", [dialog]] call ace_spectator_fnc_viewDistance;
+
+ Return Value:
+ None
+
+ Public:
+ No
+*/
+
+#include "script_component.hpp"
+
+_mode = _this select 0;
+_this = _this select 1;
+
+switch _mode do {
+
+ case "Init": {
+ _dialog = _this select 0;
+ _dist = -1;
+ _text = _dialog displayCtrl 1;
+ _slider = _dialog displayCtrl 2;
+ _slider slidersetRange [1000,20000];
+ _slider sliderSetSpeed [1000,1000,1000];
+ _slider sliderSetPosition viewDistance;
+ _text ctrlSetText str viewDistance;
+ };
+
+ case "Slider": {
+ _dialog = ctrlParent (_this select 0);
+ _dist = _this select 1;
+ _text = _dialog displayCtrl 1;
+ setViewDistance _dist;
+ _text ctrlSetText str viewDistance;
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/functions/script_component.hpp b/addons/spectator/functions/script_component.hpp
new file mode 100644
index 0000000000..d5034cb39c
--- /dev/null
+++ b/addons/spectator/functions/script_component.hpp
@@ -0,0 +1 @@
+#include "\z\ace\addons\spectator\script_component.hpp"
\ No newline at end of file
diff --git a/addons/spectator/rsc_defines.hpp b/addons/spectator/rsc_defines.hpp
new file mode 100644
index 0000000000..e7cb7178c3
--- /dev/null
+++ b/addons/spectator/rsc_defines.hpp
@@ -0,0 +1,646 @@
+// Control types
+#define CT_STATIC 0
+#define CT_BUTTON 1
+#define CT_EDIT 2
+#define CT_SLIDER 3
+#define CT_COMBO 4
+#define CT_LISTBOX 5
+#define CT_TOOLBOX 6
+#define CT_CHECKBOXES 7
+#define CT_PROGRESS 8
+#define CT_HTML 9
+#define CT_STATIC_SKEW 10
+#define CT_ACTIVETEXT 11
+#define CT_TREE 12
+#define CT_STRUCTURED_TEXT 13
+#define CT_CONTEXT_MENU 14
+#define CT_CONTROLS_GROUP 15
+#define CT_SHORTCUTBUTTON 16
+#define CT_HITZONES 17
+#define CT_XKEYDESC 40
+#define CT_XBUTTON 41
+#define CT_XLISTBOX 42
+#define CT_XSLIDER 43
+#define CT_XCOMBO 44
+#define CT_ANIMATED_TEXTURE 45
+#define CT_OBJECT 80
+#define CT_OBJECT_ZOOM 81
+#define CT_OBJECT_CONTAINER 82
+#define CT_OBJECT_CONT_ANIM 83
+#define CT_LINEBREAK 98
+#define CT_USER 99
+#define CT_MAP 100
+#define CT_MAP_MAIN 101
+#define CT_LISTNBOX 102
+#define CT_ITEMSLOT 103
+#define CT_CHECKBOX 77
+
+// Static styles
+#define ST_POS 0x0F
+#define ST_HPOS 0x03
+#define ST_VPOS 0x0C
+#define ST_LEFT 0x00
+#define ST_RIGHT 0x01
+#define ST_CENTER 0x02
+#define ST_DOWN 0x04
+#define ST_UP 0x08
+#define ST_VCENTER 0x0C
+
+#define ST_TYPE 0xF0
+#define ST_SINGLE 0x00
+#define ST_MULTI 0x10
+#define ST_TITLE_BAR 0x20
+#define ST_PICTURE 0x30
+#define ST_FRAME 0x40
+#define ST_BACKGROUND 0x50
+#define ST_GROUP_BOX 0x60
+#define ST_GROUP_BOX2 0x70
+#define ST_HUD_BACKGROUND 0x80
+#define ST_TILE_PICTURE 0x90
+#define ST_WITH_RECT 0xA0
+#define ST_LINE 0xB0
+#define ST_UPPERCASE 0xC0
+#define ST_LOWERCASE 0xD0
+
+#define ST_SHADOW 0x100
+#define ST_NO_RECT 0x200
+#define ST_KEEP_ASPECT_RATIO 0x800
+
+#define ST_TITLE ST_TITLE_BAR + ST_CENTER
+
+// Slider styles
+#define SL_DIR 0x400
+#define SL_VERT 0
+#define SL_HORZ 0x400
+
+#define SL_TEXTURES 0x10
+
+// progress bar
+#define ST_VERTICAL 0x01
+#define ST_HORIZONTAL 0
+
+// Listbox styles
+#define LB_TEXTURES 0x10
+#define LB_MULTI 0x20
+
+// Tree styles
+#define TR_SHOWROOT 1
+#define TR_AUTOCOLLAPSE 2
+
+// MessageBox styles
+#define MB_BUTTON_OK 1
+#define MB_BUTTON_CANCEL 2
+#define MB_BUTTON_USER 4
+#define MB_ERROR_DIALOG 8
+
+// Fonts
+#define GUI_FONT_NORMAL PuristaMedium
+#define GUI_FONT_BOLD PuristaSemibold
+#define GUI_FONT_THIN PuristaLight
+#define GUI_FONT_MONO EtelkaMonospacePro
+#define GUI_FONT_NARROW EtelkaNarrowMediumPro
+#define GUI_FONT_CODE LucidaConsoleB
+#define GUI_FONT_SYSTEM TahomaB
+
+//colours
+
+#define COLOUR_GUI_TEXT {"profilenamespace getvariable ['GUI_TITLETEXT_RGB_R',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_G',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_B',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_A',1]"}
+
+#define COLOUR_GUI_BG {"profilenamespace getvariable ['GUI_BCG_RGB_R',0.8]", "profilenamespace getvariable ['GUI_BCG_RGB_G',0.8]","profilenamespace getvariable ['GUI_BCG_RGB_B',0.8]","profilenamespace getvariable ['GUI_BCG_RGB_A',0.8]"}
+
+#define COLOUR_IGUI_TEXT {"profilenamespace getvariable ['IGUI_TEXT_RGB_R',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_G',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_B',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_A',1]"}
+
+#define COLOUR_IGUI_BG {"profilenamespace getvariable ['IGUI_BCG_RGB_R',0.8]", "profilenamespace getvariable ['IGUI_BCG_RGB_G',0.5]","profilenamespace getvariable ['IGUI_BCG_RGB_B',0]","profilenamespace getvariable ['IGUI_BCG_RGB_A',0.8]"}
+
+#define COLOUR_IGUI_WARN {"profilenamespace getvariable ['IGUI_TEXT_WARNING_R',0.8]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_G',0.5]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_B',0]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_A',0.8]"}
+
+// Grids
+#define GUI_GRID_CENTER_WAbs ((safezoneW / safezoneH) min 1.2)
+#define GUI_GRID_CENTER_HAbs (GUI_GRID_CENTER_WAbs / 1.2)
+#define GUI_GRID_CENTER_W (GUI_GRID_CENTER_WAbs / 40)
+#define GUI_GRID_CENTER_H (GUI_GRID_CENTER_HAbs / 25)
+#define GUI_GRID_CENTER_X (safezoneX + (safezoneW - GUI_GRID_CENTER_WAbs)/2)
+#define GUI_GRID_CENTER_Y (safezoneY + (safezoneH - GUI_GRID_CENTER_HAbs)/2)
+
+#define RESUNITS_X (safeZoneW / 100)
+#define RESUNITS_Y (safeZoneH / 100)
+#define RESCENTRE_X safeZoneX + safeZoneW / 2
+#define RESCENTRE_Y safeZoneY + safeZoneH / 2
+
+#define Q(s) #s
+
+class vip_rsc_picture {
+
+ access = 0;
+ idc = -1;
+ type = CT_STATIC;
+ style = ST_PICTURE;
+ colorBackground[] = {0,0,0,0};
+ colorText[] = {1,1,1,1};
+ font = "TahomaB";
+ sizeEx = 0;
+ lineSpacing = 0;
+ text = "";
+ fixedWidth = 0;
+ shadow = 0;
+};
+
+class vip_rsc_text {
+
+ access = 0;
+ idc = -1;
+ type = CT_STATIC;
+ style = ST_LEFT;
+ colorBackground[] = {0,0,0,0};
+ colorText[] = {1,1,1,1};
+ font = "PuristaMedium";
+ sizeEx = 0.08;
+ lineSpacing = 1;
+ text = "";
+ fixedWidth = 0;
+ moving = 0;
+};
+
+class vip_rsc_box {
+
+ idc=-1;
+ type = CT_STATIC;
+ style = ST_CENTER;
+ text = "";
+ font = "TahomaB";
+ sizeEx = 0.04;
+
+ colorBackground[] = {0,0,0,1};
+ colorText[] = {1,1,1,1};
+};
+
+class vip_rsc_button {
+
+ access = 0;
+ type = CT_BUTTON;
+ style = ST_LEFT;
+ default = 0;
+ blinkingPeriod = 0;
+
+ x = 0 * GUI_GRID_CENTER_W + GUI_GRID_CENTER_X;
+ y = 0 * GUI_GRID_CENTER_H + GUI_GRID_CENTER_Y;
+ w = 6 * GUI_GRID_CENTER_W;
+ h = 1 * GUI_GRID_CENTER_H;
+
+ colorBackground[] = {0.8,0.8,0.8,1};
+ colorBackgroundDisabled[] = {0.8,0.8,0.8, 0.25};
+ colorBackgroundActive[] = {1,1,1,1};
+ colorFocused[] = {0.8,0.8,0.8,1};
+
+ text = "";
+ sizeEx = 1 * GUI_GRID_CENTER_H;
+ font = GUI_FONT_NORMAL;
+ shadow = 1;
+ colorText[] = {0,0,0,1};
+ colorDisabled[] = {0,0,0,0.25};
+
+ borderSize = 0.0;
+ colorBorder[] = {1,1,1,1};
+
+ colorShadow[] = {0,0,0,0.0};
+ offsetX = 0.0075;
+ offsetY = 0.01;
+ offsetPressedX = 0.000;
+ offsetPressedY = 0.00;
+
+ period = 0;
+ periodFocus = 0;
+ periodOver = 0.5;
+
+ soundClick[] = {"\A3\ui_f\data\sound\RscButton\soundClick",0.09,1};
+ soundEnter[] = {"\A3\ui_f\data\sound\RscButton\soundEnter",0.09,1};
+ soundPush[] = {"\A3\ui_f\data\sound\RscButton\soundPush",0.09,1};
+ soundEscape[] = {"\A3\ui_f\data\sound\RscButton\soundEscape",0.09,1};
+
+ //onButtonClick = "false";
+};
+
+class vip_rsc_listbox {
+
+ access = 0;
+ idc = 25;
+ type = CT_COMBO;
+ style = ST_LEFT + LB_TEXTURES;
+ default = 0;
+ blinkingPeriod = 0;
+
+ x = 12 * GUI_GRID_CENTER_W + GUI_GRID_CENTER_X;
+ y = 4 * GUI_GRID_CENTER_H + GUI_GRID_CENTER_Y;
+ w = 9 * GUI_GRID_CENTER_W;
+ h = 1 * GUI_GRID_CENTER_H;
+
+ colorBackground[] = {0.2,0.2,0.2,1};
+ colorSelectBackground[] = {1,0.5,0,1};
+
+ sizeEx = GUI_GRID_CENTER_H;
+ font = GUI_FONT_NORMAL;
+ shadow = 0;
+ colorText[] = {1,1,1,1};
+ colorDisabled[] = {1,1,1,0.5};
+ colorSelect[] = {1,1,1,1};
+
+ pictureColor[] = {1,0.5,0,1};
+ pictureColorSelect[] = {1,1,1,1};
+ pictureColorDisabled[] = {1,1,1,0.5};
+
+ arrowEmpty = "\A3\ui_f\data\GUI\RscCommon\rsccombo\arrow_combo_ca.paa";
+ arrowFull = "\A3\ui_f\data\GUI\RscCommon\rsccombo\arrow_combo_active_ca.paa";
+
+ wholeHeight = 8 * GUI_GRID_CENTER_H;
+ maxHistoryDelay = 1;
+
+ soundExpand[] = {"\A3\ui_f\data\sound\RscCombo\soundExpand",0.1,1};
+ soundCollapse[] = {"\A3\ui_f\data\sound\RscCombo\soundCollapse",0.1,1};
+ soundSelect[] = {"\A3\ui_f\data\sound\RscCombo\soundSelect",0.1,1};
+
+ class ComboScrollBar
+ {
+ width = 0;
+ height = 0;
+ scrollSpeed = 0.01;
+
+ arrowEmpty = "\A3\ui_f\data\gui\cfg\scrollbar\arrowEmpty_ca.paa";
+ arrowFull = "\A3\ui_f\data\gui\cfg\scrollbar\arrowFull_ca.paa";
+ border = "\A3\ui_f\data\gui\cfg\scrollbar\border_ca.paa";
+ thumb = "\A3\ui_f\data\gui\cfg\scrollbar\thumb_ca.paa";
+
+ color[] = {1,1,1,1};
+ };
+
+ onLBSelChanged = "";
+};
+
+class vip_rsc_frame {
+ type = 0;
+ idc = -1;
+ style=ST_FRAME;
+ shadow=2;
+ colorBackground[]={0,0,0,0};
+ colorText[]={1,1,1,1};
+ font="PuristaMedium";
+ sizeEx=0.02;
+ text="";
+};
+
+class vip_rsc_map {
+ moveOnEdges=1;
+ x="SafeZoneXAbs";
+ y="SafeZoneY + 1.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
+ w="SafeZoneWAbs";
+ h="SafeZoneH - 1.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
+ shadow=0;
+ ptsPerSquareSea=5;
+ ptsPerSquareTxt=20;
+ ptsPerSquareCLn=10;
+ ptsPerSquareExp=10;
+ ptsPerSquareCost=10;
+ ptsPerSquareFor=9;
+ ptsPerSquareForEdge=9;
+ ptsPerSquareRoad=6;
+ ptsPerSquareObj=9;
+ showCountourInterval=0;
+ scaleMin=0.001;
+ scaleMax=1;
+ scaleDefault=0.16;
+ maxSatelliteAlpha=0.85000002;
+ alphaFadeStartScale=2;
+ alphaFadeEndScale=2;
+ colorBackground[]={0.96899998,0.95700002,0.949,1};
+ colorSea[]={0.46700001,0.63099998,0.85100001,0.5};
+ colorForest[]={0.62400001,0.77999997,0.38800001,0.5};
+ colorForestBorder[]={0,0,0,0};
+ colorRocks[]={0,0,0,0.30000001};
+ colorRocksBorder[]={0,0,0,0};
+ colorLevels[]={0.28600001,0.177,0.093999997,0.5};
+ colorMainCountlines[]={0.57200003,0.354,0.18799999,0.5};
+ colorCountlines[]={0.57200003,0.354,0.18799999,0.25};
+ colorMainCountlinesWater[]={0.491,0.57700002,0.70200002,0.60000002};
+ colorCountlinesWater[]={0.491,0.57700002,0.70200002,0.30000001};
+ colorPowerLines[]={0.1,0.1,0.1,1};
+ colorRailWay[]={0.80000001,0.2,0,1};
+ colorNames[]={0.1,0.1,0.1,0.89999998};
+ colorInactive[]={1,1,1,0.5};
+ colorOutside[]={0,0,0,1};
+ colorTracks[]={0.83999997,0.75999999,0.64999998,0.15000001};
+ colorTracksFill[]={0.83999997,0.75999999,0.64999998,1};
+ colorRoads[]={0.69999999,0.69999999,0.69999999,1};
+ colorRoadsFill[]={1,1,1,1};
+ colorMainRoads[]={0.89999998,0.5,0.30000001,1};
+ colorMainRoadsFill[]={1,0.60000002,0.40000001,1};
+ colorGrid[]={0.1,0.1,0.1,0.60000002};
+ colorGridMap[]={0.1,0.1,0.1,0.60000002};
+ fontLabel="PuristaMedium";
+ sizeExLabel="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontGrid="TahomaB";
+ sizeExGrid=0.02;
+ fontUnits="TahomaB";
+ sizeExUnits="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontNames="EtelkaNarrowMediumPro";
+ sizeExNames="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8) * 2";
+ fontInfo="PuristaMedium";
+ sizeExInfo="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ fontLevel="TahomaB";
+ sizeExLevel=0.02;
+ text="#(argb,8,8,3)color(1,1,1,1)";
+ class Legend
+ {
+ x="SafeZoneX + ( ((safezoneW / safezoneH) min 1.2) / 40)";
+ y="SafeZoneY + safezoneH - 4.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
+ w="10 * ( ((safezoneW / safezoneH) min 1.2) / 40)";
+ h="3.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)";
+ font="PuristaMedium";
+ sizeEx="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)";
+ colorBackground[]={1,1,1,0.5};
+ color[]={0,0,0,1};
+ };
+ class Task
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\taskIcon_CA.paa";
+ iconCreated="\A3\ui_f\data\map\mapcontrol\taskIconCreated_CA.paa";
+ iconCanceled="\A3\ui_f\data\map\mapcontrol\taskIconCanceled_CA.paa";
+ iconDone="\A3\ui_f\data\map\mapcontrol\taskIconDone_CA.paa";
+ iconFailed="\A3\ui_f\data\map\mapcontrol\taskIconFailed_CA.paa";
+ color[]=
+ {
+ "(profilenamespace getvariable ['IGUI_TEXT_RGB_R',0])",
+ "(profilenamespace getvariable ['IGUI_TEXT_RGB_G',1])",
+ "(profilenamespace getvariable ['IGUI_TEXT_RGB_B',1])",
+ "(profilenamespace getvariable ['IGUI_TEXT_RGB_A',0.8])"
+ };
+ colorCreated[]={1,1,1,1};
+ colorCanceled[]={0.69999999,0.69999999,0.69999999,1};
+ colorDone[]={0.69999999,1,0.30000001,1};
+ colorFailed[]={1,0.30000001,0.2,1};
+ size=27;
+ importance=1;
+ coefMin=1;
+ coefMax=1;
+ };
+ class Waypoint
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\waypoint_ca.paa";
+ color[]={0,0,0,1};
+ };
+ class WaypointCompleted
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\waypointCompleted_ca.paa";
+ color[]={0,0,0,1};
+ };
+ class CustomMark
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\custommark_ca.paa";
+ size=24;
+ importance=1;
+ coefMin=1;
+ coefMax=1;
+ color[]={0,0,0,1};
+ };
+ class Command
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\waypoint_ca.paa";
+ size=18;
+ importance=1;
+ coefMin=1;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class Bush
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa";
+ color[]={0.44999999,0.63999999,0.33000001,0.40000001};
+ size="14/2";
+ importance="0.2 * 14 * 0.05 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ };
+ class Rock
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\rock_ca.paa";
+ color[]={0.1,0.1,0.1,0.80000001};
+ size=12;
+ importance="0.5 * 12 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ };
+ class SmallTree
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa";
+ color[]={0.44999999,0.63999999,0.33000001,0.40000001};
+ size=12;
+ importance="0.6 * 12 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ };
+ class Tree
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa";
+ color[]={0.44999999,0.63999999,0.33000001,0.40000001};
+ size=12;
+ importance="0.9 * 16 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ };
+ class busstop
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\busstop_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class fuelstation
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\fuelstation_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class hospital
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\hospital_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class church
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\church_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class lighthouse
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\lighthouse_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class power
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\power_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class powersolar
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\powersolar_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class powerwave
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\powerwave_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class powerwind
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\powerwind_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class quay
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\quay_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class transmitter
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\transmitter_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class watertower
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\watertower_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={1,1,1,1};
+ };
+ class Cross
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\Cross_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={0,0,0,1};
+ };
+ class Chapel
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\Chapel_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={0,0,0,1};
+ };
+ class Shipwreck
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\Shipwreck_CA.paa";
+ size=24;
+ importance=1;
+ coefMin=0.85000002;
+ coefMax=1;
+ color[]={0,0,0,1};
+ };
+ class Bunker
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\bunker_ca.paa";
+ size=14;
+ importance="1.5 * 14 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class Fortress
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\bunker_ca.paa";
+ size=16;
+ importance="2 * 16 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class Fountain
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\fountain_ca.paa";
+ size=11;
+ importance="1 * 12 * 0.05";
+ coefMin=0.25;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class Ruin
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\ruin_ca.paa";
+ size=16;
+ importance="1.2 * 16 * 0.05";
+ coefMin=1;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class Stack
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\stack_ca.paa";
+ size=20;
+ importance="2 * 16 * 0.05";
+ coefMin=0.89999998;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class Tourism
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\tourism_ca.paa";
+ size=16;
+ importance="1 * 16 * 0.05";
+ coefMin=0.69999999;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+ class ViewTower
+ {
+ icon="\A3\ui_f\data\map\mapcontrol\viewtower_ca.paa";
+ size=16;
+ importance="2.5 * 16 * 0.05";
+ coefMin=0.5;
+ coefMax=4;
+ color[]={0,0,0,1};
+ };
+};
\ No newline at end of file
diff --git a/addons/spectator/script_component.hpp b/addons/spectator/script_component.hpp
new file mode 100644
index 0000000000..c445dc4cdd
--- /dev/null
+++ b/addons/spectator/script_component.hpp
@@ -0,0 +1,12 @@
+#define COMPONENT spectator
+#include "\z\ace\addons\main\script_mod.hpp"
+
+#ifdef DEBUG_ENABLED_SPECTATOR
+ #define DEBUG_MODE_FULL
+#endif
+
+#ifdef DEBUG_SETTINGS_SPECTATOR
+ #define DEBUG_SETTINGS DEBUG_SETTINGS_SPECTATOR
+#endif
+
+#include "\z\ace\addons\main\script_macros.hpp"
\ No newline at end of file
diff --git a/addons/spectator/stringtable.xml b/addons/spectator/stringtable.xml
new file mode 100644
index 0000000000..5cd585108a
--- /dev/null
+++ b/addons/spectator/stringtable.xml
@@ -0,0 +1,95 @@
+
+
+
+
+ Spectator
+ Obserwator
+ Pozorovatel
+ Espectador
+
+
+ Enable Spectator
+ Aktywuj obserwatora
+ Povolit pozorovatele
+ Activar espectador
+
+
+ Begin spectating on player death?
+ Włącz obserwatora po śmierci gracza?
+ Přepnout do pozorovatele po hráčově smrti?
+ ¿Comenzar como espectador al morir el jugador?
+
+
+ Player Side Only
+ Tylko strona gracza
+ Pouze strana hráče
+ Sólo bando del jugador
+
+
+ Only spectate units belonging to player's side?
+ Pozwól obserwować jednostki będące tylko po stronie gracza?
+ Pozorovat pouze jednotky patřící k hráčově straně?
+ ¿Sólo observar unidades que pertenecen al bando del jugador?
+
+
+ Spectate AI
+ Obserwacja AI
+ Pozorovat AI
+ Observar IA
+
+
+ Allow spectating of AI units?
+ Pozwól obserwować jednostki AI?
+ Umožnit pozorovat AI jednotky?
+ ¿Permitir observar unidades de la IA?
+
+
+ Track Units
+ Śledź jednostki
+ Sledovat jednotky
+ Seguir unidades
+
+
+ Track units' movements throughout mission?
+ Śledź ruch jednostek w trakcie misji?
+ Sledovat pohyby jednotek napříč misí?
+ ¿Seguimiento de movimientos de unidades a lo largo de la misión?
+
+
+ Start Position
+ Pozycja startowa
+ Počáteční pozice
+ Posición de inicio
+
+
+ Use this module as a starting position for spectator camera?
+ Użyj pozycji modułu jako pozycje startową dla kamery obserwatora?
+ Použít tento modul jako počáteční pozici pro pozorovací kameru?
+ ¿Utiliza este módulo como una posición de inicio para la cámara de espectador?
+
+
+ End Mission
+ Zakończ misję
+ Konec mise
+ Finalizar misión
+
+
+ End mission when all players dead (default BIS behaviour)?
+ Zakończ misję kiedy wszyscy gracze będą martwi (domyślne zachowanie BIS)?
+ Ukončit misi když umřou všichni hráči (výchozí BIS chování)?
+ ¿Finalizar misión cuando todos los jugadores mueran (comportamiento por defecto de BIS)?
+
+
+ View Distance
+ Zasięg widzenia
+ Dohlednost
+ Distancia de visión
+
+
+ OK
+ OK
+ OK
+ Aceptar
+
+
+
\ No newline at end of file
diff --git a/addons/spottingscope/stringtable.xml b/addons/spottingscope/stringtable.xml
index 8c5425dc2b..e20f0635ea 100644
--- a/addons/spottingscope/stringtable.xml
+++ b/addons/spottingscope/stringtable.xml
@@ -6,7 +6,7 @@
Teleskop
Зрительная труба
Teleskop
- Spotting Scope
+ Telescopio
Téléscope de visée
Zaměřovací Dalekohled
Spotting Scope
@@ -18,7 +18,7 @@
Teleskop aufnehmen
Поднять зрительная трубу
Zabierz teleskop
- Pick up Spotting Scope
+ Coger telescopio
Prendre téléscope de visée
Zvednout Zaměřovací dalekohled
Raccogli spottingscope
@@ -30,7 +30,7 @@
Teleskop aufstellen
Установить зрительная трубу
Ustaw teleskop
- Place Spotting Scope
+ Colocar telescopio
Placer téléscope de visée
Položit Zaměřovací dalekohled
Posiziona spottingscope
diff --git a/addons/switchunits/stringtable.xml b/addons/switchunits/stringtable.xml
index b392b09ca7..2d0bc91314 100644
--- a/addons/switchunits/stringtable.xml
+++ b/addons/switchunits/stringtable.xml
@@ -131,7 +131,7 @@
-
+ Moduł ten pozwala na zmianę strony w trakcie gry.
Tento modul umožňuje přepínání mazi dostupnými stranami.
Este módulo permite mudar o lado à disposição dos jogadores.
diff --git a/addons/tripod/$PBOPREFIX$ b/addons/tripod/$PBOPREFIX$
index a374eb7994..2a79aeafd9 100644
--- a/addons/tripod/$PBOPREFIX$
+++ b/addons/tripod/$PBOPREFIX$
@@ -1 +1 @@
-z\ace\addons\tripod
+z\ace\addons\tripod
\ No newline at end of file
diff --git a/addons/tripod/CfgEventHandlers.hpp b/addons/tripod/CfgEventHandlers.hpp
index ed5027f094..d700ed4c85 100644
--- a/addons/tripod/CfgEventHandlers.hpp
+++ b/addons/tripod/CfgEventHandlers.hpp
@@ -1,7 +1,7 @@
class Extended_PreInit_EventHandlers {
- class ADDON {
- init = QUOTE( call COMPILE_FILE(XEH_preInit) );
- };
+ class ADDON {
+ init = QUOTE( call COMPILE_FILE(XEH_preInit) );
+ };
};
class Extended_PostInit_EventHandlers {
diff --git a/addons/tripod/CfgVehicles.hpp b/addons/tripod/CfgVehicles.hpp
index 714d2cafb1..cb1774cdf4 100644
--- a/addons/tripod/CfgVehicles.hpp
+++ b/addons/tripod/CfgVehicles.hpp
@@ -1,4 +1,3 @@
-
class CfgVehicles {
class Man;
class CAManBase: Man {
diff --git a/addons/tripod/CfgWeapons.hpp b/addons/tripod/CfgWeapons.hpp
index cc7521f0f2..5ae0ee84d2 100644
--- a/addons/tripod/CfgWeapons.hpp
+++ b/addons/tripod/CfgWeapons.hpp
@@ -1,4 +1,3 @@
-
class CfgWeapons {
class ACE_ItemCore;
class InventoryItem_Base_F;
diff --git a/addons/viewdistance/XEH_postInit.sqf b/addons/viewdistance/XEH_postInit.sqf
index c49a197c26..865e5527e5 100644
--- a/addons/viewdistance/XEH_postInit.sqf
+++ b/addons/viewdistance/XEH_postInit.sqf
@@ -2,28 +2,33 @@
if (!hasInterface) exitWith {};
-// Force the view distance down to the limit.
-if (GVAR(enabled) && {viewDistance > GVAR(limitViewDistance)}) then {
- setViewDistance GVAR(limitViewDistance);
-};
-
-// Adapt view distance when the player is created or changed according to whether client is on foot or vehicle.
-["playerChanged",{
- [false] call FUNC(adaptViewDistance);
-}] call ace_common_fnc_addEventHandler;
-
-// Set the EH which waits for any of the view distance settings to be changed, so that the effect is show immediately
-["SettingChanged",{
- if ((_this select 0 == QGVAR(viewDistanceOnFoot)) ||
- (_this select 0 == QGVAR(viewDistanceLandVehicle)) ||
- (_this select 0 == QGVAR(viewDistanceAirVehicle)) ||
- (_this select 0 == QGVAR(objectViewDistanceCoeff))) then {
-
- [true] call FUNC(adaptViewDistance);
+["SettingsInitialized", {
+ // if not enabled, then bugger off.
+ if !(GVAR(enabled)) exitWith {};
+
+ // Force the view distance down to the limit.
+ if (viewDistance > GVAR(limitViewDistance)) then {
+ setViewDistance GVAR(limitViewDistance);
};
-}] call ace_common_fnc_addEventHandler;
+
+ // Adapt view distance when the player is created or changed according to whether client is on foot or vehicle.
+ ["playerChanged",{
+ [false] call FUNC(adaptViewDistance);
+ }] call EFUNC(common,addEventHandler);
+
+ // Set the EH which waits for any of the view distance settings to be changed, so that the effect is show immediately
+ ["SettingChanged",{
+ if ((_this select 0 == QGVAR(viewDistanceOnFoot)) ||
+ (_this select 0 == QGVAR(viewDistanceLandVehicle)) ||
+ (_this select 0 == QGVAR(viewDistanceAirVehicle)) ||
+ (_this select 0 == QGVAR(objectViewDistanceCoeff))) then {
-// Set the EH which waits for a vehicle change to automatically swap to On Foot/In Land Vehicle/In Air Vehicle
-["playerVehicleChanged",{
- [false] call FUNC(adaptViewDistance)
-}] call ace_common_fnc_addEventHandler;
\ No newline at end of file
+ [true] call FUNC(adaptViewDistance);
+ };
+ }] call EFUNC(common,addEventHandler);
+
+ // Set the EH which waits for a vehicle change to automatically swap between On Foot/In Land Vehicle/In Air Vehicle
+ ["playerVehicleChanged",{
+ [false] call FUNC(adaptViewDistance)
+ }] call EFUNC(common,addEventHandler);
+}] call EFUNC(common,addEventHandler);
\ No newline at end of file
diff --git a/documentation/development/ace3-config-entries.md b/documentation/development/ace3-config-entries.md
index d87ca4145e..1e28bec44d 100644
--- a/documentation/development/ace3-config-entries.md
+++ b/documentation/development/ace3-config-entries.md
@@ -63,6 +63,8 @@ ace_barrelLength
ace_laserpointer
ace_nextmodeclass
ace_modedescription
+ace_hearing_protection
+ace_hearing_lowerVolume
```
diff --git a/documentation/development/coding-guidelines.md b/documentation/development/coding-guidelines.md
index 89f0d91342..1ab53046ec 100644
--- a/documentation/development/coding-guidelines.md
+++ b/documentation/development/coding-guidelines.md
@@ -107,12 +107,12 @@ Every function should have a header of the following format:
* Arguments:
* 0: The first argument
* 1: The second argument
- *
+ *
* Return Value:
* The return value
*
* Example:
- * _bool = ["something", player] call ace_common_fnc_imanexample
+ * ["something", player] call ace_common_fnc_imanexample
*
* Public: [Yes/No]
*/
@@ -124,33 +124,39 @@ Every function should have a header of the following format:
### 4.1 Module/PBO specific Macro Usage
The family of `GVAR` macro's define global variable strings or constants for use within a module. Please use these to make sure we follow naming conventions across all modules and also prevent duplicate/overwriting between variables in different modules. The macro family expands as follows, for the example of the module 'balls':
-* `GVAR(face)` is `ace_balls_face`
-* `QGVAR(face)` is `"ace_balls_face"`
-* `EGVAR(balls,face)` is `ace_balls_face`
-* `EGVAR(leg,face)` is `ace_leg_face`
-* `QEGVAR(leg,face)` is `"ace_leg_face"`
-
+
+| Macros | is the same as |
+| -------|---------|
+| `GVAR(face)` | ace_balls_face |
+|`QGVAR(face)` | ace_balls_face |
+| `EGVAR(balls,face)` | ace_balls_face |
+| `EGVAR(leg,face)` | ace_leg_face |
+| `QEGVAR(leg,face)` | ace_leg_face |
There also exists the FUNC family of Macros:
-* `FUNC(face)` is `ace_balls_fnc_face` or the call trace wrapper for that function.
-* `EFUNC(balls,face)` is `ace_balls_fnc_face` or the call trace wrapper for that function.
-* `EFUNC(leg,face)` is `ace_leg_fnc_face` or the call trace wrapper for that function.
-* `DFUNC(face)` is `ace_balls_fnc_face` and will ALWAYS be the function global variable.
-* `DEFUNC(leg,face)` is `ace_leg_fnc_face` and will ALWAYS be the function global variable.
-* `QFUNC(face)` is `"ace_balls_fnc_face"`
-* `QEFUNC(leg,face)` is `"ace_leg_fnc_face"`
+| Macros | is the same as |
+| -------|---------|
+|`FUNC(face)` | ace_balls_fnc_face or the call trace wrapper for that function.|
+|`EFUNC(balls,face)` | ace_balls_fnc_face or the call trace wrapper for that function.|
+|`EFUNC(leg,face) `| ace_leg_fnc_face or the call trace wrapper for that function.|
+|`DFUNC(face)` | ace_balls_fnc_face and will ALWAYS be the function global variable.|
+|`DEFUNC(leg,face)` | ace_leg_fnc_face and will ALWAYS be the function global variable.|
+|`QFUNC(face)` | ace_balls_fnc_face |
+|`QEFUNC(leg,face)` |ace_leg_fnc_face|
The `FUNC` and `EFUNC` macros should NOT be used inside `QUOTE` macros if the intention is to get the function name or assumed to be the function variable due to call tracing (see below). If you need to 100% always be sure that you are getting the function name or variable use the `DFUNC` or `DEFUNC` macros. For example `QUOTE(FUNC(face)) == "ace_balls_fnc_face"` would be an illegal use of `FUNC` inside `QUOTE`.
Using `FUNC` or `EFUNC` inside a `QUOTE` macro is fine if the intention is for it to be executed as a function.
-#### 4.1.1 FUNC Macros, Call Tracing, and Non-ACE/Anonymous Functions
+#### 4.1.1 FUNC Macros, Call Tracing, and Non-ACE3 /Anonymous Functions
-ACE implements a basic call tracing system that can dump the call stack on errors or wherever you want. To do this the `FUNC` macros in debug mode will expand out to include metadata about the call including line numbers and files. This functionality is automatic with the use of calls via `FUNC` and `EFUNC`, but any calls to other functions need to use the following macros:
+ACE3 implements a basic call tracing system that can dump the call stack on errors or wherever you want. To do this the `FUNC` macros in debug mode will expand out to include metadata about the call including line numbers and files. This functionality is automatic with the use of calls via `FUNC` and `EFUNC`, but any calls to other functions need to use the following macros:
-* `CALLSTACK(functionName)` example: `[] call CALLSTACK(cba_fnc_someFunction)`
-* `CALLSTACK_NAMED(function,functionName)` example: `[] call CALLSTACK_NAMED(_anonymousFunction,'My anonymous function!')`
+| Macro | example |
+| -------|---------|
+|`CALLSTACK(functionName)` | `[] call CALLSTACK(cba_fnc_someFunction)` |
+|`CALLSTACK_NAMED(function,functionName)` | `[] call CALLSTACK_NAMED(_anonymousFunction,'My anonymous function!')`|
These macros will call these functions with the appropriate wrappers and enable call logging into them (but to no further calls inside obviously).
@@ -162,44 +168,64 @@ These macros will call these functions with the appropriate wrappers and enable
#### 4.2.1 setVariable, getVariable family macros
-* `GETVAR(player,MyVarName,false)`
- `player getVariable ["MyVarName", false]`
-* `GETMVAR(MyVarName,objNull)`
- `missionNamespace getVariable ["MyVarName", objNull]`
-* `GETUVAR(MyVarName,displayNull)`
- `uiNamespace getVariable ["MyVarName", displayNull]`
-* `SETVAR(player,MyVarName,127)`
- `player setVariable ["MyVarName", 127]`
-* `SETPVAR(player,MyVarName,127)`
- `player setVariable ["MyVarName", 127, true]`
-* `SETMVAR(MyVarName,player)`
- `missionNamespace setVariable ["MyVarName", player]`
-* `SETUVAR(MyVarName,_control)`
- `uiNamespace setVariable ["MyVarName", _control]`
+| Macro | is the same as |
+| -------|---------|
+|`GETVAR(player,MyVarName,false)` | player getVariable ["MyVarName", false]|
+|`GETMVAR(MyVarName,objNull)` | missionNamespace getVariable ["MyVarName", objNull]|
+|`GETUVAR(MyVarName,displayNull)` | uiNamespace getVariable ["MyVarName", displayNull]|
+|`SETVAR(player,MyVarName,127)` | player setVariable ["MyVarName", 127] SETPVAR(player,MyVarName,127) player setVariable ["MyVarName", 127, true] |
+|`SETMVAR(MyVarName,player)` | missionNamespace setVariable ["MyVarName", player] |
+|`SETUVAR(MyVarName,_control)` | uiNamespace setVariable ["MyVarName", _control] |
+
+#### 4.2.2 STRING family macros
+
+Note that you need the strings in module stringtable.xml in the correct format
+`STR_ACE__`
+Example:
+`STR_Balls_Banana`
+
+Script strings:
+
+| Macro | is the same as |
+| -------|---------|
+| `LSTRING(banana)` | "STR_ACE_balls_banana"|
+| `ELSTRING(balls,banana)` | "STR_ACE_balls_banana"|
+
+
+Config Strings (require `$` as first character):
+
+| Macro | is the same as |
+| -------|---------|
+| `CSTRING(banana)` | "$STR_ACE_balls_banana" |
+| `ECSTRING(balls,banana)` | "$STR_ACE_balls_banana" |
## 5. Event Handlers
-Event handlers in ACE are implemented through our event system. They should be used to trigger or allow triggering of specific functionality.
+Event handlers in ACE3 are implemented through our event system. They should be used to trigger or allow triggering of specific functionality.
The commands are listed below.
-* `[eventName, eventCodeBlock] call ace_common_fnc_addEventHandler` adds an event handler with the event name and returns the event handler id.
-* `[eventName, args] call ace_common_fnc_globalEvent` calls an event with the listed args on all machines, the local machine, and the server.
-* `[eventName, args] call ace_common_fnc_serverEvent` calls an event just on the server computer (dedicated or self-hosted).
-* `[eventName, targetObject(s), args] call ace_common_fnc_targetEvent` calls an event just on the targeted object or list of objects.
-* `[eventName, args] call ace_common_fnc_localEvent` calls an event just on the local machine, useful for inter-module events.
+| Even Handler | use |
+| -------|---------|
+|`[eventName, eventCodeBlock] call ace_common_fnc_addEventHandler` | adds an event handler with the event name and returns the event handler id.|
+| `[eventName, args] call ace_common_fnc_globalEvent` | calls an event with the listed args on all machines, the local machine, and the server. |
+|`[eventName, args] call ace_common_fnc_serverEvent` | calls an event just on the server computer (dedicated or self-hosted).|
+| `[eventName, targetObject(s), args] call ace_common_fnc_targetEvent` | calls an event just on the targeted object or list of objects.|
+|`[eventName, args] call ace_common_fnc_localEvent` | calls an event just on the local machine, useful for inter-module events.|
Events can be removed or cleared with the following commands.
-* `[eventName, eventHandlerId] call ace_common_fnc_removeEventHandler` will remove a specific event handler of the event name, using the ID returned from `ace_common_fnc_addEventHandler`.
-* `[eventName] call ace_common_fnc_removeAllEventHandlers` will remove all event handlers for that type of event.
+| Even Handler | use |
+| -------|---------|
+|`[eventName, eventHandlerId] call ace_common_fnc_removeEventHandler` | will remove a specific event handler of the event name, using the ID returned from `ace_common_fnc_addEventHandler`.|
+|`[eventName] call ace_common_fnc_removeAllEventHandlers` | will remove all event handlers for that type of event.|
-More information on the [ACE Events System](https://github.com/KoffeinFlummi/ACE3/wiki/ACE-Events-System) page.
+More information on the [ACE3 Events System](https://github.com/KoffeinFlummi/ACE3/wiki/ACE-Events-System) page.
## 6. Hashes
-Hashes are a variable type that store key value pairs. They are not implemented natively in SQF, so there are a number of macros and functions for their usage in ACE. If you are unfamiliar with the idea, they are similar in function to `setVariable`/`getVariable` but do not require an object to use.
+Hashes are a variable type that store key value pairs. They are not implemented natively in SQF, so there are a number of macros and functions for their usage in ACE3. If you are unfamiliar with the idea, they are similar in function to `setVariable`/`getVariable` but do not require an object to use.
The following example is a simple usage using our macros which will be explained further below.
@@ -217,11 +243,13 @@ if(HASH_HASKEY(_hash, "key")) then {
A description of the above macros is below.
-* `HASHCREATE` is used to create an empty hash.
-* `HASH_SET(hash, key, val)` will set the hash key to that value, a key can be anything, even objects.
-* `HASH_GET(hash, key)` will return the value of that key (or nil if it doesn't exist).
-* `HASH_HASKEY(hash, key)` will return true/false if that key exists in the hash.
-* `HASH_REM(hash, key)` will remove that hash key.
+| Macro | use |
+| -------|---------|
+|`HASHCREATE` | used to create an empty hash.|
+| `HASH_SET(hash, key, val)` | will set the hash key to that value, a key can be anything, even objects. |
+|`HASH_GET(hash, key)` | will return the value of that key (or nil if it doesn't exist). |
+| `HASH_HASKEY(hash, key)` | will return true/false if that key exists in the hash. |
+| `HASH_REM(hash, key)` | will remove that hash key.|
### 6.1 Hashlists
@@ -256,11 +284,14 @@ HASH_SET(_anotherHash, "anotherKey", "another value");
As you can see above working with hashlists are fairly simple, a more in depth explanation of the macros is below.
-* `HASHLIST_CREATELIST(keys)` creates a new hashlist with the default keys, pass [] for no default keys.
-* `HASHLIST_CREATEHASH(hashlist)` returns a blank hash template from a hashlist.
-* `HASHLIST_PUSH(hashList, hash)` pushes a new hash onto the end of the list.
-* `HASHLIST_SELECT(hashlist, index)` returns the hash at that index in the list.
-* `HASHLIST_SET(hashlist, index, hash)` sets a specific index to that hash.
+
+| Macro | use |
+| -------|---------|
+|`HASHLIST_CREATELIST(keys)` | creates a new hashlist with the default keys, pass [] for no default keys.|
+|`HASHLIST_CREATEHASH(hashlist)` | returns a blank hash template from a hashlist.|
+|`HASHLIST_PUSH(hashList, hash)` | pushes a new hash onto the end of the list.|
+|`HASHLIST_SELECT(hashlist, index)` | returns the hash at that index in the list. |
+|`HASHLIST_SET(hashlist, index, hash)` | sets a specific index to that hash.|
#### 6.1.1 A note on pass by reference and hashes
diff --git a/documentation/development/setting-up-the-development-environment.md b/documentation/development/setting-up-the-development-environment.md
index 5264760785..e02760f96d 100644
--- a/documentation/development/setting-up-the-development-environment.md
+++ b/documentation/development/setting-up-the-development-environment.md
@@ -23,7 +23,7 @@ This page describes how you can setup your development environment for ACE3, all
## 2. Why so complicated?
-If you have contributed to AGM you might be used to an easier build process, where there was even an .exe you could use for building. ACE3, however, makes use of CBA macros to simplify things and give the developer access to a better debug process, which requires a stricter build environment. Additionally, Mikero's tools are stricter and report more errors than AddonBuilder does. The structure of this development environment also allows for [file patching](#file-patching), which is very useful for debugging.
+If you have contributed to AGM you might be used to an easier build process, where there was even an .exe you could use for building. ACE3, however, makes use of CBA macros to simplify things and give the developer access to a better debug process, which requires a stricter build environment. Additionally, Mikero's tools are stricter and report more errors than AddonBuilder does. The structure of this development environment also allows for [file patching](#7-file-patching), which is very useful for debugging.
Not offering .exes for the Python scripts we use allows us to make easy changes without the hassle of compiling self-extracting exes all the time.
diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md
index 70123a0320..1f38a9d18e 100644
--- a/documentation/feature/advanced_ballistics.md
+++ b/documentation/feature/advanced_ballistics.md
@@ -25,7 +25,7 @@ The Advanced Ballistics module improves internal and external ballistics.
## 2. Usage
### 2.1 Protractor
-Press Ctrl+Shift+K while using a compatible weapon to toggle the protractor. The red line indicates the current inclination angle in degrees. The protractor will disappear if you lower or holster your weapon.
+Press Ctrl+⇧ Shift+K while using a compatible weapon to toggle the protractor. The red line indicates the current inclination angle in degrees. The protractor will disappear if you lower or holster your weapon.
## 3. Dependencies
`ace_ballistics`, `ace_weather`, `ace_modules`
diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md
index 25f4e52cad..ead653641d 100644
--- a/documentation/feature/aircraft.md
+++ b/documentation/feature/aircraft.md
@@ -35,7 +35,7 @@ Adds a HUD to the AH-9 based on the Comanche's HUD.
## 2. Usage
### 2.1 Switching flare modes
-Press CTRL+C to switch between flare firing modes (Arma 3 default key bind `countermeasure mode`)
+Press Ctrl+C to switch between flare firing modes (Arma 3 default key bind `countermeasure mode`)
## 3. Dependencies
diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md
index a248f8657f..fcf7f2ef77 100644
--- a/documentation/feature/attach.md
+++ b/documentation/feature/attach.md
@@ -17,14 +17,14 @@ Adds an attachable IR strobe, which is only visible using night vision devices a
## 2. Usage
### 2.1 Attaching to yourself
-- Use Self Interact CTRL+⊞ Win (ACE3 default).
+- Use Self Interact Ctrl+⊞ Win (ACE3 default).
- Select `Equipment`.
- Select `Attach item`.
- Select which item you want to attach.
- Repeat the process to detach.
### 2.2 Attaching to a vehicle
-- Interact with the vehicle ⊞ Win (ACE3 default).
+- Interact with the vehicle ⊞ Win (ACE3 default).
- Select `Attach item`.
- Select your item and follow the instructions on the screen.
- Repeat the process to detach.
diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md
index 33b7ec3739..6ff4623016 100644
--- a/documentation/feature/captives.md
+++ b/documentation/feature/captives.md
@@ -31,7 +31,7 @@ Allows players to surrender. It renders the unit unable to move and with the han
### 2.2 Escorting a captive
- Interact with the captive ⊞ win.
- Select the `Escort prisoner` option.
-- To stop escorting, use the mousewheel and select `Release` or use Self Interaction CTRL+⊞ win and select `Release`.
+- To stop escorting, use the mousewheel and select `Release` or use Self Interaction Ctrl+⊞ win and select `Release`.
### 2.3 Loading and unloading a captive into/from a vehicle
- Escort the captive.
diff --git a/documentation/feature/concertina_wire.md b/documentation/feature/concertina_wire.md
index 0c0cdb3ab6..72c63ece5e 100644
--- a/documentation/feature/concertina_wire.md
+++ b/documentation/feature/concertina_wire.md
@@ -1,6 +1,6 @@
---
layout: wiki
-title: concertina wire
+title: Concertina Wire
description:
group: feature
parent: wiki
@@ -8,12 +8,12 @@ parent: wiki
## 1. Overview
-A concertina wire is a type of barbed wire formed in large coils that can be expanded to form obstacles, in ACE3 any vehicle making contact with it get it's tires destroyed.
+A concertina wire is a type of barbed wire formed in large coils that can be expanded to form obstacles, in ACE3 any vehicle making contact with it gets its tires destroyed.
## 2. Usage
### 2.1 Deploying the concertina wire
-- Approach the concertina coil and select ⊞ Win (ACE3 default)
+- Approach the concertina coil and select ⊞ Win (ACE3 default)
- Select `Deploy concertina wire`.
- Follow the instructions on screen.
diff --git a/documentation/feature/disarming.md b/documentation/feature/disarming.md
index 02b8dc2163..f635b94901 100644
--- a/documentation/feature/disarming.md
+++ b/documentation/feature/disarming.md
@@ -14,7 +14,7 @@ You can search the inventory and disarm captured or unconscious units.
## 2. Usage
### 2.1 Searching and disarming
-- Interact with the captured or unconscious unit ⊞ Win (ACE3 default key bind `Interaction Key`).
+- Interact with the captured or unconscious unit ⊞ Win (ACE3 default key bind `Interaction Key`).
- Select `Open inventory`.
- Drag & Drop the items you wish to remove from the unit.
diff --git a/documentation/feature/dragging.md b/documentation/feature/dragging.md
index e3fdf0b6fe..d23935034d 100644
--- a/documentation/feature/dragging.md
+++ b/documentation/feature/dragging.md
@@ -14,9 +14,9 @@ This adds the option to drag or carry units or objects.
### 2.1 Dragging / Carrying units and objects
- You can only drag or carry an unconscious unit.
-- Interact with the unit or object ⊞ Win (ACE3 default key bind `Interact Key`).
+- Interact with the unit or object ⊞ Win (ACE3 default key bind `Interact Key`).
- Select `Drag` or `Carry`.
-- To release, use the mouse wheel and select `Release` or use Self Interaction CTRL+⊞ Win and select `Release`.
+- To release, use the mouse wheel and select `Release` or use Self Interaction Ctrl+⊞ Win and select `Release`.
## 3. Dependencies
diff --git a/documentation/feature/explosives.md b/documentation/feature/explosives.md
index a88b9ae1b4..071252ffc0 100644
--- a/documentation/feature/explosives.md
+++ b/documentation/feature/explosives.md
@@ -20,18 +20,18 @@ Enables attaching explosives to vehicles.
## 2. Usage
### 2.1 Placing explosives
-- Use self interaction CTRL+⊞ Win (ACE3 default key bind `Self Interaction Key`).
+- Use self interaction Ctrl+⊞ Win (ACE3 default key bind `Self Interaction Key`).
- Select `Explosives`.
- Choose your explosive type and follow the instructions on the screen.
### 2.2 Arming and detonating explosives
-- Interact with the explosive ⊞ Win (ACE3 default key bind `Interact Key`).
+- Interact with the explosive ⊞ Win (ACE3 default key bind `Interact Key`).
- Choose the arming method.
- For clackers use Self Interaction `Explosives` → `Detonate` and choose the corresponding Firing Device.
### 2.3 Defusing explosives
- A `Defusal Kit` is required.
-- Interact with the explosive ⊞ Win.
+- Interact with the explosive ⊞ Win.
- Select `Disarm`.
- You are safe to pick it up after the action has completed.
diff --git a/documentation/feature/fcs.md b/documentation/feature/fcs.md
index b66cad8522..713fba4dcf 100644
--- a/documentation/feature/fcs.md
+++ b/documentation/feature/fcs.md
@@ -21,13 +21,13 @@ Anti air cannons can now use airburst ammunition. It will explode on the FCS' ze
### 2.1 Engaging moving targets
- Place the crosshair on the enemy vehicle.
-- Press and hold TAB (ACE 3 default key bind `Lock Target [Hold]`) and follow the target for about 2 seconds.
-- Release TAB.
+- Press and hold Tab ↹ (ACE 3 default key bind `Lock Target [Hold]`) and follow the target for about 2 seconds.
+- Release Tab ↹.
- The optic is now adjusted sideways to ensure a hit.
### 2.2 Ranging stationary targets
- Place the crosshair on the object to range.
-- Tap TAB
+- Tap Tab ↹
- The optic is now adjusted.
*NOTE: GBU guidance is **DISABLED** as of ACE3 3.0.1*
diff --git a/documentation/feature/hearing.md b/documentation/feature/hearing.md
index 5389f0c3d5..c596f12d19 100644
--- a/documentation/feature/hearing.md
+++ b/documentation/feature/hearing.md
@@ -11,15 +11,18 @@ parent: wiki
### 1.1 Hearing damage simulation
Introduces hearing damage caused by nearby explosions and large-caliber weapons.
-### 1.2 Earplugs
+### 1.2 Earplugs
Adds earplugs to mitigate that effect. Soldiers with high caliber weapons or
missile launchers will be equipped with those, but remember to put them in.
+### 1.3 Helmets
+Some types of helmets can mitigate hearing damage also (ie. crewman helmet, pilot helmet etc.).
+
## 2. Usage
### 2.1 Equipping earplugs
- For this you need the `Earplugs` item.
-- Press the self interaction key CTRL + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
+- Press the self interaction key Ctrl + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
- Select `Equipment`.
- Select `Earplugs in`.
- Same method to remove them but the option is `Earplugs out`.
diff --git a/documentation/feature/huntIR.md b/documentation/feature/huntIR.md
index e4e690dac3..205b812e33 100644
--- a/documentation/feature/huntIR.md
+++ b/documentation/feature/huntIR.md
@@ -17,10 +17,10 @@ NOTE: the HuntIR round doesn't work with modded weapons without a compatibility
- To be able to connect to the IR CMOS camera you'll need a `HuntIR monitor`.
- Fire the HuntIR round as high as possible over the area you want to observe.
- Open the `HuntIR monitor`.
- - To open the `HuntIR monitor` self interact CTRL + ⊞ Win (ACE3 default)
+ - To open the `HuntIR monitor` self interact Ctrl + ⊞ Win (ACE3 default)
- Select `Equipment`.
- Select `Activate HuntIR monitor`.
-- You now have control of the IR CMOS camera to close the monitor press ESC or ⊞ Win
+- You now have control of the IR CMOS camera to close the monitor press ESC or ⊞ Win
### 2.2 IR CMOS camera controls
diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md
index 8cf59c0a08..a4187a0b82 100644
--- a/documentation/feature/javelin.md
+++ b/documentation/feature/javelin.md
@@ -20,12 +20,12 @@ The Titan / Javelin now posses the ability to be used in top down attack or dire
- For this feature you need to have a compatible launcher.
- Fully zoom in with the launcher.
- Switch to thermals N (Arma 3 default key bind `Night vision`).
-- While keeping your aim steadily on target press and hold TAB (ACE3 default key bind `Lock Target [Hold]`).
+- While keeping your aim steadily on target press and hold Tab ↹ (ACE3 default key bind `Lock Target [Hold]`).
- When the sound changes and a cross appears on the screen the target is locked and you're able to fire.
### 2.2 Switching fire mode
- For this feature you need to have a compatible launcher.
-- When aiming with your launcher press CTRL + TAB.
+- When aiming with your launcher press Ctrl + Tab ↹.
- On the right side of the screen (for most launchers) you should see that `TOP`is now illumiated in green which means that your missile will be fired in top down mode.
## 3. Dependencies
diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md
index 2920d4b7a4..367d161340 100644
--- a/documentation/feature/logistics_uavbattery.md
+++ b/documentation/feature/logistics_uavbattery.md
@@ -15,7 +15,7 @@ Adds an item `ACE_UAVBattery` that allows refuelling / recharging of the "Darter
### 2.1 Recharging the darter
- For this you need a `UAV battery` and the UAV needs to be a quad-copter.
-- Interact with the UAV ⊞ Win (ACE3 default key bind `Interact Key`)
+- Interact with the UAV ⊞ Win (ACE3 default key bind `Interact Key`)
- Select `Recharge`
## 3. Dependencies
diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md
index 077e3b48cb..71eb6ac62f 100644
--- a/documentation/feature/logistics_wirecutter.md
+++ b/documentation/feature/logistics_wirecutter.md
@@ -16,7 +16,7 @@ Adds an item `ACE_wirecutter` that allows cutting of fences in Arma 3 and AllInA
### 2.1 Using the wirecutter
- For this you need a `Wirecutter`.
- Approach the fence you want to cut.
-- Press the interaction key ⊞ Win (ACE3 default key bind `Interaction Key`).
+- Press the interaction key ⊞ Win (ACE3 default key bind `Interaction Key`).
- Find the interaction point and select `Cut Fence` (the only option).
## 3. Dependencies
diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md
index 191f12d2b7..304f3e7f96 100644
--- a/documentation/feature/magazinerepack.md
+++ b/documentation/feature/magazinerepack.md
@@ -15,7 +15,7 @@ Adds the ability to repack magazines of the same type.
### 2.1 Repacking
- For this you need multiple half empty mags of the same type.
-- Press the self interaction button CTRL + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
+- Press the self interaction button Ctrl + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
- Select `Repack magazines`.
- Select the type of magazines you want to repack.
diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md
index a67412343f..1618721c82 100644
--- a/documentation/feature/maptools.md
+++ b/documentation/feature/maptools.md
@@ -22,10 +22,10 @@ If you are equipped with a vanilla GPS it will be shown on the map. (You don't n
### 2.1 Using map tools
- For this you need to have `Map Tools`.
- Open the map M (Arma 3 default key bind `Map`).
-- Press the self interaction key CTRL + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
+- Press the self interaction key Ctrl + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
- Select `Map tools`.
- Select the type of tools you want to use.
-- Note that you can drag the Roamer (map tool) around with LMB and rotate it with CTRL + LMB.
+- Note that you can drag the Roamer (map tool) around with LMB and rotate it with Ctrl + LMB.
### 2.2 Drawing lines
- To draw lines `Map Tools` are not required.
diff --git a/documentation/feature/microdagr.md b/documentation/feature/microdagr.md
index 3ff9562293..2ed13875f2 100644
--- a/documentation/feature/microdagr.md
+++ b/documentation/feature/microdagr.md
@@ -1,26 +1,148 @@
---
layout: wiki
title: MicroDAGR
-description:
+description: A GPS device and much more !
group: feature
parent: wiki
---
-## Overview
+For an easier time reading don't forget that you can view all chapters on the right side of the page by clicking on Show/hide under table of content.
-### Sub-feature 1
-Short description of sub-feature 1.
+## 1. Overview
-### Sub-feature 2
-Short description of sub-feature 2.
+"Military operations rely on the position,
+navigation and timing (PNT) data that GPS
+can provide. In combat, the accuracy of
+PNT data can mean the difference between
+life and death. Non-military GPS receivers
+simply aren’t good enough when lives are
+on the line" (Extracted from the real life manual)
+
+that's where the MicroDAGR comes in, here's a list of it's features (in arma 3) :
+
+- Compass and headings.
+- Date and hour synced to the mission.
+- Elevation (above or below sea level)
+- Current speed.
+- GPS with topographic and satellite view.
+- Creating, naming, deleting waypoints.
+- Friendly identification (BLUFOR tracker need to be on)
+- The MicroDAGR is also able to connect to your vector to retrieve data from it.
+
+## 2. Usage
+
+Please note that the numbers in 2.1 are going to be referred to as `1` `2` etc when explaining how to use the MicroDAGR
+
+### 2.1 Bringing the MicroDAGR
+
+- Self interact Ctrl+⊞ Win.
+- Select `Equipment`.
+- Select `configure MicroDAGR`.
+
+### 2.2 The MicroDAGR interface
+
+
+
+number | function |
+------ | ----------------------------------------------------- |
+`1` | Options menu and hour display.
+`2` | Grid position `e` is west to east `n` is south to north.
+`3` | Elevation above sea level in meters.
+`4` & `11` | Compass heading.
+`5` & `10` | Current speed.
+`6` | Date (mission).
+`7` | Main menu button.
+`8` | Compass menu button.
+`9` | Map menu button.
+`12` | Compass
+`13` | Player heading (your eyes).
+`14` | Center the map on your position.
+`15` | Map zoom.
+`16` | Map dezoom
+`17` | Your position.
+`18` | Waypoint creation menu
+`19` | Waypoint editing menu.
+`20` | Connection menu.
+`21` | Settings menu.
+
+### 2.3 Waypoints
+#### 2.3.1 Adding waypoints
+- There's three ways of adding a waypoint.
+
+- First way: Using the waypoint creation menu.
+ - Find the position you want to mark on the map.
+ - Get it's map grid.
+ - The grid is composed of 6 digits.
+ - The first three digits are read west to east. (Top of the map screen).
+ - The last three are read south to north. (Left side of the map screen).
+ - Go to the options menu (Click in `1` area, above the bar).
+ - Click on `Mark`(`18`).
+ - Enter the grid number.
+ - Press OK.
+ - Enter the desired name of the waypoint.
+ - Press OK.
+
+- Second way: Using the waypoint menu
+ - Find the position you want to mark on the map.
+ - Get it's map grid.
+ - The grid is composed of 6 digits.
+ - The first three digits are read west to east. (Top of the map screen).
+ - The last three are read south to north. (Left side of the map screen).
+ - Go to the options menu (Click in `1` area, above the bar).
+ - CLick on `Waypoints` (`19`).
+ - Click on `Add`.
+ - Enter the grid number.
+ - Press OK.
+ - Enter the name of the waypoint.
+ - Press OK.
+
+- Third way: Using the Map menu.
+ - Go to the map menu (click on `9`)
+ - double left click on the position where you want your waypoint.
+ - Enter the name of the waypoint.
+ - Press OK.
+
+#### 2.3.2 Setting a waypoint
+- Go to the options menu (Click in `1` area, above the bar).
+- CLick on `Waypoints` (`19`).
+- Select the waypoint.
+- Click on `SetWp`.
-## Usage
+- Once a waypoint is set:
+ - It's heading, elevation and distance are marked on the main menu. (`7`)
+ - It's heading, direction, grid position and name are marked in the compass menu (`8`)
+ - A marker appear at the waypoint grid location in the map menu (`9`)
-Short overview of how to use the feature, e.g. menu options, key bindings,
-instructions. May not apply to all modules.
+#### 2.3.3 Deleting a waypoint
+- Go to the options menu (Click in `1` area, above the bar).
+- CLick on `Waypoints` (`19`).
+- Select the waypoint.
+- Click on `Delete`.
+
+### 2.4 Switching between mils and degrees
+- Go to the options menu (Click in `1` area, above the bar).
+- Click on `Settings` (`21`)
+- Double left click on the unit next to `Angular unit:`
+
+### 2.5 Switching between topographical and satellite view
+
+- Go to the map menu (`9`)
+- Click on the map menu button again (`9`)
+
+### 2.6 Retrieving data from the vector
+- For this you obviously need a `vector 21`.
+- Go to the options menu (Click in `1` area, above the bar).
+- Click on `Connect to` (`20`).
+- Pull out your `vector 21`.
+ - Press and hold both R and Tab ↹ until the red pointing circle appears.
+ - Sight the circle on the object and release both keys.
+- The data on the main menu now have changed, you can now see the azimuth the range and the elevation of the point you sighted.
+- Note that the compass menu also changed and now features the azimuth, compass bearing, distance and grid position of the point you sighted.
+
+Note that the results of the measure you took won't change until you do an other measure.
-## Dependencies
+## 3. Dependencies
`ace_common`
diff --git a/documentation/feature/missileguidance.md b/documentation/feature/missileguidance.md
index 7dd4d6a304..7231741d1a 100644
--- a/documentation/feature/missileguidance.md
+++ b/documentation/feature/missileguidance.md
@@ -13,14 +13,14 @@ Adds the AMG framework, for more information about it refer to the [AMG framewor
## 2. Usage
### 2.1 Switching fire mode
-- Press CTRL + TAB the LED's on the right of the UI will change.
+- Press Ctrl + Tab ↹ the LED's on the right of the UI will change.
- `TOP` for top down mode.
- `DIR` for direct mode.
### 2.2 Locking
- Fully zoom in by using NUMPAD +
- Switch to thermals by pressing N the `FLTR` LED should light up.
-- Aim at the target and hold TAB a crosshair will appear and the `SEEK` LED will light up.
+- Aim at the target and hold Tab ↹ a crosshair will appear and the `SEEK` LED will light up.
- Fire!
## 3. Dependencies
diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md
index eb4b22caaf..90b6512ed5 100644
--- a/documentation/feature/mk6mortar.md
+++ b/documentation/feature/mk6mortar.md
@@ -18,7 +18,7 @@ ACE3 adds wind deflection for shells as well as a rangetable to accurately take
### 2.2 Working with the rangetable
- To open the table:
- - Self interact CTRL + ⊞ Win
+ - Self interact Ctrl + ⊞ Win
- Select `equipment`.
- Select `Open 82mm Rangetable`.
@@ -34,7 +34,7 @@ ACE3 adds wind deflection for shells as well as a rangetable to accurately take
- Once you finished your maths, it's time to aim, get the cross of the mortar on target, if you don't see it use a waypoint if possible. In our case ELEV is 1339-2 = 1337.
- On the right side of the screen, while looking through the mk6 scope you should see ELV, we need to match this number with the one we found.
- - To adjust the ELV use pageUP and pageDOWN.
+ - To adjust the ELV use Page Up and page Down.
- Once the number you found and ELV are the same FIRE !
- On top of that you can calculate the time the shell will take to land by using the third row from the left, in our case the shell need to travel 2000m that's 20xthe number indicated. so 20x0,5 = 10s.
diff --git a/documentation/feature/modules.md b/documentation/feature/modules.md
new file mode 100644
index 0000000000..3b6bcef0b8
--- /dev/null
+++ b/documentation/feature/modules.md
@@ -0,0 +1,14 @@
+---
+layout: wiki
+title: Modules
+group: feature
+parent: wiki
+---
+
+## 1. Overview
+
+This is taking care of module initialization **DO NOT REMOVE**.
+
+## 2. Dependencies
+
+`ace_main`
diff --git a/documentation/feature/overheating.md b/documentation/feature/overheating.md
index dcbc4c1939..b97df663ce 100644
--- a/documentation/feature/overheating.md
+++ b/documentation/feature/overheating.md
@@ -25,12 +25,12 @@ Adds the ability to changes barrels on machine guns to compensate for those effe
### 2.2 Swapping barrels
- For this you need a `Spare barrel` and a compatible weapon.
-- Press self interaction CTRL + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
+- Press self interaction Ctrl + ⊞ Win (ACE3 default key bind `Self Interaction Key`).
- Select `Equipment`.
- Select `Swap barrel`.
### 2.3 Checking your barrel temperature
-- Press self interaction CTRL + ⊞ Win.
+- Press self interaction Ctrl + ⊞ Win.
- Select `Equipment`.
- Select `Check weapon temperature`.
diff --git a/documentation/feature/rangecard.md b/documentation/feature/rangecard.md
index b40e76cd49..6c588de45a 100644
--- a/documentation/feature/rangecard.md
+++ b/documentation/feature/rangecard.md
@@ -13,7 +13,7 @@ Add a range card that updates itself for your weapon and the type of ammo you're
## 2. Usage
### 2.1 Opening the range card
-- Open the self interaction menu CTRL + ⊞ Win
+- Open the self interaction menu Ctrl + ⊞ Win
- Select `Equipment`
- Select `Open Range Card`
diff --git a/documentation/feature/reload.md b/documentation/feature/reload.md
index 3cd4db1c8d..1d8637c290 100644
--- a/documentation/feature/reload.md
+++ b/documentation/feature/reload.md
@@ -14,7 +14,7 @@ Hides the actual round count of magazines and removes the icon when the current
## 2. Usage
### 2.1 Checking your ammo
-- Press CTRL + R (ACE3 default key bind `Check Ammo`).
+- Press Ctrl + R (ACE3 default key bind `Check Ammo`).
## 3. Dependencies
diff --git a/documentation/feature/reloadlaunchers.md b/documentation/feature/reloadlaunchers.md
index 773814a73e..3bfa739360 100644
--- a/documentation/feature/reloadlaunchers.md
+++ b/documentation/feature/reloadlaunchers.md
@@ -13,7 +13,7 @@ Add the ability to reload someone else's launcher.
### 2. Usage
### 2.1 Reloading someone else's launcher
-- Press the interaction key ⊞ Win and aim at your buddy's launcher.
+- Press the interaction key ⊞ Win and aim at your buddy's launcher.
- Select `reload launcher`.
- Select the type of ammo.
diff --git a/documentation/feature/respawn.md b/documentation/feature/respawn.md
index 753784b52b..08d3bf7feb 100644
--- a/documentation/feature/respawn.md
+++ b/documentation/feature/respawn.md
@@ -23,7 +23,7 @@ Adds rallypoints to all 3 sides to enable teleportation from base spawn to FOB's
### 2.1 Using rallypoints
- For this to work pre-emptive preparations need to be made by the mission maker.
- Approach the rallypoint flagpole
-- Use the interaction key ⊞ Win (ACE3 default key bind `Interaction key`).
+- Use the interaction key ⊞ Win (ACE3 default key bind `Interaction key`).
- Select teleport to (base / rallypoint).
diff --git a/documentation/feature/safemode.md b/documentation/feature/safemode.md
index 9024ac973b..0bcf4435de 100644
--- a/documentation/feature/safemode.md
+++ b/documentation/feature/safemode.md
@@ -14,8 +14,8 @@ You can now use the safety mode of any weapon. Switching weapon modes takes the
## 2. Usage
### 2.1 Switching safety on / off
-- To turn it on press CTRL + ` (QWERTY layout) (ACE3 default key bind `Safe Mode`).
-- To turn it off press CTRL + ` (QWERTY layout) again or switch firing mode.
+- To turn it on press Ctrl + ` (QWERTY layout) (ACE3 default key bind `Safe Mode`).
+- To turn it off press Ctrl + ` (QWERTY layout) again or switch firing mode.
## 3. Dependencies
diff --git a/documentation/feature/sandbags.md b/documentation/feature/sandbags.md
index 5e0011b755..9c0c90b7e0 100644
--- a/documentation/feature/sandbags.md
+++ b/documentation/feature/sandbags.md
@@ -15,7 +15,7 @@ Note that those sandbags are affected by physics, a rocket will send them flying
### 2.1 Placing the sandbags
- You'll need at least one `sandbag (empty)`.
- You need to be over a grass area / sand area to be able to fill the sandbag.
-- Self interact CTRL+⊞ Win (ACE3 default).
+- Self interact Ctrl+⊞ Win (ACE3 default).
- Select `Deploy sandbag`.
- Follow the instruction on screen.
diff --git a/documentation/feature/scopes.md b/documentation/feature/scopes.md
index 9e70641f71..cfcee4a687 100644
--- a/documentation/feature/scopes.md
+++ b/documentation/feature/scopes.md
@@ -15,16 +15,16 @@ Allows snipers to adjust their scopes horizontally and vertically in mils.
### 2.1 Adjusting your scope vertically
Please not that the following key combinations are ACE3 default key binds.
-- Minor adjustment up pageUP.
-- Minor adjustment down pageDOWN.
-- Major adjustment up Shift + pageUP.
-- Major adjustment down Shift + pageDOWN.
+- Minor adjustment up Page Up.
+- Minor adjustment down page Down.
+- Major adjustment up ⇧ Shift + Page Up.
+- Major adjustment down ⇧ Shift + page Down.
### 2.2 Adjusting your scope horizontally
-- Minor adjustment right CTRL + pageUP.
-- Minor adjustment left CTRL + pageDOWN.
-- Major adjustment right CTRL + Shift + pageUP.
-- Major adjustment left CTRL + Shift + pageDOWN.
+- Minor adjustment right Ctrl + Page Up.
+- Minor adjustment left Ctrl + page Down.
+- Major adjustment right Ctrl + ⇧ Shift + Page Up.
+- Major adjustment left Ctrl + ⇧ Shift + page Down.
## 3. Dependencies
diff --git a/documentation/feature/spotting_scope.md b/documentation/feature/spotting_scope.md
index ead45d540f..a2b9bdf19d 100644
--- a/documentation/feature/spotting_scope.md
+++ b/documentation/feature/spotting_scope.md
@@ -12,7 +12,7 @@ Adds a deployable spotting scope.
## 2. Usage
### 2.1 Deploying the spotting scope
-- Self interact CTRL+⊞ Win (ACE3 default).
+- Self interact Ctrl+⊞ Win (ACE3 default).
- Select `Equipment`.
- Select `Place spotting scope` (note that the scope will be at your feet).
diff --git a/documentation/feature/tacticallader.md b/documentation/feature/tacticallader.md
index f992236db6..9ed4b9459d 100644
--- a/documentation/feature/tacticallader.md
+++ b/documentation/feature/tacticallader.md
@@ -12,9 +12,9 @@ Adds a deployable ladder with adjustable height that you can transport on your b
## 2. Usage
### 2.1 Deploying the ladder
-- Self interact CTRL+⊞ Win (ACE3 default).
+- Self interact Ctrl+⊞ Win (ACE3 default).
- Select `Deploy ladder`.
-- You can adjust it's position and height by interacting with it ⊞ Win (ACE3 default) and following the instructions on screen.
+- You can adjust it's position and height by interacting with it ⊞ Win (ACE3 default) and following the instructions on screen.
## 3. Dependencies
diff --git a/documentation/feature/tripod.md b/documentation/feature/tripod.md
index 4f57dc05a7..f6f49ba3d1 100644
--- a/documentation/feature/tripod.md
+++ b/documentation/feature/tripod.md
@@ -13,12 +13,12 @@ Adds a packable tripod deployable on the field. It features a flat part to deplo
### 2.1 deploying the tripod
- Note that you need a `SSWT kit` in your inventory.
-- Self interact CTRL+⊞ Win.
+- Self interact Ctrl+⊞ Win.
- Select `Equipment`
- Select `Place SSWT kit`.
-To adjust or pick up the tripod just interact with it ⊞ Win and select the desired action.
+To adjust or pick up the tripod just interact with it ⊞ Win and select the desired action.
## 3. Dependencies
-`ace_interaction`
\ No newline at end of file
+`ace_interaction`
diff --git a/documentation/feature/vector.md b/documentation/feature/vector.md
index 025012959a..4dbf4440a1 100644
--- a/documentation/feature/vector.md
+++ b/documentation/feature/vector.md
@@ -32,12 +32,12 @@ The Vector is controlled with 2 keys: the azimuth key and the range key; Ta
#### 2.2 Azimuth
-- Press and hold the TAB until the azimuth is displayed.
+- Press and hold the Tab ↹ until the azimuth is displayed.
#### 2.3 Slope distance and Azimuth
-- Press and hold both R and TAB until the red pointing circle appears.
+- Press and hold both R and Tab ↹ until the red pointing circle appears.
- Sight the circle on the object and release both keys.
#### 2.4 Horizontal distance and height difference
@@ -49,35 +49,35 @@ The Vector is controlled with 2 keys: the azimuth key and the range key; Ta
#### 2.5 Azimuth and Inclination
-- Tap TAB once then press and hold it until the azimuth and inclination is displayed.
+- Tap Tab ↹ once then press and hold it until the azimuth and inclination is displayed.
#### 2.6 Distance between two points
- Press and hold R until the red pointing circle appears.
-- Sight the circle on the first object and tap TAB while further holding R. The first measurement is confirmed ("1-P" = first point).
+- Sight the circle on the first object and tap Tab ↹ while further holding R. The first measurement is confirmed ("1-P" = first point).
- Sight the second object and release R.
#### 2.7 Horizontal and vertical distance between two points
- Tap R once then press and hold it until the red pointing circle appears.
-- Sight the circle on the object and tap TAB once. The first measurement is confirmed ("1-P" = first point).
+- Sight the circle on the object and tap Tab ↹ once. The first measurement is confirmed ("1-P" = first point).
- Sight the second object and release R.
#### 2.8 Horizontal distance and azimuth between two points
-- Press and hold TAB until the azimuth appears.
-- Sight the circle on the first object and tap R while further holding TAB. The first measurement is confirmed ("1-P" = first point).
-- Sight the second object and release TAB.
+- Press and hold Tab ↹ until the azimuth appears.
+- Sight the circle on the first object and tap R while further holding Tab ↹. The first measurement is confirmed ("1-P" = first point).
+- Sight the second object and release Tab ↹.
### 2.9 Fall of shot
-- Tap TAB once then press and hold it until the azimuth appears.
-- Sight the circle on the object and tap R while further holding TAB. The first measurement is confirmed ("1-P" = first point).
-- Sight the Fall of shot and release TAB. The left digits display the left (`L`)/right (`r`) correction value in meter and the right digits display the longer (`A` = add)/shorter (`d` = drop) correction value in meter. If R is tapped the height correction values will be displayed (`UP` and `dn`).
+- Tap Tab ↹ once then press and hold it until the azimuth appears.
+- Sight the circle on the object and tap R while further holding Tab ↹. The first measurement is confirmed ("1-P" = first point).
+- Sight the Fall of shot and release Tab ↹. The left digits display the left (`L`)/right (`r`) correction value in meter and the right digits display the longer (`A` = add)/shorter (`d` = drop) correction value in meter. If R is tapped the height correction values will be displayed (`UP` and `dn`).
## 3. Dependencies
diff --git a/documentation/feature/vehicles.md b/documentation/feature/vehicles.md
index 3f78b654b2..a58d314194 100644
--- a/documentation/feature/vehicles.md
+++ b/documentation/feature/vehicles.md
@@ -41,6 +41,10 @@ MBT main guns and mortars can no longer lock on enemies. The AT rounds of both n
- To turn the engine on press 2.
- To turn the engine off press 1.
+### 2.2 Turning the speed limiter on / off
+- To turn the speed limiter on press Del.
+- To turn it off press Del again.
+
## 3. Dependencies
`ace_common`
diff --git a/documentation/framework/carry-drag.md b/documentation/framework/carry-drag.md
index 988797ba79..cfa4eb13af 100644
--- a/documentation/framework/carry-drag.md
+++ b/documentation/framework/carry-drag.md
@@ -26,3 +26,71 @@ class CfgVehicles {
};
```
+## 2. Functions
+
+**NOTE THAT THE FOLLOWING FUNCTIONS ARE NOT PUBLIC AND THUS MAY CHANGE IN THE FUTURE.**
+
+
+Also note that if the item is too heavy you won't be able to carry / drag it, the mass is also affected by what's inside it.
+To bypass this empty the object and / or use setMass.
+
+### 2.1 Enabling / disabling dragging
+
+`ace_dragging_fnc_setDraggable.`
+Enable the object to be dragged.
+
+| Arguments | |
+--------------| -------- |
+0 | Any object (Object)
+1: | true to enable dragging, false to disable (Bool)
+2:| Position offset for attachTo command (Array, optional; default: [0,0,0])
+3: | Direction in degree to rotate the object after attachTo (Number, optional; default: 0)
+Return value: NONE
+
+#### 2.1.1 example 1:
+```
+[foo,true,[0,2,0],45] call ace_dragging_fnc_setDraggable
+```
+| Arguments | |
+--------------| -------- |
+0:| foo (my object)
+1:| true (dragging is enabled)
+2:| `[0,2,0]` (0 meters sideways, 2 meters forward, 0 meters upwards)
+3:| 45 (the object is rotated by 45°)
+
+#### 2.1.2 example 2
+```
+[bar,false,[3,-2,2],20] call ace_dragging_fnc_setDraggable
+```
+
+| Arguments | |
+--------------| -------- |
+0:| bar (object)
+1:| false (dragging is disabled)
+2:| 3 meters sideways, -2 meters backwards, 2 meters upwards
+3:| the object is rotated by 20°
+
+### 2.2 Enabling / disabling carrying
+`ace_dragging_fnc_setCarryable.`
+Enable the object to be carried.
+
+| Arguments | |
+--------------| -------- |
+0 | Any object (Object)
+1:| true to enable carrying, false to disable (Bool)
+2:| Position offset for attachTo command (Array, optional; default: [0,1,1])
+3:| Direction in degree to rotate the object after attachTo (Number, optional; default: 0)
+Return value: NONE
+
+
+#### 2.1.1 example 1:
+```
+[foo,true,[0,3,1],10] call ace_dragging_fnc_setCarryable
+```
+| Arguments | |
+--------------| -------- |
+0:| foo (my object)
+1:| true (carrying is enabled)
+2:| `[0,2,0]` (0 meters sideways, 3 meters forward, 1 meters upwards)
+3:| 10 (the object is rotated by 10°)
+
diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt
index 2382e64558..ed8dd066e4 100644
--- a/extensions/CMakeLists.txt
+++ b/extensions/CMakeLists.txt
@@ -126,6 +126,7 @@ add_subdirectory(break_line)
add_subdirectory(clipboard)
add_subdirectory(advanced_ballistics)
add_subdirectory(medical)
+add_subdirectory(parse_imagepath)
# Test Extension for dynamically loading/unloading built extensions; does not build in release
if (DEVEL)
diff --git a/extensions/parse_imagepath/CMakeLists.txt b/extensions/parse_imagepath/CMakeLists.txt
new file mode 100644
index 0000000000..e38a4bb506
--- /dev/null
+++ b/extensions/parse_imagepath/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(ACE_EXTENSION_NAME "ace_parse_imagepath")
+
+file(GLOB SOURCES *.h *.hpp *.c *.cpp)
+add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES})
+target_link_libraries(${ACE_EXTENSION_NAME} ace_common)
+set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "")
+set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions)
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1)
+ set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_END_STATIC 1)
+endif()
\ No newline at end of file
diff --git a/extensions/parse_imagepath/ace_parse_imagepath.cpp b/extensions/parse_imagepath/ace_parse_imagepath.cpp
new file mode 100644
index 0000000000..051535e473
--- /dev/null
+++ b/extensions/parse_imagepath/ace_parse_imagepath.cpp
@@ -0,0 +1,54 @@
+/*
+ * ace_parse_imagepath.cpp
+ * Author: PabstMirror
+ * Gets raw image path from structured text input.
+ *
+ * Takes:
+ * Structured text that usualy has an image:
+ * Example: "
";
+ *
+ * Returns:
+ * Just the image path or "" if none
+ */
+
+#include "shared.hpp"
+
+#include
+#include
+
+extern "C" {
+ __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
+};
+
+std::string getImagePathFromStructuredText(const std::string & input) {
+ std::string returnValue = "";
+ std::size_t endIndex = input.find(".paa");
+ std::size_t startIndex = endIndex - 1;
+ if ((endIndex != std::string::npos) && (endIndex > 1)) {
+ endIndex = endIndex + 4;
+ while ((startIndex > 0) && (returnValue == "")) {
+ if ((input[startIndex]) == '\'') {
+ returnValue = input.substr((startIndex + 1), (endIndex - startIndex - 1));
+ };
+ startIndex = startIndex - 1;
+ };
+ };
+ return returnValue;
+}
+
+// i like to live dangerously. jk, fix strncpy sometime pls.
+#pragma warning( push )
+#pragma warning( disable : 4996 )
+
+void __stdcall RVExtension(char *output, int outputSize, const char *function) {
+ ZERO_OUTPUT();
+ if (!strcmp(function, "version")) {
+ strncpy(output, ACE_FULL_VERSION_STR, outputSize);
+ } else {
+ strncpy(output, getImagePathFromStructuredText(function).c_str(), outputSize);
+ output[outputSize - 1] = '\0';
+ }
+ EXTENSION_RETURN();
+}
+
+#pragma warning( pop )
diff --git a/extras/assets/icons/png/Icon_Actions/disarm.png b/extras/assets/icons/Icon_Actions_png/disarm.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Actions/disarm.png
rename to extras/assets/icons/Icon_Actions_png/disarm.png
diff --git a/extras/assets/icons/icon_microDAGR.png b/extras/assets/icons/Icon_Actions_png/icon_microDAGR.png
similarity index 100%
rename from extras/assets/icons/icon_microDAGR.png
rename to extras/assets/icons/Icon_Actions_png/icon_microDAGR.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Ambient_Sounds_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Ambient_Sounds_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Ambient_Sounds_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Ambient_Sounds_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_BFTracking_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_BFTracking_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_BFTracking_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_BFTracking_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_CheckPBO_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_CheckPBO_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_CheckPBO_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_CheckPBO_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Explosives_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Explosives_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Explosives_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Explosives_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_FriendlyFire_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_FriendlyFire_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_FriendlyFire_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_FriendlyFire_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Hearing_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Hearing_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Hearing_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Hearing_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Interaction_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Interaction_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Interaction_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Interaction_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_LSD_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_LSD_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_LSD_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_LSD_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Make_Unit_Surrender_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Make_Unit_Surrender_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Make_Unit_Surrender_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Make_Unit_Surrender_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Map_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Map_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Map_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Map_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Medical_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Medical_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Medical_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Medical_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_NameTags_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_NameTags_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_NameTags_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_NameTags_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Rallypoint_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Rallypoint_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Rallypoint_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Rallypoint_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Repair_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Repair_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Repair_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Repair_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Respawn_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Respawn_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Respawn_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Respawn_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icons_Module_Sitting_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Sitting_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icons_Module_Sitting_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Sitting_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_SwitchUnits_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_SwitchUnits_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_SwitchUnits_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_SwitchUnits_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_VehicleKey_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_VehicleKey_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_VehicleKey_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_VehicleKey_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_VehicleLock_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_VehicleLock_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_VehicleLock_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_VehicleLock_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Wind_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Wind_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Wind_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Wind_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Captive_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Captive_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Captive_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Captive_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Settings_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Settings_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Settings_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Settings_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Surrender_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Surrender_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Surrender_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Surrender_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Unconscious_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Unconscious_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_Zeus_Unconscious_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_Zeus_Unconscious_ca.png
diff --git a/extras/assets/icons/png/Icon_Module/Icon_Module_microDAGR_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_microDAGR_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module/Icon_Module_microDAGR_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_microDAGR_ca.png
diff --git a/extras/assets/icons/png/Icon_Module_mk6_ca.png b/extras/assets/icons/Icon_Module_png/Icon_Module_mk6_ca.png
similarity index 100%
rename from extras/assets/icons/png/Icon_Module_mk6_ca.png
rename to extras/assets/icons/Icon_Module_png/Icon_Module_mk6_ca.png
diff --git a/optionals/compat_bwa3/CfgAmmo.hpp b/optionals/compat_bwa3/CfgAmmo.hpp
index 599651ac10..c19e00819a 100644
--- a/optionals/compat_bwa3/CfgAmmo.hpp
+++ b/optionals/compat_bwa3/CfgAmmo.hpp
@@ -3,6 +3,7 @@ class CfgAmmo {
class B_556x45_Ball_Tracer_Red;
class B_762x51_Tracer_Red;
class B_127x99_Ball_Tracer_Red;
+ class GrenadeHand;
class BWA3_B_556x45_Ball: B_556x45_Ball_Tracer_Red {
ACE_caliber=5.69;
ACE_bulletLength=23.012;
@@ -132,4 +133,10 @@ class CfgAmmo {
ACE_muzzleVelocities[]={};
ACE_barrelLengths[]={};
};
+ class BWA3_G_DM51A1: GrenadeHand {
+ ace_frag_metal = 296;
+ ace_frag_charge = 180;
+ ace_frag_gurney_c = 2930; // Gurney velocity constant for PETN
+ ace_frag_gurney_k = 1/2; // shape factor for a cylinder
+ };
};
\ No newline at end of file
diff --git a/optionals/compat_bwa3/CfgMagazines.hpp b/optionals/compat_bwa3/CfgMagazines.hpp
new file mode 100644
index 0000000000..bf43af6426
--- /dev/null
+++ b/optionals/compat_bwa3/CfgMagazines.hpp
@@ -0,0 +1,9 @@
+class CfgMagazines {
+ class CA_Magazine;
+ class BWA3_200Rnd_556x45: CA_Magazine {
+ ACE_isBelt = 1;
+ };
+ class BWA3_120Rnd_762x51: CA_Magazine {
+ ACE_isBelt = 1;
+ };
+};
\ No newline at end of file
diff --git a/optionals/compat_bwa3/CfgWeapons.hpp b/optionals/compat_bwa3/CfgWeapons.hpp
index 731396ed73..c0acea9912 100644
--- a/optionals/compat_bwa3/CfgWeapons.hpp
+++ b/optionals/compat_bwa3/CfgWeapons.hpp
@@ -2,6 +2,7 @@ class CfgWeapons {
class Pistol_Base_F;
class Rifle_Base_F;
class Rifle_Long_Base_F;
+ class UGL_F;
class BWA3_P8: Pistol_Base_F {
ACE_barrelTwist=248.92;
ACE_barrelLength=108;
@@ -30,6 +31,13 @@ class CfgWeapons {
ACE_barrelTwist=304.8;
ACE_barrelLength=406;
};
+ class BWA3_G27_AG: BWA3_G27 {
+ class AG40: UGL_F {
+ magazines[] += {
+ "ACE_HuntIR_M203"
+ };
+ };
+ };
class BWA3_MG4: Rifle_Long_Base_F {
ACE_barrelTwist=177.8;
ACE_barrelLength=480;
@@ -42,7 +50,11 @@ class CfgWeapons {
ACE_barrelTwist=381.0;
ACE_barrelLength=736.7;
};
-
+ class AG40: UGL_F {
+ magazines[] += {
+ "ACE_HuntIR_M203"
+ };
+ };
class optic_Hamr;
class InventoryOpticsItem_Base_F;
diff --git a/optionals/compat_bwa3/config.cpp b/optionals/compat_bwa3/config.cpp
index e1ca37d121..efdebaf616 100644
--- a/optionals/compat_bwa3/config.cpp
+++ b/optionals/compat_bwa3/config.cpp
@@ -13,3 +13,4 @@ class CfgPatches {
#include "CfgAmmo.hpp"
#include "CfgWeapons.hpp"
+#include "CfgMagazines.hpp"
diff --git a/optionals/compat_rhs_afrf3/CfgMagazines.hpp b/optionals/compat_rhs_afrf3/CfgMagazines.hpp
index 6acd70844a..92444a380b 100644
--- a/optionals/compat_rhs_afrf3/CfgMagazines.hpp
+++ b/optionals/compat_rhs_afrf3/CfgMagazines.hpp
@@ -5,13 +5,13 @@ class cfgMagazines {
class rhs_100Rnd_762x54mmR: rhs_30Rnd_545x39_AK {
ace_isbelt = 1;
};
- class rhs_100Rnd_762x54mmR_green: rhs_100Rnd_762x54mmR {
+ class rhs_mag_127x108mm_50: VehicleMagazine {
ace_isbelt = 1;
};
- class rhs_mag_127x108mm_50 : VehicleMagazine {
- ace_isbelt = 1;
+ class rhs_mag_127x108mm_150: rhs_mag_127x108mm_50 {
+ ace_isbelt = 0;
};
- class rhs_mag_127x108mm_150 : rhs_mag_127x108mm_50 {
+ class rhs_mag_127x108mm_1470 : rhs_mag_127x108mm_50 {
ace_isbelt = 0;
};
};
\ No newline at end of file
diff --git a/optionals/compat_rhs_afrf3/CfgWeapons.hpp b/optionals/compat_rhs_afrf3/CfgWeapons.hpp
index 4c3e2e425e..0c3d3dfac4 100644
--- a/optionals/compat_rhs_afrf3/CfgWeapons.hpp
+++ b/optionals/compat_rhs_afrf3/CfgWeapons.hpp
@@ -57,7 +57,7 @@ class CfgWeapons
ACE_barrelTwist=195.072;
ACE_barrelLength=589.28;
};
-
+
class rhs_acc_sniper_base;
class rhs_acc_pso1m2: rhs_acc_sniper_base {
ACE_ScopeAdjust_Vertical[] = { 0, 0 };
@@ -65,8 +65,29 @@ class CfgWeapons
ACE_ScopeAdjust_VerticalIncrement = 0.0;
ACE_ScopeAdjust_HorizontalIncrement = 0.5;
};
+
class Launcher_Base_F;
class rhs_weap_rpg7: Launcher_Base_F {
ace_reloadlaunchers_enabled = 1;
};
+
+ class H_HelmetB;
+ class rhs_tsh4: H_HelmetB {
+ ace_hearing_protection = 1;
+ ace_hearing_lowerVolume = 0.80;
+ };
+ class rhs_tsh4_ess: rhs_tsh4 {};
+ class rhs_tsh4_bala: rhs_tsh4 {};
+ class rhs_tsh4_ess_bala: rhs_tsh4 {};
+
+ class rhs_zsh7a: H_HelmetB {
+ ace_hearing_protection = 1;
+ ace_hearing_lowerVolume = 0.80;
+ };
+ class rhs_zsh7a_mike: rhs_zsh7a {};
+
+ class rhs_gssh18: H_HelmetB {
+ ace_hearing_protection = 0.5;
+ ace_hearing_lowerVolume = 0.60;
+ };
};
\ No newline at end of file
diff --git a/optionals/compat_rhs_afrf3/config.cpp b/optionals/compat_rhs_afrf3/config.cpp
index 5e88ad2830..123f80b566 100644
--- a/optionals/compat_rhs_afrf3/config.cpp
+++ b/optionals/compat_rhs_afrf3/config.cpp
@@ -5,7 +5,7 @@ class CfgPatches {
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
- requiredAddons[] = {"rhs_c_weapons"};
+ requiredAddons[] = {"rhs_c_weapons", "rhs_c_troops"};
author[]={"Ruthberg"};
VERSION_CONFIG;
};
diff --git a/optionals/compat_rhs_usf3/CfgMagazines.hpp b/optionals/compat_rhs_usf3/CfgMagazines.hpp
index f067cd6eee..e067d1f293 100644
--- a/optionals/compat_rhs_usf3/CfgMagazines.hpp
+++ b/optionals/compat_rhs_usf3/CfgMagazines.hpp
@@ -10,16 +10,7 @@ class cfgMagazines {
class rhsusf_100Rnd_556x45_M200_soft_pouch: rhs_mag_30Rnd_556x45_M200_Stanag {
ace_isbelt = 1;
};
- class rhsusf_200Rnd_556x45_soft_pouch: rhsusf_100Rnd_556x45_soft_pouch {
- ace_isbelt = 1;
- };
- class rhsusf_100Rnd_762x51: CA_Magazine {
- ace_isbelt = 1;
- };
- class rhsusf_100Rnd_762x51_m80a1epr: rhsusf_100Rnd_762x51 {
- ace_isbelt = 1;
- };
- class rhsusf_100Rnd_762x51_m993: rhsusf_100Rnd_762x51 {
+ class rhsusf_50Rnd_762x51: CA_Magazine {
ace_isbelt = 1;
};
class rhs_mag_100rnd_127x99_mag: VehicleMagazine {
diff --git a/optionals/compat_rhs_usf3/CfgWeapons.hpp b/optionals/compat_rhs_usf3/CfgWeapons.hpp
index e2e1efc00e..d5ab60f3eb 100644
--- a/optionals/compat_rhs_usf3/CfgWeapons.hpp
+++ b/optionals/compat_rhs_usf3/CfgWeapons.hpp
@@ -5,7 +5,7 @@ class CfgWeapons
class Rifle_Base_F;
class srifle_EBR_F;
class launch_O_Titan_F;
-
+
class rhs_weap_XM2010_Base_F: Rifle_Base_F {
ACE_barrelTwist=254.0;
ACE_barrelLength=609.6;
@@ -51,11 +51,13 @@ class CfgWeapons
ACE_twistDirection=0;
ACE_barrelLength=508.0;
};
+
class hgun_ACPC2_F;
class rhsusf_weap_m1911a1: hgun_ACPC2_F {
ACE_barrelTwist=406.4;
ACE_barrelLength=127.0;
};
+
class rhsusf_acc_sniper_base;
class rhsusf_acc_LEUPOLDMK4: rhsusf_acc_sniper_base {
ACE_ScopeAdjust_Vertical[] = { -4, 30 };
@@ -69,13 +71,50 @@ class CfgWeapons
ACE_ScopeAdjust_VerticalIncrement = 0.1;
ACE_ScopeAdjust_HorizontalIncrement = 0.1;
};
+
class rhs_weap_fgm148 : launch_O_Titan_F {
ace_javelin_enabled = 1;
weaponInfoType = "ACE_RscOptics_javelin";
modelOptics = "\z\ace\addons\javelin\data\reticle_titan.p3d";
-
+
canLock = 0;
lockingTargetSound[] = {"",0,1};
lockedTargetSound[] = {"",0,1};
};
+
+ class rhsusf_opscore_01;
+ class rhsusf_cvc_helmet: rhsusf_opscore_01 {
+ ace_hearing_protection = 1;
+ ace_hearing_lowerVolume = 0.80;
+ };
+ class rhsusf_cvc_green_helmet: rhsusf_cvc_helmet {};
+ class rhsusf_cvc_ess: rhsusf_cvc_helmet {};
+ class rhsusf_cvc_green_ess: rhsusf_cvc_ess {};
+
+ class H_PilotHelmetHeli_B;
+ class H_CrewHelmetHeli_B;
+ class rhsusf_hgu56p: H_PilotHelmetHeli_B
+ {
+ ace_hearing_protection = 0.75;
+ ace_hearing_lowerVolume = 0.70;
+ };
+ class rhsusf_hgu56p_mask: H_CrewHelmetHeli_B
+ {
+ ace_hearing_protection = 0.75;
+ ace_hearing_lowerVolume = 0.70;
+ };
+
+ class H_HelmetB;
+ class RHS_jetpilot_usaf: H_HelmetB {
+ ace_hearing_protection = 1;
+ ace_hearing_lowerVolume = 0.80;
+ };
+
+ class rhsusf_ach_helmet_ocp;
+ class rhsusf_opscore_01: rhsusf_ach_helmet_ocp {
+ ace_hearing_protection = 0.50;
+ ace_hearing_lowerVolume = 0.60;
+ };
+ class rhsusf_opscore_01_tan: rhsusf_opscore_01 {};
+ class rhsusf_opscore_03_ocp: rhsusf_opscore_01 {};
};
diff --git a/optionals/compat_rhs_usf3/config.cpp b/optionals/compat_rhs_usf3/config.cpp
index 9a13565ccf..3e9aee6ec7 100644
--- a/optionals/compat_rhs_usf3/config.cpp
+++ b/optionals/compat_rhs_usf3/config.cpp
@@ -5,7 +5,7 @@ class CfgPatches {
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
- requiredAddons[] = {"rhsusf_c_weapons"};
+ requiredAddons[] = {"rhsusf_c_weapons", "rhsusf_c_troops"};
author[]={"Ruthberg"};
VERSION_CONFIG;
};
diff --git a/optionals/tracers/CfgAmmo.hpp b/optionals/tracers/CfgAmmo.hpp
index 7155087627..a432be3286 100644
--- a/optionals/tracers/CfgAmmo.hpp
+++ b/optionals/tracers/CfgAmmo.hpp
@@ -1,217 +1,159 @@
class CfgAmmo {
- class B_556x45_Ball;
- class B_556x45_Ball_Tracer_Red : B_556x45_Ball {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_556x45_Ball_Tracer_Green : B_556x45_Ball {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_556x45_Ball_Tracer_Yellow : B_556x45_Ball {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class ACE_545x39_Ball_7T3M : B_556x45_Ball_Tracer_Green {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_65x39_Case;
- class B_65x39_Case_green: B_65x39_Case {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_65x39_Case_yellow: B_65x39_Case {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_65x39_Caseless;
- class B_65x39_Caseless_green: B_65x39_Caseless {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_65x39_Caseless_yellow: B_65x39_Caseless {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_762x51_Ball;
- class B_762x51_Tracer_Red: B_762x51_Ball {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_762x51_Tracer_Green: B_762x51_Ball {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_762x51_Tracer_Yellow: B_762x51_Ball {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_762x54_Ball;
- class B_762x54_Tracer_Red: B_762x54_Ball {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_762x54_Tracer_Green: B_762x54_Ball {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_762x54_Tracer_Yellow: B_762x54_Ball {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class ACE_762x54_Ball_7T2 : B_762x54_Tracer_Green {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class ACE_762x39_Ball_57N231P : B_762x54_Tracer_Green {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_9x21_Ball;
- class B_9x21_Ball_Tracer_Green: B_9x21_Ball {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_127x99_Ball;
- class B_127x99_Ball_Tracer_Red: B_127x99_Ball {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_127x99_Ball_Tracer_Green: B_127x99_Ball {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_127x99_Ball_Tracer_Yellow: B_127x99_Ball {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_127x99_SLAP;
- class B_127x99_SLAP_Tracer_Red: B_127x99_SLAP {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_127x99_SLAP_Tracer_Green: B_127x99_SLAP {
- model = PATHTOF(ace_TracerGreen2.p3d);
- };
- class B_127x99_SLAP_Tracer_Yellow: B_127x99_SLAP {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_30mm_HE;
- class B_30mm_HE_Tracer_Red: B_30mm_HE {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_30mm_HE_Tracer_Green: B_30mm_HE {
- model = PATHTOF(tracer_green_2.p3d);
- };
- class B_30mm_HE_Tracer_Yellow: B_30mm_HE {
- model = PATHTOF(tracer_yellow_2.p3d);
- };
- class B_40mm_GPR;
- class B_40mm_GPR_Tracer_Red: B_40mm_GPR {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_40mm_GPR_Tracer_Green: B_40mm_GPR {
- model = PATHTOF(tracer_green_2.p3d);
- };
- class B_40mm_GPR_Tracer_Yellow: B_40mm_GPR {
- model = PATHTOF(tracer_yellow_2.p3d);
- };
- class B_20mm;
- class B_20mm_Tracer_Red: B_20mm {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_30mm_AP;
- class B_30mm_AP_Tracer_Red: B_30mm_AP {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_30mm_AP_Tracer_Green: B_30mm_AP {
- model = PATHTOF(tracer_green_2.p3d);
- };
- class B_30mm_AP_Tracer_Yellow: B_30mm_AP {
- model = PATHTOF(tracer_yellow_2.p3d);
- };
- class B_30mm_APFSDS;
- class B_30mm_APFSDS_Tracer_Red: B_30mm_APFSDS {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_30mm_APFSDS_Tracer_Green: B_30mm_APFSDS {
- model = PATHTOF(tracer_green_2.p3d);
- };
- class B_30mm_APFSDS_Tracer_Yellow: B_30mm_APFSDS {
- model = PATHTOF(tracer_yellow_2.p3d);
- };
- class B_35mm_AA;
- class B_35mm_AA_Tracer_Red: B_35mm_AA {
- model = PATHTOF(tracer_red_2.p3d);
- };
- class B_35mm_AA_Tracer_Green: B_35mm_AA {
- model = PATHTOF(tracer_green_2.p3d);
- };
- class B_35mm_AA_Tracer_Yellow: B_35mm_AA {
- model = PATHTOF(tracer_yellow_2.p3d);
- };
- class Sh_120mm_HE;
- class Sh_120mm_HE_Tracer_Red: Sh_120mm_HE {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_120mm_HE_Tracer_Green: Sh_120mm_HE {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_120mm_HE_Tracer_Yellow: Sh_120mm_HE {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
- class Sh_120mm_APFSDS;
- class Sh_120mm_APFSDS_Tracer_Red: Sh_120mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_120mm_APFSDS_Tracer_Green: Sh_120mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_120mm_APFSDS_Tracer_Yellow: Sh_120mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
+ class BulletBase;
+ class ShellBase;
class SubmunitionBullet;
- class B_762x51_Minigun_Tracer_Red: SubmunitionBullet {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_762x51_Minigun_Tracer_Yellow: B_762x51_Minigun_Tracer_Red {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
- class B_762x51_Minigun_Tracer_Red_splash: B_762x51_Ball {
- model = PATHTOF(ace_TracerRed2.p3d);
- };
- class B_762x51_Minigun_Tracer_Yellow_splash: B_762x51_Minigun_Tracer_Red_splash {
- model = PATHTOF(ace_TracerYellow2.p3d);
- };
+
+ //No idea
+ class B_56x15_dual: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+
+ //Pistol
+ class B_9x21_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+ class B_9x21_Ball_Tracer_Green: B_9x21_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ class B_45ACP_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_45ACP_Ball_Green: B_45ACP_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_45ACP_Ball_Yellow: B_45ACP_Ball {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ //Assault rifle
+ class B_556x45_Ball: BulletBase {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+ class B_556x45_Ball_Tracer_Red: B_556x45_Ball {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_556x45_Ball_Tracer_Green: B_556x45_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_556x45_Ball_Tracer_Yellow: B_556x45_Ball {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_65x39_Caseless: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_65x39_Caseless_green: B_65x39_Caseless {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_65x39_Caseless_yellow: B_65x39_Caseless {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_65x39_Case;
+ class B_65x39_Case_green: B_65x39_Case {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_65x39_Case_yellow: B_65x39_Case {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_65x39_Minigun_Caseless: SubmunitionBullet {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_65x39_Minigun_Caseless_Red_splash;
+ class B_65x39_Minigun_Caseless_Yellow_splash: B_65x39_Minigun_Caseless_Red_splash {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+ class B_65x39_Minigun_Caseless_Green_splash: B_65x39_Minigun_Caseless_Red_splash {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ //Battle rifle
+ class B_762x51_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+ class B_762x51_Tracer_Red: B_762x51_Ball {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_762x51_Tracer_Green: B_762x51_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_762x51_Tracer_Yellow: B_762x51_Ball {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_762x51_Minigun_Tracer_Red: SubmunitionBullet {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_762x51_Minigun_Tracer_Red_splash: B_762x51_Ball {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+
+ class B_762x51_Minigun_Tracer_Yellow: B_762x51_Minigun_Tracer_Red {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+ class B_762x51_Minigun_Tracer_Yellow_splash: B_762x51_Minigun_Tracer_Red_splash {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_762x54_Ball;
+ class B_762x54_Tracer_Red: B_762x54_Ball {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_762x54_Tracer_Green: B_762x54_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_762x54_Tracer_Yellow: B_762x54_Ball {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ //Sniper rifle
+ class B_127x99_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+ class B_127x99_Ball_Tracer_Red: B_127x99_Ball {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_127x99_Ball_Tracer_Green: B_127x99_Ball {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_127x99_Ball_Tracer_Yellow: B_127x99_Ball {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_127x99_SLAP;
+ class B_127x99_SLAP_Tracer_Red: B_127x99_SLAP {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_127x99_SLAP_Tracer_Green: B_127x99_SLAP {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_127x99_SLAP_Tracer_Yellow: B_127x99_SLAP {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_408_Ball: BulletBase {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_127x33_Ball: BulletBase {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ class B_127x108_Ball: BulletBase {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ class B_338_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+
+ class B_338_NM_Ball: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+
+ class B_127x54_Ball: BulletBase {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ class B_93x64_Ball: BulletBase {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+
+ //Autocannon
+ class B_19mm_HE: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+
+ class B_30mm_HE;
+ class B_30mm_HE_Tracer_Red: B_30mm_HE {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_30mm_HE_Tracer_Green: B_30mm_HE {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_30mm_HE_Tracer_Yellow: B_30mm_HE {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_30mm_MP;
+ class B_30mm_MP_Tracer_Red: B_30mm_MP {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_30mm_MP_Tracer_Green: B_30mm_MP {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_30mm_MP_Tracer_Yellow: B_30mm_MP {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_40mm_GPR;
+ class B_40mm_GPR_Tracer_Red: B_40mm_GPR {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_40mm_GPR_Tracer_Green: B_40mm_GPR {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_40mm_GPR_Tracer_Yellow: B_40mm_GPR {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_20mm: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_20mm_Tracer_Red: B_20mm {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+
+ class B_25mm: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+
+ class B_30mm_AP: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+ class B_30mm_AP_Tracer_Red: B_30mm_AP {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_30mm_AP_Tracer_Green: B_30mm_AP {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_30mm_AP_Tracer_Yellow: B_30mm_AP {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_30mm_APFSDS;
+ class B_30mm_APFSDS_Tracer_Red: B_30mm_APFSDS {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_30mm_APFSDS_Tracer_Green: B_30mm_APFSDS {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_30mm_APFSDS_Tracer_Yellow: B_30mm_APFSDS {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_40mm_APFSDS;
+ class B_40mm_APFSDS_Tracer_Red: B_40mm_APFSDS {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_40mm_APFSDS_Tracer_Green: B_40mm_APFSDS {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_40mm_APFSDS_Tracer_Yellow: B_40mm_APFSDS {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class B_35mm_AA: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_white
+ class B_35mm_AA_Tracer_Red: B_35mm_AA {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red
+ class B_35mm_AA_Tracer_Green: B_35mm_AA {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green
+ class B_35mm_AA_Tracer_Yellow: B_35mm_AA {model = PATHTOF(ace_TracerYellow2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_yellow
+
+ class Gatling_30mm_HE_Plane_CAS_01_F: BulletBase {model = PATHTOF(ace_TracerRed2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_red.p3d
+ class Cannon_30mm_HE_Plane_CAS_02_F: Gatling_30mm_HE_Plane_CAS_01_F {model = PATHTOF(ace_TracerGreen2.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\tracer_green.p3d
+
+ //Cannon
+ class Sh_120mm_HE: ShellBase {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_white
+ class Sh_120mm_HE_Tracer_Red: Sh_120mm_HE {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_120mm_HE_Tracer_Green: Sh_120mm_HE {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_120mm_HE_Tracer_Yellow: Sh_120mm_HE {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
+ class Sh_120mm_APFSDS: ShellBase {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_white
+ class Sh_120mm_APFSDS_Tracer_Red: Sh_120mm_APFSDS {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_120mm_APFSDS_Tracer_Green: Sh_120mm_APFSDS {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_120mm_APFSDS_Tracer_Yellow: Sh_120mm_APFSDS {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
class Sh_125mm_APFSDS;
- class Sh_125mm_APFSDS_T_Red: Sh_125mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_125mm_APFSDS_T_Green: Sh_125mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_125mm_APFSDS_T_Yellow: Sh_125mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
+ class Sh_125mm_APFSDS_T_Red: Sh_125mm_APFSDS {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_125mm_APFSDS_T_Green: Sh_125mm_APFSDS {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_125mm_APFSDS_T_Yellow: Sh_125mm_APFSDS {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
class Sh_125mm_HE;
- class Sh_125mm_HE_T_Red: Sh_125mm_HE {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_125mm_HE_T_Green: Sh_125mm_HE {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_125mm_HE_T_Yellow: Sh_125mm_HE {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
+ class Sh_125mm_HE_T_Red: Sh_125mm_HE {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_125mm_HE_T_Green: Sh_125mm_HE {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_125mm_HE_T_Yellow: Sh_125mm_HE {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
class Sh_125mm_HEAT;
- class Sh_125mm_HEAT_T_Red: Sh_125mm_HEAT {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_125mm_HEAT_T_Green: Sh_125mm_HEAT {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_125mm_HEAT_T_Yellow: Sh_125mm_HEAT {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
+ class Sh_125mm_HEAT_T_Red: Sh_125mm_HEAT {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_125mm_HEAT_T_Green: Sh_125mm_HEAT {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_125mm_HEAT_T_Yellow: Sh_125mm_HEAT {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
class Sh_105mm_APFSDS;
- class Sh_105mm_APFSDS_T_Red: Sh_105mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_105mm_APFSDS_T_Green: Sh_105mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_105mm_APFSDS_T_Yellow: Sh_105mm_APFSDS {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
+ class Sh_105mm_APFSDS_T_Red: Sh_105mm_APFSDS {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_105mm_APFSDS_T_Green: Sh_105mm_APFSDS {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_105mm_APFSDS_T_Yellow: Sh_105mm_APFSDS {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+
class Sh_105mm_HEAT_MP;
- class Sh_105mm_HEAT_MP_T_Red: Sh_105mm_HEAT_MP {
- model = PATHTOF(ace_shell_tracer_red.p3d);
- };
- class Sh_105mm_HEAT_MP_T_Green: Sh_105mm_HEAT_MP {
- model = PATHTOF(ace_shell_tracer_green.p3d);
- };
- class Sh_105mm_HEAT_MP_T_Yellow: Sh_105mm_HEAT_MP {
- model = PATHTOF(ace_shell_tracer_yellow.p3d);
- };
-};
+ class Sh_105mm_HEAT_MP_T_Red: Sh_105mm_HEAT_MP {model = PATHTOF(ace_shell_tracer_red.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_red
+ class Sh_105mm_HEAT_MP_T_Green: Sh_105mm_HEAT_MP {model = PATHTOF(ace_shell_tracer_green.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_green
+ class Sh_105mm_HEAT_MP_T_Yellow: Sh_105mm_HEAT_MP {model = PATHTOF(ace_shell_tracer_yellow.p3d);}; //Replaces \A3\Weapons_f\Data\bullettracer\shell_tracer_yellow
+};
\ No newline at end of file