diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp
index 2a3c4a0..978abca 100644
--- a/framework/CfgFunctions.hpp
+++ b/framework/CfgFunctions.hpp
@@ -5,9 +5,10 @@ class DOUBLES(PREFIX,init) {
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 setDefaults {};
+ class addAARChatHandler {};
+ class addRespawnChatHandler {};
+ class checkMissionSettings {};
};
};
@@ -22,10 +23,11 @@ class PREFIX {
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 initClient {};
+ class addMicroDAGRWaypoints {};
+ class addZenModules {};
+ class bindEventHandlers {};
+ class bindVehicleActions {};
};
};
@@ -103,13 +105,14 @@ class DOUBLES(PREFIX,performance) {
class functions {
file = "framework\performance\functions";
class addCBASettings {preInit=1;};
- class addDNI_PlayerFPS { postInit = 1; };
+ class addDNI_PlayerFPS {postInit = 1;};
// PFHs managed in addCBASettings onChange code
class addClientStatsPFH {};
class calculateClientStats {};
class addServerStatsPFH {};
class calculateServerStats {};
+ class addEmptyGroupCleanupPFH {};
};
};
diff --git a/framework/client/functions/fn_addMicroDAGRWaypoints.sqf b/framework/client/functions/fn_addMicroDAGRWaypoints.sqf
new file mode 100644
index 0000000..f72e858
--- /dev/null
+++ b/framework/client/functions/fn_addMicroDAGRWaypoints.sqf
@@ -0,0 +1,59 @@
+#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 > 0) then {
+ if (typeName _pos == "STRING") then {
+ _realPos = [_pos, true] call ACE_common_fnc_getMapPosFromGrid;
+ _realPos set [2, getTerrainHeightASL _realPos];
+ } else {_realPos = _pos;};
+ };
+ // 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;
+ } forEach _customWaypoints;
+}] call CBA_fnc_waitUntilAndExecute;
+
+nil;
\ 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..1d5e7bb
--- /dev/null
+++ b/framework/client/functions/fn_initClient.sqf
@@ -0,0 +1,20 @@
+#include "..\script_component.hpp"
+
+
+if (!hasInterface) exitWith {};
+
+call FUNC(addMicroDAGRWaypoints);
+call FUNC(addZenModules);
+call FUNC(bindEventHandlers);
+call FUNC(bindVehicleActions);
+
+[
+ 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/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..3a08fbf 100644
--- a/framework/init/functions/fn_addRespawnChatHandler.sqf
+++ b/framework/init/functions/fn_addRespawnChatHandler.sqf
@@ -1,5 +1,7 @@
#include "..\script_component.hpp"
+if (!hasInterface) exitWith {};
+
[
"respawn",
{
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..fc9f0d5 100644
--- a/framework/init/functions/fn_initClient.sqf
+++ b/framework/init/functions/fn_initClient.sqf
@@ -1,6 +1,6 @@
#include "..\script_component.hpp"
-if ( !hasInterface ) exitWith {};
+if (!hasInterface) exitWith {};
["milsim_logText", {
params [["_strArray", [""], [[]]]];
@@ -14,6 +14,13 @@ waitUntil {!isNil QGVARMAIN(complete)};
["InitializePlayer", [player, true]] call BIS_fnc_dynamicGroups;
+// run primary init functions
+call FUNC(addAARChatHandler);
+call FUNC(addRespawnChatHandler);
+call FUNC(setDefaults);
+call FUNC(checkMissionSettings);
+
+
// Initialize a holder for managing local diary records
// store records in format:
// [subject, [
@@ -23,6 +30,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 +41,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_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/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/mission_settings.hpp b/mission_settings.hpp
index 224ef78..fcc6810 100644
--- a/mission_settings.hpp
+++ b/mission_settings.hpp
@@ -9,8 +9,21 @@ 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
+// 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";