diff --git a/.gitea/workflows/create-testing-snapshot.yaml b/.gitea/workflows/create-testing-snapshot.yaml
new file mode 100644
index 0000000..5fb5877
--- /dev/null
+++ b/.gitea/workflows/create-testing-snapshot.yaml
@@ -0,0 +1,71 @@
+name: Generate testing snapshot
+on:
+ push:
+ branches: [develop]
+
+jobs:
+ Clean:
+ name: Create testing release
+ runs-on: windows
+ steps:
+ - name: Diagnostics
+ run: |
+ echo "repository: ${{ gitea.repository }}"
+ echo "ref: ${{ gitea.ref }}"
+ echo "ref_name: ${{ gitea.ref_name }}"
+ echo "sha: ${{ gitea.sha }}"
+ echo "api_url: ${{ gitea.api_url }}"
+ echo "workflow: ${{ gitea.workflow }}"
+
+ - name: Checkout framework
+ uses: actions/checkout@v3
+ with:
+ path: MissionFramework
+
+ - name: Clean framework
+ run: |
+ Remove-Item -Recurse MissionFramework\aaFrameworkUtils
+ Remove-Item -Recurse MissionFramework\framework\x
+ Remove-Item -Recurse MissionFramework\.git*
+
+ - name: Backup artifacts from runner
+ uses: actions/upload-artifact@v3
+ with:
+ name: framework-test-snapshot
+ path: MissionFramework
+
+ - name: Create archive
+ run: Compress-Archive MissionFramework framework-test-snapshot.zip
+
+ - name: Delete old testing-release release
+ run: |
+ $headers = @{
+ "accept" = "application/json"
+ "Authorization" = "token ${{secrets.RELEASE_TOKEN}}"
+ }
+ Invoke-WebRequest -Uri "${{ gitea.api_url }}/repos/${{ gitea.repository }}/releases/tags/testing-release" -Method Delete -Headers $headers
+
+ - name: Delete old testing-release tag
+ run: |
+ $headers = @{
+ "accept" = "application/json"
+ "Authorization" = "token ${{secrets.RELEASE_TOKEN}}"
+ }
+ Invoke-WebRequest -Uri "${{ gitea.api_url }}/repos/${{ gitea.repository }}/tags/testing-release" -Method Delete -Headers $headers
+
+ - name: Create new testing-release tag
+ run: |
+ $headers = @{
+ "accept" = "application/json"
+ "Authorization" = "token ${{secrets.RELEASE_TOKEN}}"
+ }
+ Invoke-WebRequest -Uri "${{ gitea.api_url }}/repos/${{ gitea.repository }}/tags" -Method Post -Headers $headers -ContentType "application/json" -Body "{`"message`": `"testing-release`", `"tag_name`": `"testing-release`", `"target`": `"${{ gitea.sha }}`"}"
+
+ - name: Create new testing-release
+ uses: https://gitea.com/actions/gitea-release-action@v1.1.6
+ with:
+ tag_name: 'testing-release'
+ name: 'testing-release'
+ prerelease: true
+ files: |-
+ framework-test-snapshot.zip
diff --git a/custom_leaflets.hpp b/custom_leaflets.hpp
new file mode 100644
index 0000000..8caadd4
--- /dev/null
+++ b/custom_leaflets.hpp
@@ -0,0 +1,39 @@
+// This contains custom definitions for leaflets. It is not required to set this up, but you're welcome to if you want to use them.
+
+// To use this, configure one or more of the below. Then use the pylon editor of a drone in EDEN to add the appropriate magazine type (like 1Rnd_Leaflets_Custom_01_F) to the drone. Then, when the drone is flying, do `drone1 fire "1Rnd_Leaflets_Custom_01_F";` to drop the leaflets. The leaflet will then be shown in the world, and can be picked up by players to read the text and see the image.
+
+class Custom_01 // configuration for 1Rnd_Leaflets_Custom_01_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_01.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
+
+class Custom_02 // configuration for 1Rnd_Leaflets_Custom_02_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_02.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
+
+class Custom_03 // configuration for 1Rnd_Leaflets_Custom_03_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_03.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
+
+class Custom_04 // configuration for 1Rnd_Leaflets_Custom_04_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_04.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
+
+class Custom_05 // configuration for 1Rnd_Leaflets_Custom_05_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_05.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
+
+class Custom_06 // configuration for 1Rnd_Leaflets_Custom_06_F
+{
+ text = "Leaflet text"; // text shown when previewing the leaflet full-screen. Ideally should be localized, so even player who cannot read the image can get the information
+ texture = "images\leaflets\leaflet_custom_06.paa"; // leaflet texture shown when previewing the leaflet full-screen
+};
\ No newline at end of file
diff --git a/custom_scripts.hpp b/custom_scripts.hpp
new file mode 100644
index 0000000..8b9b928
--- /dev/null
+++ b/custom_scripts.hpp
@@ -0,0 +1,11 @@
+// This file's contents will be included in the mission's CfgFunctions section, and serves to give you a place to define custom functions from files you've placed in /scripts.
+
+class milsim_scripts {
+ class functions {
+ file = "scripts";
+ // Add your custom functions here, like so:
+ // class init {postInit = 1;}; // refers to scripts/fn_init.sqf. postInit=1 means it will be run on each machine when they're done loading the mission.
+ // class customFunction1 {}; // refers to the file scripts/fn_customFunction1.sqf, and is called as milsim_scripts_fnc_customFunction1
+ // class customFunction2 {}; // refers to the file scripts/fn_customFunction2.sqf, and is called as milsim_scripts_fnc_customFunction2
+ };
+};
\ No newline at end of file
diff --git a/defines/SupplyCrates.hpp b/defines/SupplyCrates.hpp
index 51245fd..9bf50cd 100644
--- a/defines/SupplyCrates.hpp
+++ b/defines/SupplyCrates.hpp
@@ -21,18 +21,14 @@ class SupplyCrates {
{"rhsusf_200Rnd_556x45_mixed_soft_pouch_coyote",25},
{"rhsusf_20Rnd_762x51_m993_Mag",25},
{"SmokeShell",12},
- {"rhs_mag_m67",12},
+ {"rhs_mag_m67",24},
{"1Rnd_Smoke_Grenade_shell",24},
{"1Rnd_SmokeRed_Grenade_shell",24},
{"1Rnd_SmokeGreen_Grenade_shell",24},
{"1Rnd_SmokeYellow_Grenade_shell",12},
{"Tier1_30Rnd_556x45_M856A1_EMag",25},
- {"Tier1_30Rnd_556x45_Mk318Mod0_EMag",75},
- {"ACE_30Rnd_65_Creedmor_mag",25},
+ {"ACE_30Rnd_556x45_Stanag_M995_AP_mag",75},
{"SMA_30Rnd_762x35_BLK_EPR",25},
- {"Tier1_30Rnd_762x35_300BLK_SMK_PMAG",25},
- {"SMA_30Rnd_68x43_SPC_FMJ",25},
- {"SMA_30Rnd_68x43_SPC_FMJ_Tracer",25},
{"SMA_20Rnd_762x51mm_M80A1_EPR",25},
{"SMA_20Rnd_762x51mm_M80A1_EPR_Tracer",25},
{"SMA_20Rnd_762x51mm_Mk316_Mod_0_Special_Long_Range",25},
@@ -42,8 +38,6 @@ class SupplyCrates {
{"ACE_20Rnd_762x51_M993_AP_Mag",25},
{"rhsusf_20Rnd_762x51_SR25_m993_Mag",25},
{"Tier1_20Rnd_762x51_M993_SR25_Mag",25},
- {"Tier1_20Rnd_65x48_Creedmoor_SR25_Mag",25},
- {"rhssaf_30rnd_556x45_EPR_G36", 25},
{"DemoCharge_Remote_Mag",16}
};
items[] = {};
@@ -56,13 +50,15 @@ class SupplyCrates {
icon = "\A3\ui_f\data\map\vehicleicons\iconCrateWpns_ca.paa";
backpacks[] = {};
- weapons[] = {};
+ weapons[] = {
+ {"launch_MRAWS_green_F",2}
+ };
magazines[] = {
{"MRAWS_HEAT_F",35},
{"MRAWS_HE_F",15},
{"Tier1_250Rnd_762x51_Belt_M993_AP",50},
{"Tier1_30Rnd_556x45_M856A1_EMag",25},
- {"Tier1_30Rnd_556x45_Mk318Mod0_EMag",50},
+ {"ACE_30Rnd_556x45_Stanag_M995_AP_mag",50},
{"Titan_AA",10},
{"Titan_AT",10},
{"200Rnd_65x39_cased_Box_Tracer_Red",50}
@@ -168,12 +164,15 @@ class SupplyCrates {
icon = "\A3\ui_f\data\igui\cfg\simpleTasks\types\scout_ca.paa";
backpacks[] = {};
- weapons[] = {};
+ weapons[] = {
+ {"rhs_weap_M136",2},
+ {"twc_2inch_bag",3}
+ };
magazines[] = {
{"twc_2inch_he_1rnd",70},
{"twc_2inch_smoke_1rnd",15},
{"twc_2inch_illum_1rnd",15},
- {"Tier1_30Rnd_556x45_Mk318Mod0_EMag",20}
+ {"ACE_30Rnd_556x45_Stanag_M995_AP_mag",20}
};
items[] = {};
};
diff --git a/description.ext b/description.ext
index b23393f..1efe1da 100644
--- a/description.ext
+++ b/description.ext
@@ -89,15 +89,16 @@ minPlayerDistance = 500;
//-------------------------------------------BASE SETTINGS---------------------------------------------------------------//
-class Params
-{
+class Params {};
+
+class CfgFunctions {
+ #include "framework\CfgFunctions.hpp"
+ #include "custom_scripts.hpp"
};
-
-// CfgFunctions
-#include "framework\CfgFunctions.hpp"
-
-
+class CfgLeaflets {
+ #include "custom_leaflets.hpp"
+};
class CfgDebriefingSections {
class acex_killTracker {
diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp
index bfe7d28..744bea3 100644
--- a/framework/CfgFunctions.hpp
+++ b/framework/CfgFunctions.hpp
@@ -1,180 +1,188 @@
#include "script_mod.hpp"
-class CfgFunctions {
-
- class DOUBLES(PREFIX,init) {
- class functions {
- file = "framework\init\functions";
- class initServer { postInit = 1;};
- class initClient { postInit = 1;};
- class setDefaults { postInit = 1; };
- class addAARChatHandler { postInit = 1; };
- class addRespawnChatHandler { postInit = 1; };
- };
+class DOUBLES(PREFIX,init) {
+ class functions {
+ file = "framework\init\functions";
+ class initServer { postInit = 1;};
+ class initClient { postInit = 1;};
+ class setDefaults {};
+ class addAARChatHandler {};
+ class addRespawnChatHandler {};
+ class checkMissionSettings {};
};
-
- class PREFIX {
- class ambience {
- file = "framework\ambience";
- class flakInitVehicle {};
- class flakEH {};
- };
+};
+
+class PREFIX {
+ class ambience {
+ file = "framework\ambience";
+ class flakInitVehicle {};
+ class flakEH {};
};
+};
- class DOUBLES(PREFIX,client) {
- class functions {
- file = "framework\client\functions";
- class bindEmptyGroupGarbageCleanup { postInit = 1; };
- class bindEventHandlers { postInit = 1; };
- class bindVehicleActions { postInit = 1; };
- class addZenModules {postInit = 1;};
- };
+class DOUBLES(PREFIX,client) {
+ class functions {
+ file = "framework\client\functions";
+ class initClient {};
+ class addDraw3DPFH {};
+ class addGetNearMenPFH {};
+ class addMicroDAGRWaypoints {};
+ class addZenModules {};
+ class bindEventHandlers {};
+ class bindVehicleActions {};
+ class clearPFHCode {};
+ class logRespawnButtonUse {};
+ class registerPFHCode {};
+ class staticLineProtection {};
};
+};
- class DOUBLES(PREFIX,common) {
- class functions {
- file = "framework\common\functions";
- class addCBASettings { preInit = 1; };
- class logMissionInfo {};
- class addPlayerInfoToArray {};
- class createOrUpdateDiaryRecord {};
- class getApprovedAssetsCfg {};
- class getBattalionCfg {};
- class getNameOfBase {};
- class getNearestBase {};
- class log {};
- class checkPlayerInventory {};
- class logSettingChanged {};
- class padString {};
- class recurseSubclasses {};
- };
+class DOUBLES(PREFIX,common) {
+ class functions {
+ file = "framework\common\functions";
+ class addCBASettings { preInit = 1; };
+ class addPlayerInfoToArray {};
+ class checkPlayerInventory {};
+ class createOrUpdateDiaryRecord {};
+ class draw3DIconStatus {};
+ class getApprovedAssetsCfg {};
+ class getBattalionCfg {};
+ class getNameOfBase {};
+ class getNearestBase {};
+ class log {};
+ class logMissionInfo {};
+ class logSettingChanged {};
+ class padString {};
+ class recurseSubclasses {};
};
+};
- class DOUBLES(PREFIX,fbcb2_assets) {
- class functions {
- file = "framework\fbcb2_assets\functions";
- class addCBASettings {preInit=1;};
- class initServer {};
- class initClient {};
- class getCallsignFromClassname {};
- class getCurrentAssetsByBase {};
- class getInventory {};
- class getMagsForWeapon {};
- class getStartingAndCurrentAssets {};
- class getStartingAssetsByBase {};
- class getVehicleData {};
- class getWeaponry {};
- class hintAllApprovedAssets {};
- class isAssetInRangeOfBase {};
- class removeAssetDiaryRecords {};
- class removeMarkersOnMap {};
- class showMarkersOnMap {};
- class updateAssetDiary {};
- class updateAssetsByBase {};
- };
+class DOUBLES(PREFIX,fbcb2_assets) {
+ class functions {
+ file = "framework\fbcb2_assets\functions";
+ class addCBASettings {preInit=1;};
+ class initServer {};
+ class initClient {};
+ class getCallsignFromClassname {};
+ class getCurrentAssetsByBase {};
+ class getInventory {};
+ class getMagsForWeapon {};
+ class getStartingAndCurrentAssets {};
+ class getStartingAssetsByBase {};
+ class getVehicleData {};
+ class getWeaponry {};
+ class hintAllApprovedAssets {};
+ class isAssetInRangeOfBase {};
+ class removeAssetDiaryRecords {};
+ class removeMarkersOnMap {};
+ class showMarkersOnMap {};
+ class updateAssetDiary {};
+ class updateAssetsByBase {};
};
+};
- class DOUBLES(PREFIX,fbcb2_main) {
- class functions {
- file = "framework\fbcb2_main\functions";
- class initClient {};
- class addEnvironmentRecord {};
- class addFrequenciesRecord {};
- class addSignalColorsRecord {};
- };
- class util {
- file = "framework\fbcb2_main\util";
- class formatRadioElementForDiary {};
- class generateElementFrequencyRecordText {};
- };
+class DOUBLES(PREFIX,fbcb2_main) {
+ class functions {
+ file = "framework\fbcb2_main\functions";
+ class initClient {};
+ class addEnvironmentRecord {};
+ class addFrequenciesRecord {};
+ class addSignalColorsRecord {};
};
-
- class DOUBLES(PREFIX,mapcopy) {
- class functions {
- file = "framework\mapcopy\functions";
- class addCBASettings {preInit=1;};
- class initClient {};
- class getMapMarkers {};
- class loadMapMarkers {};
- class mapMarkerToString {};
- class stringToMapMarker {};
- };
+ class util {
+ file = "framework\fbcb2_main\util";
+ class formatRadioElementForDiary {};
+ class generateElementFrequencyRecordText {};
};
+};
- class DOUBLES(PREFIX,performance) {
- class functions {
- file = "framework\performance\functions";
- class addCBASettings {preInit=1;};
- class addDNI_PlayerFPS { postInit = 1; };
-
- // PFHs managed in addCBASettings onChange code
- class addClientStatsPFH {};
- class calculateClientStats {};
- class addServerStatsPFH {};
- class calculateServerStats {};
- };
+class DOUBLES(PREFIX,mapcopy) {
+ class functions {
+ file = "framework\mapcopy\functions";
+ class addCBASettings {preInit=1;};
+ class initClient {};
+ class getMapMarkers {};
+ class loadMapMarkers {};
+ class mapMarkerToString {};
+ class stringToMapMarker {};
};
+};
- class DOUBLES(PREFIX,reinsert) {
- class functions {
- file = "framework\reinsert\functions";
- class addCBASettings {preInit=1;};
- };
- class server {
- file = "framework\reinsert\server";
- class initServer {};
- class addToQueue {};
- class globalShowQueue {};
- class removeFromQueue {};
- class returnReinsertQueueNotification {};
- class validateQueue {};
- };
- class client {
- file = "framework\reinsert\client";
- class initClient {};
- class addAceSelfActions {};
- class addCheckQueueSelfAction {};
- class requestShowQueue {};
- };
+class DOUBLES(PREFIX,performance) {
+ class functions {
+ file = "framework\performance\functions";
+ class addCBASettings {preInit=1;};
+ class addDNI_PlayerFPS {postInit = 1;};
+
+ // PFHs managed in addCBASettings onChange code
+ class addClientStatsPFH {};
+ class calculateClientStats {};
+ class addServerStatsPFH {};
+ class calculateServerStats {};
+ class addEmptyGroupCleanupPFH {};
};
+};
- class DOUBLES(PREFIX,resupply) {
- class functions {
- file = "framework\resupply\functions";
- class addCBASettings {preInit=1;};
- class initClient {};
- class createBox {};
- class getSupplyCratesCfg {};
- class addArsenalObjectSpawnBoxActions {};
- };
+class DOUBLES(PREFIX,reinsert) {
+ class functions {
+ file = "framework\reinsert\functions";
+ class addCBASettings {preInit=1;};
};
-
- class DOUBLES(PREFIX,triageIcons) {
- class functions {
- file = "framework\triageIcons\functions";
- class addCBASettings {preInit=1;};
- class initClient {};
- class addDrawIconsPFH {};
- class addGetEntitiesPFH {};
- class updateColors {};
- };
+ class server {
+ file = "framework\reinsert\server";
+ class initServer {};
+ class addToQueue {};
+ class globalShowQueue {};
+ class removeFromQueue {};
+ class returnReinsertQueueNotification {};
+ class validateQueue {};
};
-
- class DOUBLES(PREFIX,vehicleFlags) {
- class functions {
- file = "framework\vehicleFlags\functions";
- class initClient {};
- class getActionsFlagCategories {};
- class getVehicleFlagsCfg {};
- class isClassExcluded {};
- };
+ class client {
+ file = "framework\reinsert\client";
+ class initClient {};
+ class addAceSelfActions {};
+ class addCheckQueueSelfAction {};
+ class requestShowQueue {};
};
+};
- class DOUBLES(PREFIX,zeus) {
- class functions {
- file = "framework\zeus\functions";
- class initClient {};
- class addZenModules {};
- };
+class DOUBLES(PREFIX,resupply) {
+ class functions {
+ file = "framework\resupply\functions";
+ class addCBASettings {preInit=1;};
+ class initClient {};
+ class createBox {};
+ class getSupplyCratesCfg {};
+ class addArsenalObjectSpawnBoxActions {};
+ };
+};
+
+class DOUBLES(PREFIX,triageIcons) {
+ class functions {
+ file = "framework\triageIcons\functions";
+ class addCBASettings {preInit=1;};
+ class initClient {};
+ class draw3D {};
+ class updateColors {};
+ };
+};
+
+class DOUBLES(PREFIX,vehicleFlags) {
+ class functions {
+ file = "framework\vehicleFlags\functions";
+ class initClient {};
+ class addFlagActions {};
+ class draw3D {};
+ class getActionsFlagCategories {};
+ class getVehicleFlagsCfg {};
+ class isClassExcluded {};
+ };
+};
+
+class DOUBLES(PREFIX,zeus) {
+ class functions {
+ file = "framework\zeus\functions";
+ class initClient {};
+ class addZenModules {};
};
};
\ No newline at end of file
diff --git a/framework/client/functions/fn_addDraw3DPFH.sqf b/framework/client/functions/fn_addDraw3DPFH.sqf
new file mode 100644
index 0000000..8b0626a
--- /dev/null
+++ b/framework/client/functions/fn_addDraw3DPFH.sqf
@@ -0,0 +1,10 @@
+#include "..\script_component.hpp"
+
+
+if (!isNil QGVAR(draw3DPFH)) then {
+ [GVAR(draw3DPFH)] call CBA_fnc_removePerFrameHandler;
+};
+// add pfh that processes queued code
+GVAR(draw3DPFH) = [{
+ {call _x; true;} count (localNamespace getVariable [QGVAR(pfhCode), []]);
+}, 0] call CBA_fnc_addPerFrameHandler;
diff --git a/framework/client/functions/fn_addGetNearMenPFH.sqf b/framework/client/functions/fn_addGetNearMenPFH.sqf
new file mode 100644
index 0000000..dbad6c5
--- /dev/null
+++ b/framework/client/functions/fn_addGetNearMenPFH.sqf
@@ -0,0 +1,17 @@
+#include "..\script_component.hpp"
+
+// subroutine to gather nearest 50 units every 5 seconds and store in GVAR(nearMen)
+// cleanup
+if (!isNil QGVAR(getNearMenPFH)) then {
+ [GVAR(getNearMenPFH)] call CBA_fnc_removePerFrameHandler;
+};
+// add pfh
+GVAR(getNearMenPFH) = [{
+ localNamespace setVariable [
+ QGVAR(nearMen),
+ (nearestObjects [player,["Man"],50,false]) select {
+ !isNull _x &&
+ player isNotEqualTo _x
+ }
+ ];
+}, 1] call CBA_fnc_addPerFrameHandler;
diff --git a/framework/client/functions/fn_addMicroDAGRWaypoints.sqf b/framework/client/functions/fn_addMicroDAGRWaypoints.sqf
new file mode 100644
index 0000000..832bc54
--- /dev/null
+++ b/framework/client/functions/fn_addMicroDAGRWaypoints.sqf
@@ -0,0 +1,76 @@
+#include "..\script_component.hpp"
+
+// adds default base locations to players' microDAGR as waypoints
+
+if (!hasInterface) exitWith {};
+
+[{!isNull player}, {
+
+ // add base locations (respawn modules)
+ {
+ private _wpName = [_x] call EFUNC(common,getNameOfBase);
+ private _posASL = getPosASL _x;
+ [_wpName, _posASL] call ace_microdagr_fnc_deviceAddWaypoint;
+ } forEach GVARMAIN(baseObjects);
+
+ // add custom waypoints from mission_settings.hpp
+ private _customWaypoints = [missionConfigFile >> "custom_microdagr_waypoints", "ARRAY", []] call CBA_fnc_getConfigEntry;
+ {
+ _x params [
+ ["_wpName", ""],
+ ["_pos", [0, 0, 0], [[], ""]],
+ ["_object", "", [""]]
+ ];
+ private _realPos = nil;
+ // if pos was provided, process
+ if (count _pos >= 2) then {
+ switch (typeName _pos) do {
+ case "ARRAY": {
+ // pos is provided as an array
+ _realPos = _pos select [0, 2];
+ _realPos set [2, getTerrainHeightASL _realPos];
+ };
+ case "STRING": {
+ // pos is provided as a string
+ _realPos = [_pos, true] call ACE_common_fnc_getMapPosFromGrid;
+ _realPos set [2, getTerrainHeightASL _realPos];
+ };
+ default {
+ [
+ LEVEL_WARNING,
+ QUOTE(COMPONENT),
+ format["Invalid position for custom microDAGR waypoint: %1", _wpName],
+ [["name", _wpName], ["pos", _pos], ["object", _object]]] call EFUNC(common,log);
+ continue;
+ };
+ };
+ };
+ // if object was provided, process and override any pos
+ if (count _object > 0) then {
+ // object is provided as a string variable name
+ private _realObject = missionNamespace getVariable _object;
+ if (isNull _realObject) then {
+ [
+ LEVEL_WARNING,
+ QUOTE(COMPONENT),
+ format["Invalid object for custom microDAGR waypoint: %1", _wpName],
+ [["name", _wpName], ["pos", _pos], ["object", _object]]] call EFUNC(common,log);
+ continue;
+ };
+ _realPos = getPosASL (missionNamespace getVariable _object);
+ };
+ if (isNil "_realPos") then {
+ [
+ LEVEL_WARNING,
+ QUOTE(COMPONENT),
+ format["Invalid waypoint position for custom microDAGR waypoint: %1", _wpName],
+ [["name", _wpName], ["pos", _pos], ["object", _object]]] call EFUNC(common,log);
+ continue;
+ };
+
+ [_wpName, _realPos] call ace_microdagr_fnc_deviceAddWaypoint;
+ true;
+ } count _customWaypoints;
+}] call CBA_fnc_waitUntilAndExecute;
+
+nil;
\ No newline at end of file
diff --git a/framework/client/functions/fn_bindEventHandlers.sqf b/framework/client/functions/fn_bindEventHandlers.sqf
index 802c2c5..53b2162 100644
--- a/framework/client/functions/fn_bindEventHandlers.sqf
+++ b/framework/client/functions/fn_bindEventHandlers.sqf
@@ -2,23 +2,6 @@
if ( !hasInterface ) exitWith {};
-player addEventHandler["Respawn",
- {
- params ["_unit", "_corpse"];
- private _killer = _corpse getVariable ["ace_medical_causeOfDeath", "#scripted"];
- if (_killer == "respawn_button") then {
- [
- LEVEL_INFO,
- QUOTE(COMPONENT),
- "RESPAWNED WHILE UNCONSCIOUS",
- [_unit] call EFUNC(common,addPlayerInfoToArray)
- ] remoteExec [QEFUNC(common,log), 2];
- // format["%1 was unconscious then clicked the respawn button", name _unit] remoteExec["systemChat", 0];
- };
- }
-];
-
-
[
{
params ["_unit", "_object", "_cost"];
diff --git a/framework/client/functions/fn_clearPFHCode.sqf b/framework/client/functions/fn_clearPFHCode.sqf
new file mode 100644
index 0000000..08129a5
--- /dev/null
+++ b/framework/client/functions/fn_clearPFHCode.sqf
@@ -0,0 +1,5 @@
+#include "..\script_component.hpp"
+
+localNamespace setVariable [QGVAR(pfhCode), []];
+
+count [];
\ No newline at end of file
diff --git a/framework/client/functions/fn_initClient.sqf b/framework/client/functions/fn_initClient.sqf
new file mode 100644
index 0000000..b60a487
--- /dev/null
+++ b/framework/client/functions/fn_initClient.sqf
@@ -0,0 +1,32 @@
+#include "..\script_component.hpp"
+
+
+if (!hasInterface) exitWith {};
+
+call FUNC(addMicroDAGRWaypoints);
+call FUNC(addZenModules);
+call FUNC(bindEventHandlers);
+call FUNC(bindVehicleActions);
+
+// add core getNearMenPFH handler
+localNamespace setVariable [QGVAR(nearMen), []];
+call FUNC(addGetNearMenPFH);
+// add core draw3dPFH handler
+localNamespace setVariable [QGVAR(pfhCode), []];
+call FUNC(addDraw3DPFH);
+
+// add listener that tracks using the respawn button while unconscious
+call FUNC(logRespawnButtonUse);
+// add conditional eject-from-vehicle handler to apply temp invincibility when static line jumping
+call FUNC(staticLineProtection);
+
+[
+ LEVEL_DEBUG,
+ QUOTE(COMPONENT),
+ "initClient complete",
+ []
+] call EFUNC(common,log);
+
+localNamespace setVariable [QGVAR(complete), true];
+
+nil;
\ No newline at end of file
diff --git a/framework/client/functions/fn_logRespawnButtonUse.sqf b/framework/client/functions/fn_logRespawnButtonUse.sqf
new file mode 100644
index 0000000..ec085e6
--- /dev/null
+++ b/framework/client/functions/fn_logRespawnButtonUse.sqf
@@ -0,0 +1,56 @@
+#include "..\script_component.hpp"
+
+if ( !hasInterface ) exitWith {};
+
+["ace_killed", {
+ params ["_unit", "_causeOfDeath", "_killer", "_instigator"];
+
+ if (not (local _unit)) exitWith {};
+
+ private _causeOfDeath = _unit getVariable ["ace_medical_causeOfDeath", "#scripted"];
+
+ if (_causeOfDeath != "respawn_button") exitWith {};
+ private _timeWentUnconscious = _unit getVariable [QGVARMAIN(lastTimeKnockedOut), -1];
+ private _durationSpentUnconscious = -1;
+ if (_timeWentUnconscious != -1) then {
+ _durationSpentUnconscious = diag_tickTime - _timeWentUnconscious;
+ };
+
+ [
+ LEVEL_INFO,
+ QUOTE(COMPONENT),
+ "RESPAWNED WHILE UNCONSCIOUS",
+ [_unit, [
+ ["durationSpentUnconscious", _durationSpentUnconscious]
+ ]] call EFUNC(common,addPlayerInfoToArray)
+ ] remoteExec [QEFUNC(common,log), 2];
+ // format["%1 was unconscious then clicked the respawn button", name _unit] remoteExec["systemChat", 0];
+}] call CBA_fnc_addEventHandler;
+
+
+["ace_medical_knockOut", { // local event for module & epi event
+ // systemChat format["ace_medical_knockOut: %1", _this];
+ private _unit = _this;
+ if (not (local _unit)) exitWith {};
+ _this setVariable [QGVARMAIN(lastTimeKnockedOut), diag_tickTime];
+}] call CBA_fnc_addEventHandler;
+
+["ace_medical_WakeUp", { // local event for module & epi event
+ // systemChat format["ace_medical_WakeUp: %1", _this];
+ private _unit = _this;
+ if (not (local _unit)) exitWith {};
+ _this setVariable [QGVARMAIN(lastTimeKnockedOut), nil];
+}] call CBA_fnc_addEventHandler;
+
+["ace_unconscious", { // used when applying damage
+ params ["_unit", "_isUnconscious"];
+ if (not (local _unit)) exitWith {};
+
+ if (_isUnconscious && isNil {_unit getVariable QGVARMAIN(lastTimeKnockedOut)}) then {
+ // systemChat format["%1 is unconscious", _unit];
+ _unit setVariable [QGVARMAIN(lastTimeKnockedOut), diag_tickTime];
+ } else {
+ // systemChat format["%1 is conscious", _unit];
+ _unit setVariable [QGVARMAIN(lastTimeKnockedOut), nil];
+ };
+}] call CBA_fnc_addEventHandler;
\ No newline at end of file
diff --git a/framework/client/functions/fn_registerPFHCode.sqf b/framework/client/functions/fn_registerPFHCode.sqf
new file mode 100644
index 0000000..990dfec
--- /dev/null
+++ b/framework/client/functions/fn_registerPFHCode.sqf
@@ -0,0 +1,9 @@
+#include "..\script_component.hpp"
+
+params [["_code", {}, [{}]]];
+
+private _pfhCode = localNamespace getVariable [QGVAR(pfhCode), []];
+_pfhCode pushBack _code;
+localNamespace setVariable [QGVAR(pfhCode), _pfhCode];
+
+count _pfhCode;
\ No newline at end of file
diff --git a/framework/client/functions/fn_staticLineProtection.sqf b/framework/client/functions/fn_staticLineProtection.sqf
new file mode 100644
index 0000000..7d562f3
--- /dev/null
+++ b/framework/client/functions/fn_staticLineProtection.sqf
@@ -0,0 +1,40 @@
+#include "..\script_component.hpp"
+
+if ( !hasInterface ) exitWith {};
+
+// Add GetOutMan event handler to grant temporary invincibility to players ejecting from vehicles
+// Only for players who have "hooked up" using VS static line
+// and are ejecting from a plane or helicopter above 100m
+player addEventHandler ["GetOutMan", {
+ params ["_unit", "_role", "_vehicle", "_turret", "_isEject"];
+ if (!isEject) exitWith {};
+ if (isNil {_unit getVariable "VS_Jump"}) exitWith {};
+ if (
+ not (_vehicle isKindOf "Plane" || _vehicle isKindOf "Helicopter") ||
+ ((getPosATL _vehicle)#2) < 100
+ ) exitWith {};
+
+ // disable damage for the unit to avoid collision damage
+ _unit allowDamage false;
+ // tested - vehicle _unit is the _unit, as this EH runs when they have left the vehicle
+
+
+ [
+ {!isNull (objectParent _this)}, // condition - wait until player re-enters vehicle (chute)
+ {
+ // if they enter a chute within 5 seconds, disable chute damage
+ (vehicle _this) allowDamage false;
+ // then wait X seconds and re-enable damage for both
+ [{
+ _this allowDamage true;
+ (vehicle _this) allowDamage true;
+ }, _this, 5] call CBA_fnc_waitAndExecute;
+ },
+ _unit, // args
+ 2, // timeout
+ { // run on timeout, if for some reason they don't enter a chute
+ // re-enable damage for unit
+ _this allowDamage true;
+ }
+ ] call CBA_fnc_waitUntilAndExecute;
+}];
\ No newline at end of file
diff --git a/framework/common/functions/fn_draw3DIconStatus.sqf b/framework/common/functions/fn_draw3DIconStatus.sqf
new file mode 100644
index 0000000..a697632
--- /dev/null
+++ b/framework/common/functions/fn_draw3DIconStatus.sqf
@@ -0,0 +1,54 @@
+#include "..\script_component.hpp"
+
+if (!hasInterface) exitWith {};
+
+params [
+ ["_drawTargets", [], [[]]],
+ ["_icon", "", [""]],
+ ["_text", "", [""]],
+ ["_color", [], [[]]]
+];
+
+if (count _drawTargets isEqualTo 0) exitWith {};
+
+_cameraPos = positionCameraToWorld [0,0,0];
+_cameraPosASL = AGLToASL _cameraPos;
+
+{
+ _target = _x;
+ _visible = [objNull, "VIEW"] checkVisibility [_cameraPosASL, eyePos _target];
+
+ if ( _visible isEqualTo 0 ) exitWith {};
+
+ _objectPos = (_target modelToWorldVisual (_target selectionPosition "pilot"));
+ _distance = (visiblePosition _target) vectorDiff _cameraPos;
+
+ _scale = 0;
+ _heightOffset = 0;
+ _heightScaling = 0.012;
+
+ if ( _icon isNotEqualTo "") then {
+ _heightOffset = 0.065;
+ _scale = 1;
+ _heightScaling = 0.075;
+ };
+
+ _drawPos = _objectPos vectorAdd [0, 0, (0.18 + _heightOffset) + (vectorMagnitude _distance * _heightScaling)];
+
+ drawIcon3D [
+ _icon,
+ _color,
+ _drawPos,
+ _scale,
+ _scale,
+ 0,
+ _text,
+ 2,
+ 0.025
+ ];
+
+ true;
+} count _drawTargets;
+
+nil
+
diff --git a/framework/common/functions/fn_log.sqf b/framework/common/functions/fn_log.sqf
index 716c0df..11487e6 100644
--- a/framework/common/functions/fn_log.sqf
+++ b/framework/common/functions/fn_log.sqf
@@ -24,10 +24,10 @@ if (_logLevel < DEBUG_MODE) exitWith {};
private _hash = createHashMapFromArray _data;
// Replace square brackets with round brackets to avoid parsing issues.
-_message regexReplace ['(\[)', "("];
-_message regexReplace ['(\])', ")"];
+[_message, "]", ")"] call CBA_fnc_replace;
+[_message, "[", "("] call CBA_fnc_replace;
private _json = [_hash] call CBA_fnc_encodeJSON;
-_log = format ["[%1] [%2] [%3] [%4] :: %5", QUOTE(PREFIX), _component, _fnc_scriptNameParent, _message, _json];
+private _log = format ["[%1] [%2] [%3] [%4] :: %5", QUOTE(PREFIX), _component, _fnc_scriptNameParent, _message, _json];
diag_log text _log;
\ No newline at end of file
diff --git a/framework/init/functions/fn_addAARChatHandler.sqf b/framework/init/functions/fn_addAARChatHandler.sqf
index 10f3979..88d5703 100644
--- a/framework/init/functions/fn_addAARChatHandler.sqf
+++ b/framework/init/functions/fn_addAARChatHandler.sqf
@@ -1,5 +1,7 @@
#include "..\script_component.hpp"
+if (!hasInterface) exitWith {};
+
[
"saveaar",
{
diff --git a/framework/init/functions/fn_addRespawnChatHandler.sqf b/framework/init/functions/fn_addRespawnChatHandler.sqf
index 6e4c22f..cfb06d3 100644
--- a/framework/init/functions/fn_addRespawnChatHandler.sqf
+++ b/framework/init/functions/fn_addRespawnChatHandler.sqf
@@ -1,17 +1,27 @@
#include "..\script_component.hpp"
+if (!hasInterface) exitWith {};
+
[
"respawn",
{
_clientID = _thisArgs select 0;
player setDamage 1;
+ private _timeWentUnconscious = player getVariable [QGVARMAIN(lastTimeKnockedOut), -1];
+ private _durationSpentUnconscious = -1;
+ if (_timeWentUnconscious > - 1) then {
+ _durationSpentUnconscious = diag_tickTime - _timeWentUnconscious;
+ };
+
// log to server RPT
[
LEVEL_INFO,
QUOTE(COMPONENT),
"CHAT COMMAND RESPAWN",
- [player] call EFUNC(common,addPlayerInfoToArray)
+ [player, [
+ ["durationSpentUnconscious", _durationSpentUnconscious]
+ ]] call EFUNC(common,addPlayerInfoToArray)
] remoteExec [QEFUNC(common,log), 2];
// systemChat to all remote machines
diff --git a/framework/init/functions/fn_checkMissionSettings.sqf b/framework/init/functions/fn_checkMissionSettings.sqf
new file mode 100644
index 0000000..fa017d5
--- /dev/null
+++ b/framework/init/functions/fn_checkMissionSettings.sqf
@@ -0,0 +1,41 @@
+#include "..\script_component.hpp"
+
+if (!hasInterface || !is3DENPreview) exitWith {};
+
+private _warningText = [];
+
+if (getText(missionConfigFile >> "author") in ["MISSION AUTHOR", ""]) then {
+ _warningText pushBack "mission_settings\author is blank or default!";
+};
+if (getText(missionConfigFile >> "onLoadName") in ["THIS APPEARS ON TOP OF THE LOADING SCREEN IMAGE", ""]) then {
+ _warningText pushBack "mission_settings\onLoadName is blank or default!";
+};
+
+if (getText(missionConfigFile >> "briefingName") in ["THIS IS THE NAME ON THE #MISSIONS LIST", ""]) then {
+ _warningText pushBack "mission_settings\briefingName is blank or default!";
+};
+if (getText(missionConfigFile >> "overviewText") in ["THIS IS WHERE YOU DESCRIBE THE MISSION IN THE #MISSION LIST", ""]) then {
+ _warningText pushBack "mission_settings\overviewText is blank or default!";
+};
+
+if (getText(missionConfigFile >> "missionSeries") in ["MY SERIES NAME", ""]) then {
+ _warningText pushBack "mission_settings\missionSeries is blank or default!";
+};
+
+if (count GVARMAIN(baseObjects) isEqualTo 0) then {
+ _warningText pushBack "No respawn points placed!";
+};
+
+if (count _warningText > 0) then {
+ [{
+ if (isNull (call BIS_fnc_displayMission)) exitWith {};
+
+ (_this#0) spawn {
+ [_this joinString "
", "Issues found!", true, false] call BIS_fnc_guiMessage;
+ };
+ [_this#1] call CBA_fnc_removePerFrameHandler;
+
+ }, 1, _warningText] call CBA_fnc_addPerFrameHandler;
+};
+
+nil;
\ No newline at end of file
diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf
index 6e82106..8f09921 100644
--- a/framework/init/functions/fn_initClient.sqf
+++ b/framework/init/functions/fn_initClient.sqf
@@ -1,19 +1,17 @@
#include "..\script_component.hpp"
-if ( !hasInterface ) exitWith {};
-
-["milsim_logText", {
- params [["_strArray", [""], [[]]]];
- {
- diag_log text _x;
- } forEach _strArray;
-}] call CBA_fnc_addEventHandler;
+if (!hasInterface) exitWith {};
// make sure the server has finished init
waitUntil {!isNil QGVARMAIN(complete)};
["InitializePlayer", [player, true]] call BIS_fnc_dynamicGroups;
+// run primary init functions
+call FUNC(addAARChatHandler);
+call FUNC(addRespawnChatHandler);
+call FUNC(setDefaults);
+
// Initialize a holder for managing local diary records
// store records in format:
// [subject, [
@@ -23,6 +21,7 @@ EGVAR(common,diaryRecords) = createHashMap;
// initialize other modules
+call EFUNC(client,initClient);
call EFUNC(mapcopy,initClient);
call EFUNC(reinsert,initClient);
call EFUNC(resupply,initClient);
@@ -33,6 +32,8 @@ call EFUNC(fbcb2_main,initClient);
call EFUNC(fbcb2_assets,initClient);
+call FUNC(checkMissionSettings);
+
[
LEVEL_DEBUG,
QUOTE(COMPONENT),
diff --git a/framework/init/functions/fn_initServer.sqf b/framework/init/functions/fn_initServer.sqf
index 84e2666..c40180e 100644
--- a/framework/init/functions/fn_initServer.sqf
+++ b/framework/init/functions/fn_initServer.sqf
@@ -9,16 +9,6 @@ publicVariable QGVARMAIN(baseObjects);
// Initializes the Dynamic Groups framework and groups
["Initialize", [true]] call BIS_fnc_dynamicGroups;
-if (isDedicated) then {
- ["milsim_logText", {
- params [["_strArray", [""], [[]]]];
- {
- diag_log text _x;
- } forEach _strArray;
- }] call CBA_fnc_addEventHandler;
-};
-
-
// initialize other modules
call EFUNC(common,logMissionInfo);
call EFUNC(fbcb2_assets,initServer);
diff --git a/framework/init/functions/fn_setDefaults.sqf b/framework/init/functions/fn_setDefaults.sqf
index 45a18d3..6bd43f8 100644
--- a/framework/init/functions/fn_setDefaults.sqf
+++ b/framework/init/functions/fn_setDefaults.sqf
@@ -1,5 +1,7 @@
#include "..\script_component.hpp"
+if (!hasInterface) exitWith {};
+
enableSaving[false, false];
enableRadio false;
diff --git a/framework/mapcopy/functions/fn_initClient.sqf b/framework/mapcopy/functions/fn_initClient.sqf
index 3287103..51c4304 100644
--- a/framework/mapcopy/functions/fn_initClient.sqf
+++ b/framework/mapcopy/functions/fn_initClient.sqf
@@ -10,6 +10,9 @@ private _mapCopyAction =
"\a3\ui_f\data\igui\cfg\actions\talk_ca.paa",
{
params ["_target", "_player", "_params"];
+ if (!isPlayer _target) exitWith {
+ format["%1 is not a player", name _target] call CBA_fnc_notify;
+ };
format["Copying map markers from %1", name _target] call CBA_fnc_notify;
[QGVAR(mapCopyRequest), _this, _target] call CBA_fnc_targetEvent;
},
diff --git a/framework/performance/functions/fn_addCBASettings.sqf b/framework/performance/functions/fn_addCBASettings.sqf
index 405e72c..947c1cb 100644
--- a/framework/performance/functions/fn_addCBASettings.sqf
+++ b/framework/performance/functions/fn_addCBASettings.sqf
@@ -1,5 +1,27 @@
#include "..\script_component.hpp"
+[
+ QGVAR(emptyGroupCleanup_enable),
+ "CHECKBOX",
+ "Empty Group Cleanup Enabled",
+ [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)],
+ true,
+ true,
+ {
+ params ["_value"];
+ [
+ QGVAR(emptyGroupCleanup_enable),
+ _value
+ ] call EFUNC(common,logSettingChanged);
+
+ if (!isNull (missionNamespace getVariable [QGVAR(emptyGroupCleanupPFH), locationNull])) then {
+ deleteLocation GVAR(emptyGroupCleanupPFH);
+ };
+
+ call FUNC(addEmptyGroupCleanupPFH);
+ }
+] call CBA_fnc_addSetting;
+
//---------------------
// Server CPS
//---------------------
diff --git a/framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf b/framework/performance/functions/fn_addEmptyGroupCleanupPFH.sqf
similarity index 71%
rename from framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf
rename to framework/performance/functions/fn_addEmptyGroupCleanupPFH.sqf
index 4833821..6dc4a90 100644
--- a/framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf
+++ b/framework/performance/functions/fn_addEmptyGroupCleanupPFH.sqf
@@ -7,7 +7,7 @@
[]
] call EFUNC(common,log);
-_emptyGroupPFH = [
+GVAR(emptyGroupCleanupPFH) = [
{
{
if (local _x) then {
@@ -19,7 +19,7 @@ _emptyGroupPFH = [
},
300,
[],
- {
+ { // on creation
[
LEVEL_INFO,
QUOTE(COMPONENT),
@@ -27,15 +27,16 @@ _emptyGroupPFH = [
[]
] call EFUNC(common,log);
},
- { [
+ { // on deletion
+ [
LEVEL_INFO,
QUOTE(COMPONENT),
"Empty group deletion PFH unloaded",
[]
] call EFUNC(common,log);
},
- { true },
- { false },
+ { (missionNamespace getVariable [QGVAR(emptyGroupCleanup_enable), false]) },
+ { not (missionNamespace getVariable [QGVAR(emptyGroupCleanup_enable), false]) },
[]
] call CBA_fnc_createPerFrameHandlerObject;
diff --git a/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf b/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf
deleted file mode 100644
index 781227e..0000000
--- a/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "..\script_component.hpp"
-
-// subroutine to gather nearest 50 units every 5 seconds and store in GVAR(drawTargets)
-// cleanup
-if (!isNil QGVAR(getEntitiesPFH)) then {
- [GVAR(getEntitiesPFH)] call CBA_fnc_removePerFrameHandler;
-};
-// add pfh
-GVAR(getEntitiesPFH) = [{
- GVAR(drawTargets) = (
- (allUnits + allDeadMen) select {
- _x isKindOf "CAManBase" &&
- player distance _x < 50 &&
- !isNull _x &&
- player isNotEqualTo _x
- }
- );
-}, 10] call CBA_fnc_addPerFrameHandler;
diff --git a/framework/triageIcons/functions/fn_addDrawIconsPFH.sqf b/framework/triageIcons/functions/fn_draw3D.sqf
similarity index 64%
rename from framework/triageIcons/functions/fn_addDrawIconsPFH.sqf
rename to framework/triageIcons/functions/fn_draw3D.sqf
index 6478264..21c9738 100644
--- a/framework/triageIcons/functions/fn_addDrawIconsPFH.sqf
+++ b/framework/triageIcons/functions/fn_draw3D.sqf
@@ -1,6 +1,6 @@
/*
-milsim_fnc_addMedicalOverlayPFH
+milsim_triageIcons_fnc_draw3D
Author: IndigoFox
@@ -14,30 +14,20 @@ Description:
#include "..\script_component.hpp"
+if (!hasInterface) exitWith {};
-// Per-frame handler to draw icons
-// cleanup
-if (!isNil QGVAR(drawIconsPfh)) then {
- [GVAR(drawIconsPfh)] call CBA_fnc_removePerFrameHandler;
-};
-// add pfh
-GVAR(drawIconsPfh) = [{
+
+// adds codeblock to common array to be processed per frame
+private _code = {
// if disabled, skip processing
if (!GVAR(setting_enabled)) exitWith {false};
- // if no targets, skip processing
- if (count GVAR(drawTargets) == 0) exitWith {false};
+
// if the player doesn't have medical perms, skip processing
if !([player] call ace_medical_treatment_fnc_isMedic) exitWith {false};
+
{
private _unit = _x;
- // distance within X meters
- if (player distance _unit > GVAR(setting_drawRange)) then {continue};
- // check unit not null, not conscious, and not in a vehicle
- if (
- !(_unit getVariable ["ACE_isUnconscious", false]) ||
- !isNull (objectParent _unit)
- ) then {continue};
-
+
// color based on triage level
private _triageLevel = _unit getVariable ["ace_medical_triageLevel", 4];
if (_triageLevel == -1) then {continue};
@@ -57,6 +47,17 @@ GVAR(drawIconsPfh) = [{
true // outline
// further params optional, omitted
];
- } forEach GVAR(drawTargets);
-}, 0, []] call CBA_fnc_addPerFrameHandler;
+
+ true;
+ } count (
+ (localNamespace getVariable [QEGVAR(client,nearMen), []]) select {
+ // is unconscious and is NOT in vehicle and is within draw range
+ (_x getVariable ["ACE_isUnconscious", false]) &&
+ isNull (objectParent _x) &&
+ player distance _x <= GVAR(setting_drawRange)
+ }
+ );
+};
+// add codeblock to common array
+[_code] call EFUNC(client,registerPFHCode);
\ No newline at end of file
diff --git a/framework/triageIcons/functions/fn_initClient.sqf b/framework/triageIcons/functions/fn_initClient.sqf
index 7b22f9d..f14600a 100644
--- a/framework/triageIcons/functions/fn_initClient.sqf
+++ b/framework/triageIcons/functions/fn_initClient.sqf
@@ -1,7 +1,8 @@
#include "..\script_component.hpp"
-// List of units to draw icons for
-GVAR(drawTargets) = [];
+if (!hasInterface) exitWith {};
+
+call FUNC(draw3D);
[
LEVEL_DEBUG,
diff --git a/framework/vehicleFlags/functions/fn_addFlagActions.sqf b/framework/vehicleFlags/functions/fn_addFlagActions.sqf
new file mode 100644
index 0000000..7b14721
--- /dev/null
+++ b/framework/vehicleFlags/functions/fn_addFlagActions.sqf
@@ -0,0 +1,103 @@
+#include "..\script_component.hpp"
+
+private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg);
+
+if (!isClass _vehicleFlagsCfg) exitWith {
+ ["WARNING: Vehicle Flags: Vehicle Flags config not found. Vehicle Flags will not be available."] call BIS_fnc_error;
+};
+
+private _baseClassesToApplyActionsFor =
+ (_vehicleFlagsCfg >> "baseClassesToApplyActionsFor") call BIS_fnc_getCfgDataArray;
+private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren;
+
+{ // forEach _baseClassesToApplyActionsFor
+ private _parentClass = _x;
+
+ ////////////////////////////////////////////////////////////////////////
+ // create the root action
+ ////////////////////////////////////////////////////////////////////////
+ private _rootActionID = QGVAR(SetVehicleFlagAction);
+ private _flagRootAction = [
+ _rootActionID, // id
+ "Set Vehicle Flag", // displayed title
+ "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon
+ {
+ params ["_target", "_player", "_params"];
+ // set broadcasted variable of self to indicate we're looking at flags
+ _player setVariable [QGVAR(inFlagMenu), true, true];
+ [{_this setVariable [QGVAR(inFlagMenu), false, true];}, _player, 3] call CBA_fnc_waitAndExecute;
+ true
+ }, // statement
+ {
+ params ["_target", "_player", "_params"];
+ // _params params ["_parentActionID", "_flagCategories"];
+
+ // check if vehicle is excluded
+ private _excluded = [typeOf _target] call FUNC(isClassExcluded);
+ if (_excluded || !alive _target) exitWith {false};
+
+ true;
+ }, // condition
+ {
+ ////////////////////////////////////////////////////////////////////////
+ // create the flag category actions (with nested flag actions)
+ ////////////////////////////////////////////////////////////////////////
+ params ["_target", "_player", "_params"];
+ _params params ["_rootActionID"];
+
+ private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg);
+ if (isNull _vehicleFlagsCfg) exitWith {[]};
+ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren;
+
+ // return category child actions with individual flag actions nested as children
+ [_rootActionID, _flagCategoryCfgs] call FUNC(getActionsFlagCategories);
+
+ }, // child code
+ [_rootActionID], // params
+ nil, // position
+ 4, // distance
+ [false, false, false, true, false], // other params - run on hover is true
+ nil // modifier function code
+ ] call ace_interact_menu_fnc_createAction;
+
+ ////////////////////////////////////////////////////////////////////////
+ // add root action to add flags
+ ////////////////////////////////////////////////////////////////////////
+ [
+ _parentClass, // parent classname
+ 0, // action 0 or self-action 1
+ ["ACE_MainActions"], // parent
+ _flagRootAction, // action
+ true // apply to child classes
+ ] call ace_interact_menu_fnc_addActionToClass;
+
+ ////////////////////////////////////////////////////////////////////////
+ // add action to remove flag under the root action
+ ////////////////////////////////////////////////////////////////////////
+ // create action
+ private _removeFlagAction = [
+ _rootActionID + "_removeflag", // id
+ "Remove Flag", // displayed title
+ "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon
+ {
+ params ["_target", "_player", "_params"];
+ _target forceFlagTexture "";
+ }, // statement
+ {
+ params ["_target", "_player", "_params"];
+ alive _target && getForcedFlagTexture _target != "";
+ }, // condition
+ nil // child code
+ ] call ace_interact_menu_fnc_createAction;
+
+ // add the action to the vehicle
+ // in this class event handler, this#0 will be the vehicle
+ [
+ _parentClass, // parent classname
+ 0, // action 0 or self-action 1
+ ["ACE_MainActions", _rootActionID], // parent
+ _removeFlagAction, // action
+ true // apply to child classes
+ ] call ace_interact_menu_fnc_addActionToClass;
+
+} forEach _baseClassesToApplyActionsFor;
\ No newline at end of file
diff --git a/framework/vehicleFlags/functions/fn_draw3D.sqf b/framework/vehicleFlags/functions/fn_draw3D.sqf
new file mode 100644
index 0000000..3b971a3
--- /dev/null
+++ b/framework/vehicleFlags/functions/fn_draw3D.sqf
@@ -0,0 +1,24 @@
+#include "..\script_component.hpp"
+
+// we'll use this to display status if nearby players are in the flag menu
+
+// adds codeblock to common array to be processed per frame
+private _code = {
+ private _unitsToDraw = (localNamespace getVariable [QEGVAR(client,nearMen), []]) select {
+ (_x getVariable [QGVAR(inFlagMenu), false]) && {
+ // distance within X meters
+ player distance _x <= 15 ||
+ // check unit not in a vehicle
+ isNull (objectParent _x)
+ }
+ };
+ [
+ _unitsToDraw,
+ "",
+ "Setting vehicle flag...",
+ [0.9, 0.9, 0.9, 1]
+ ] call EFUNC(common,draw3dIconStatus);
+};
+
+// add codeblock to common array
+[_code] call EFUNC(client,registerPFHCode);
\ No newline at end of file
diff --git a/framework/vehicleFlags/functions/fn_initClient.sqf b/framework/vehicleFlags/functions/fn_initClient.sqf
index b0d9537..f09a25c 100644
--- a/framework/vehicleFlags/functions/fn_initClient.sqf
+++ b/framework/vehicleFlags/functions/fn_initClient.sqf
@@ -2,101 +2,8 @@
if (!hasInterface) exitWith {};
-private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg);
-
-if (!isClass _vehicleFlagsCfg) exitWith {
- ["WARNING: Vehicle Flags: Vehicle Flags config not found. Vehicle Flags will not be available."] call BIS_fnc_error;
-};
-
-private _baseClassesToApplyActionsFor =
- (_vehicleFlagsCfg >> "baseClassesToApplyActionsFor") call BIS_fnc_getCfgDataArray;
-private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren;
-
-{ // forEach _baseClassesToApplyActionsFor
- private _parentClass = _x;
-
- ////////////////////////////////////////////////////////////////////////
- // create the root action
- ////////////////////////////////////////////////////////////////////////
- private _rootActionID = QGVAR(SetVehicleFlagAction);
- private _flagRootAction = [
- _rootActionID, // id
- "Set Vehicle Flag", // displayed title
- "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon
- {true}, // statement
- {
- params ["_target", "_player", "_params"];
- // _params params ["_parentActionID", "_flagCategories"];
-
- // check if vehicle is excluded
- private _excluded = [typeOf _target] call FUNC(isClassExcluded);
- if (_excluded || !alive _target) exitWith {false};
-
- true;
- }, // condition
- {
- ////////////////////////////////////////////////////////////////////////
- // create the flag category actions (with nested flag actions)
- ////////////////////////////////////////////////////////////////////////
- params ["_target", "_player", "_params"];
- _params params ["_rootActionID"];
-
- private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg);
- if (isNull _vehicleFlagsCfg) exitWith {[]};
- private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren;
-
- // return category child actions with individual flag actions nested as children
- [_rootActionID, _flagCategoryCfgs] call FUNC(getActionsFlagCategories);
-
- }, // child code
- [_rootActionID], // params
- nil, // position
- 4, // distance
- [false, false, false, false, false], // other params
- nil // modifier function code
- ] call ace_interact_menu_fnc_createAction;
-
- ////////////////////////////////////////////////////////////////////////
- // add root action to add flags
- ////////////////////////////////////////////////////////////////////////
- [
- _parentClass, // parent classname
- 0, // action 0 or self-action 1
- ["ACE_MainActions"], // parent
- _flagRootAction, // action
- true // apply to child classes
- ] call ace_interact_menu_fnc_addActionToClass;
-
- ////////////////////////////////////////////////////////////////////////
- // add action to remove flag under the root action
- ////////////////////////////////////////////////////////////////////////
- // create action
- private _removeFlagAction = [
- _rootActionID + "_removeflag", // id
- "Remove Flag", // displayed title
- "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon
- {
- params ["_target", "_player", "_params"];
- _target forceFlagTexture "";
- }, // statement
- {
- params ["_target", "_player", "_params"];
- alive _target && getForcedFlagTexture _target != "";
- }, // condition
- nil // child code
- ] call ace_interact_menu_fnc_createAction;
-
- // add the action to the vehicle
- // in this class event handler, this#0 will be the vehicle
- [
- _parentClass, // parent classname
- 0, // action 0 or self-action 1
- ["ACE_MainActions", _rootActionID], // parent
- _removeFlagAction, // action
- true // apply to child classes
- ] call ace_interact_menu_fnc_addActionToClass;
-
-} forEach _baseClassesToApplyActionsFor;
+call FUNC(addFlagActions);
+call FUNC(draw3D);
[
LEVEL_DEBUG,
diff --git a/images/leaflets/.gitkeep b/images/leaflets/.gitkeep
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/images/leaflets/.gitkeep
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/images/leaflets/leaflet_template.jpg b/images/leaflets/leaflet_template.jpg
new file mode 100644
index 0000000..23d90e5
Binary files /dev/null and b/images/leaflets/leaflet_template.jpg differ
diff --git a/mission_settings.hpp b/mission_settings.hpp
index 224ef78..a47eb0b 100644
--- a/mission_settings.hpp
+++ b/mission_settings.hpp
@@ -1,4 +1,4 @@
-author = "MISSION AUTHOR";
+author = "MISSION AUTHOR";
onLoadName = "THIS APPEARS ON TOP OF THE LOADING SCREEN IMAGE";
loadScreen = "mission.jpg";
onLoadMission = "THIS APPEARS BELOW THE LOADING SCREEN IMAGE";
@@ -9,8 +9,28 @@ overviewText = "THIS IS WHERE YOU DESCRIBE THE MISSION IN THE #MISSION LIST";
// The name for the series of missions of your campaign. Used for organizational and search purposes
missionSeries = "MY SERIES NAME";
-// activate via #ace-fortify west base 2000
+// What kind of mission is this? (Use only one)
+missionGroup = "17thSaturdayOp";
+// missionGroup = "17thFridayOp";
+// missionGroup = "17thWednesdayOp";
+// missionGroup = "17thFTX";
+// missionGroup = "17thTraining";
+
+// Add waypoints to players' MicroDAGR devices
+// respawn locations (bases) are added by default, don't put them here
+custom_microdagr_waypoints[] = {
+ // the first element is the waypoint name
+ // the second element is the position of the waypoint - you may use a string for map grid (up to 10 digit) or an array for {X, Y} coordinates
+ // the third element is optional - provide the variable name of an object if you want to use its initial position instead
+ // {"WAYPOINT NAME", {POSITION <[x,y]>}, OBJECT },
+ // EXAMPLES:
+ // {"KAVALA HOSPITAL", {1234.56, 7890.12}, ""},
+ // {"CAMP TEMPEST", "03421460, ""},
+ // {"MY CUSTOM OBJECT", {}, "myCustomObject"}
+};
+
+// activate via #ace-fortify west base 2000
class ACEX_Fortify_Presets {
class base {
displayName = "Ken Custom";