diff --git a/README.md b/README.md index 655431a..d48d6bd 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,27 @@ # Installation Instructions -Once your mission has been created and saved in the Arma 3 Eden Editor, download the latest mission template zip and copy its contents to the folder where your mission file lives. +The only file which should be pre-existing in your mission folder is `mission.sqm`, once freshly saved from Arma 3's EDEN Editor. -The only file which should be pre-existing in your mission folder is `mission.sqm` +Download the latest mission template zip from the [latest release](https://17th-gs.iceberg-gaming.com:5443/hizumi/MissionTemplate/releases/latest) and copy its contents to the folder where your mission file lives. Once copied, the final structure should appear similar to the following: ```markdown -├── functions/ +├── aaFrameworkUtils/ +├── defines/ +├── framework/ ├── images/ ├── scripts/ ├── sounds/ ├── textures/ +├── CHANGELOG.md ├── description.ext +├── mission_settings.hpp ├── mission.jpg ├── mission.sqm -├── mission_settings.hpp ``` +If you're building a mission for use in an op, please delete "aaFrameworkUtils" and "framework\x". These are for the purposes of development and add size bloat to the mission download when players connect to your mission. + After the requisite configuration file edits have been made, your mission is ready to be packed into a pbo for deployment. # Files @@ -46,7 +51,7 @@ This directory is for organizational purposes for any images you wish to use in ## scripts/ -This directory is for organizational purposes for any custom scripts you wish to use in your mission. +This directory is for organizational purposes for any custom scripts you wish to use in your mission. > **Note**: Scripts may need to be edited to account for their new location ## sounds/ @@ -56,4 +61,12 @@ This directory is for organizational purposes for any custom scripts you wish to ## textures/ -This directory is for organizational purposes for textures files used by mission scripts \ No newline at end of file +This directory is for organizational purposes for textures files used by mission scripts. + +## DEV NOTES + +All modules are broken apart as such in /framework. Client and server inits are managed in /framework/init. + +Pay attention to framework/script_mod.hpp prior to deployment of releases, as the debug settings within will determine what is logged during prod missions. + +CfgFunctions is sensitive to the folder/script_component.hpp of each module. \ No newline at end of file diff --git a/defines/BattalionInfo.hpp b/defines/BattalionInfo.hpp index 52ab77a..bcb4f8b 100644 --- a/defines/BattalionInfo.hpp +++ b/defines/BattalionInfo.hpp @@ -8,7 +8,7 @@ #define RRC_CALLSIGN TIGER #define MEDIC_CALLSIGN LIFELINE #define ALPHA_CALLSIGN BLACKJACK -#define ECHO_CALLSIGN ZOOMER +#define ECHO_CALLSIGN FIREBRAND #define WPN_CALLSIGN BLACKFOOT // Define the frequencies for the Battalion @@ -229,8 +229,8 @@ class BattalionInfo { }; }; - class Attack { - callsign = CALLSIGN_ELEMENT(ECHO_CALLSIGN, ATTACK); + class Armor { + callsign = CALLSIGN_ELEMENT(ECHO_CALLSIGN, ARMOR); textColor = LVL4_TEXT_COLOR; frequencies[] = { {"Contact", {}, {FREQ_ECHO_GROUND, FREQ_ECHO_FLIGHT_CAS}}, diff --git a/defines/SignalColors.hpp b/defines/SignalColors.hpp new file mode 100644 index 0000000..f6c3393 --- /dev/null +++ b/defines/SignalColors.hpp @@ -0,0 +1,44 @@ +class SignalColors { + class White { + name = "White"; + hexCode = "#FFFFFF"; + usage = "Concealment, Light"; + itemExamples[] = {"SmokeShell", "1Rnd_Smoke_Grenade_shell", "ACE_Chemlight_White"}; + }; + class Green { + name = "Green"; + hexCode = "#00FF00"; + usage = "Friendly Forces"; + itemExamples[] = {"SmokeShellGreen", "1Rnd_SmokeGreen_Grenade_shell", "Chemlight_green"}; + }; + class Blue { + name = "Blue"; + hexCode = "#0000FF"; + usage = "LZ Marking"; + itemExamples[] = {"SmokeShellBlue", "1Rnd_SmokeBlue_Grenade_shell", "Chemlight_blue"}; + }; + class Red { + name = "Red"; + hexCode = "#FF0000"; + usage = "Enemy Location"; + itemExamples[] = {"SmokeShellRed", "1Rnd_SmokeRed_Grenade_shell", "Chemlight_red"}; + }; + class Orange { + name = "Orange"; + hexCode = "#FFA500"; + usage = "Resupply Marker"; + itemExamples[] = {"SmokeShellOrange", "1Rnd_SmokeOrange_Grenade_shell", "ACE_Chemlight_Orange"}; + }; + class Yellow { + name = "Yellow"; + hexCode = "#FFFF00"; + usage = "Medical Emergency"; + itemExamples[] = {"SmokeShellYellow", "1Rnd_SmokeYellow_Grenade_shell", "Chemlight_yellow"}; + }; + class Purple { + name = "Purple"; + hexCode = "#800080"; + usage = "Broken Arrow - 100m radius"; + itemExamples[] = {"SmokeShellPurple", "1Rnd_SmokePurple_Grenade_shell"}; + }; +}; \ No newline at end of file diff --git a/description.ext b/description.ext index 3bb5ba0..b23393f 100644 --- a/description.ext +++ b/description.ext @@ -17,11 +17,13 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include "mission_settings.hpp" +#include "framework\script_mod.hpp" #include "defines\ApprovedAssets.hpp" #include "defines\BattalionInfo.hpp" #include "defines\DisallowedEquipment.hpp" #include "defines\SupplyCrates.hpp" #include "defines\VehicleFlags.hpp" +#include "defines\SignalColors.hpp" //-------------------------------------------MISSION INFO-------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -92,10 +94,9 @@ class Params }; -class cfgFunctions -{ - #include "functions\CfgFunctions.hpp" -}; +// CfgFunctions +#include "framework\CfgFunctions.hpp" + class CfgDebriefingSections { diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp new file mode 100644 index 0000000..d9e5f96 --- /dev/null +++ b/framework/CfgFunctions.hpp @@ -0,0 +1,172 @@ +#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 PREFIX { + class ambience { + file = "framework\ambience"; + class flakInitVehicle {}; + class flakEH {}; + }; + + class map { + file = "framework\map"; + class initMapCopy { postInit = 1; }; + class copyMapFromPlayer {}; //needs refactor + class getPlayerMapMarkers {}; //needs refactor + class loadMapMarkers {}; //needs refactor + class mapMarkerToString {}; //needs refactor + class stringToMapMarker {}; //needs refactor + }; + }; + + class DOUBLES(PREFIX,client) { + class functions { + file = "framework\client\functions"; + class addZenModules { postInit = 1; }; + class bindEmptyGroupGarbageCleanup { postInit = 1; }; + class bindEventHandlers { postInit = 1; }; + class bindVehicleActions { postInit = 1; }; + }; + }; + + + class DOUBLES(PREFIX,common) { + class functions { + file = "framework\common\functions"; + class addCBASettings { preInit = 1; }; + class logMissionInfo {}; + class addPlayerInfoToArray {}; + class getApprovedAssetsCfg {}; + class getBattalionCfg {}; + class getNameOfBase {}; + class getNearestBase {}; + class log {}; + class checkPlayerInventory {}; + 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_main) { + class functions { + file = "framework\fbcb2_main\functions"; + class initClient {}; + class addEnvironmentRecord {}; + class addFrequenciesRecord {}; + class addSignalColorsRecord {}; + }; + class util { + file = "framework\fbcb2_main\util"; + class createOrUpdateDiaryRecord {}; + 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,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,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 addDrawIconsPFH {}; + class addGetEntitiesPFH {}; + class updateColors {}; + }; + }; + + class DOUBLES(PREFIX,vehicleFlags) { + class functions { + file = "framework\vehicleFlags\functions"; + class initClient {}; + class getActionsFlagCategories {}; + class getVehicleFlagsCfg {}; + class isClassExcluded {}; + }; + }; +}; \ No newline at end of file diff --git a/functions/ambience/fn_flakEH.sqf b/framework/ambience/fn_flakEH.sqf similarity index 100% rename from functions/ambience/fn_flakEH.sqf rename to framework/ambience/fn_flakEH.sqf diff --git a/functions/ambience/fn_flakInitVehicle.sqf b/framework/ambience/fn_flakInitVehicle.sqf similarity index 100% rename from functions/ambience/fn_flakInitVehicle.sqf rename to framework/ambience/fn_flakInitVehicle.sqf diff --git a/functions/client/fn_addZenModules.sqf b/framework/client/functions/fn_addZenModules.sqf similarity index 80% rename from functions/client/fn_addZenModules.sqf rename to framework/client/functions/fn_addZenModules.sqf index 211aa43..0aeb533 100644 --- a/functions/client/fn_addZenModules.sqf +++ b/framework/client/functions/fn_addZenModules.sqf @@ -1,12 +1,14 @@ +#include "..\script_component.hpp" + if ( !hasInterface ) exitWith {}; [ - "17th Battalion", + QUOTE(MODULE_CATEGORY_NAME), "Create Resupply Box", { params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; // get parent definition - private _supplyCratesCfg = call milsim_resupply_fnc_getSupplyCratesCfg; + private _supplyCratesCfg = call EFUNC(resupply,getSupplyCratesCfg); // get the subclass names private _boxTypesAvailable = _supplyCratesCfg call BIS_fnc_getCfgSubClasses; @@ -36,11 +38,17 @@ if ( !hasInterface ) exitWith {}; _args params ["_pos", "_target", "_keysSorted"]; - private _box = [_target, _typeOptionSelected, _pos] call milsim_resupply_fnc_createBox; + private _box = [_target, _typeOptionSelected, _pos] call EFUNC(resupply,createBox); if (isNull _box) exitWith { ["Resupply Box", "WARNING: Failed to locate or create box!"] call BIS_fnc_curatorHint; }; - ["Resupply Box", format["Created box from class %1", _typeOptionSelected]] call BIS_fnc_curatorHint; + [ + "Resupply Box", + format[ + "Created %1", + getText((call EFUNC(resupply,getSupplyCratesCfg)) >> _typeOptionSelected >> "displayName") + ] + ] call BIS_fnc_curatorHint; }, {}, [_pos, _target] @@ -50,7 +58,7 @@ if ( !hasInterface ) exitWith {}; [ - "17th Battalion", + QUOTE(MODULE_CATEGORY_NAME), "Grounds Cleanup", { params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; diff --git a/framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf b/framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf new file mode 100644 index 0000000..4833821 --- /dev/null +++ b/framework/client/functions/fn_bindEmptyGroupGarbageCleanup.sqf @@ -0,0 +1,43 @@ +#include "..\script_component.hpp" + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "Initializing empty group deletion PFH", + [] +] call EFUNC(common,log); + +_emptyGroupPFH = [ + { + { + if (local _x) then { + if ((count units _x) == 0) then { + deleteGroup _x; + }; + }; + } forEach allGroups; + }, + 300, + [], + { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Empty group deletion PFH loaded", + [] + ] call EFUNC(common,log); + }, + { [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Empty group deletion PFH unloaded", + [] + ] call EFUNC(common,log); + }, + { true }, + { false }, + [] +] call CBA_fnc_createPerFrameHandlerObject; + + + diff --git a/functions/client/fn_bindEventHandlers.sqf b/framework/client/functions/fn_bindEventHandlers.sqf similarity index 82% rename from functions/client/fn_bindEventHandlers.sqf rename to framework/client/functions/fn_bindEventHandlers.sqf index b4bcf8f..802c2c5 100644 --- a/functions/client/fn_bindEventHandlers.sqf +++ b/framework/client/functions/fn_bindEventHandlers.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + if ( !hasInterface ) exitWith {}; player addEventHandler["Respawn", @@ -6,10 +8,11 @@ player addEventHandler["Respawn", private _killer = _corpse getVariable ["ace_medical_causeOfDeath", "#scripted"]; if (_killer == "respawn_button") then { [ - "client", + LEVEL_INFO, + QUOTE(COMPONENT), "RESPAWNED WHILE UNCONSCIOUS", - [_unit] call milsim_fnc_addPlayerInfoToArray - ] remoteExec ["milsim_fnc_log", 2]; + [_unit] call EFUNC(common,addPlayerInfoToArray) + ] remoteExec [QEFUNC(common,log), 2]; // format["%1 was unconscious then clicked the respawn button", name _unit] remoteExec["systemChat", 0]; }; } @@ -43,11 +46,11 @@ addMissionEventHandler ["HandleChatMessage", ["ace_arsenal_displayClosed", { - [player] remoteExec ["milsim_fnc_logPlayerInventory", 2]; + [player] remoteExec [QEFUNC(common,checkPlayerInventory), 2]; }] call CBA_fnc_addEventHandler; [missionNamespace, "arsenalClosed", { - [player] remoteExec ["milsim_fnc_logPlayerInventory", 2]; + [player] remoteExec [QEFUNC(common,checkPlayerInventory), 2]; }] call BIS_fnc_addScriptedEventHandler; diag_log text "[MILSIM] (client) event handlers bound"; diff --git a/functions/client/fn_bindVehicleActions.sqf b/framework/client/functions/fn_bindVehicleActions.sqf similarity index 92% rename from functions/client/fn_bindVehicleActions.sqf rename to framework/client/functions/fn_bindVehicleActions.sqf index ccf502f..6947457 100644 --- a/functions/client/fn_bindVehicleActions.sqf +++ b/framework/client/functions/fn_bindVehicleActions.sqf @@ -56,7 +56,7 @@ _patchTire = "Patching" ] call ace_common_fnc_progressBar }, - { ( alive _target ) && ( [_player, "ToolKit"] call ace_common_fnc_hasItem ) && ( getDammage _target > 0.2 ) && ( _target getVariable["milsim_ace_repair_wheel_canPatch", true] ) } + { ( alive _target ) && ( [_player, "ToolKit"] call ace_common_fnc_hasItem ) && ( damage _target > 0.2 ) && ( _target getVariable["milsim_ace_repair_wheel_canPatch", true] ) } ] call ace_interact_menu_fnc_createAction; ["ACE_Wheel", 0, ["ACE_MainActions"], _patchTire, true] call ace_interact_menu_fnc_addActionToClass; diff --git a/framework/client/script_component.hpp b/framework/client/script_component.hpp new file mode 100644 index 0000000..3186ff3 --- /dev/null +++ b/framework/client/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT client +#define COMPONENT_BEAUTIFIED Client +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/common/functions/fn_addCBASettings.sqf b/framework/common/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..700f1ae --- /dev/null +++ b/framework/common/functions/fn_addCBASettings.sqf @@ -0,0 +1,27 @@ +#include "..\script_component.hpp" + +//--------------------- +// Side Chat +//--------------------- + +[ + QGVARMAIN(sideChat), + "CHECKBOX", + "Side Chat Text Enabled", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + false, // default value + true, // requires restart + { + params ["_value"]; + [ + QGVARMAIN(sideChat), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[QGVARMAIN(sideChat), false] call CBA_settings_fnc_set; + +diag_log text "[MILSIM] (settings) Custom CBA settings initialized"; + +nil; \ No newline at end of file diff --git a/functions/util/fn_addPlayerInfoToArray.sqf b/framework/common/functions/fn_addPlayerInfoToArray.sqf similarity index 59% rename from functions/util/fn_addPlayerInfoToArray.sqf rename to framework/common/functions/fn_addPlayerInfoToArray.sqf index 4a473df..353410c 100644 --- a/functions/util/fn_addPlayerInfoToArray.sqf +++ b/framework/common/functions/fn_addPlayerInfoToArray.sqf @@ -1,4 +1,6 @@ -params [["_playerObj", objNull], ["_arrayToModify", [], [[]]]]; +#include "..\script_component.hpp" + +params [["_playerObj", objNull, [nil, objNull]], ["_arrayToModify", [], [[]]]]; if (isNull _playerObj) exitWith {_arrayToModify}; @@ -8,7 +10,7 @@ if (isNull _playerObj) exitWith {_arrayToModify}; ["playerName", name _playerObj], ["playerUID", getPlayerUID _playerObj], ["playerGroup", groupId (group _playerObj)], - ["playerNetID", [_playerObj] call BIS_fnc_netId] + ["playerNetID", _playerObj call BIS_fnc_netId] ]; _arrayToModify; \ No newline at end of file diff --git a/functions/server/fn_logPlayerInventory.sqf b/framework/common/functions/fn_checkPlayerInventory.sqf similarity index 88% rename from functions/server/fn_logPlayerInventory.sqf rename to framework/common/functions/fn_checkPlayerInventory.sqf index 835d529..ab30d33 100644 --- a/functions/server/fn_logPlayerInventory.sqf +++ b/framework/common/functions/fn_checkPlayerInventory.sqf @@ -1,5 +1,5 @@ /* - Function: milsim_fnc_logPlayerInventory + Function: milsim_common_fnc_checkPlayerInventory Description: Checks a player's inventory for non-compliant items and logs results to all machines. @@ -13,16 +13,19 @@ - Array of strings to be logged. */ +#include "..\script_component.hpp" + params [ ["_player", objNull, [objNull]] ]; if (!isPlayer _player) exitWith { [ - "logPlayerInventory", + LEVEL_ERROR, + QUOTE(COMPONENT), "PARAM PLAYER IS NOT A PLAYER", [["player", _player]] - ] call milsim_fnc_log; + ] call EFUNC(common,log); }; // testing @@ -53,10 +56,11 @@ _playerItems pushBack (uniform _player); [ - "logPlayerInventory", + LEVEL_DEBUG, + QUOTE(COMPONENT), "CHECKING PLAYER INVENTORY", - [_player] call milsim_fnc_addPlayerInfoToArray -] call milsim_fnc_log; + [_player] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); //////////////////////////////////////// // HARDCODED DISALLOWED ITEMS - see functions/definitions/DisallowedEquipment.hpp @@ -115,10 +119,11 @@ private _thermalItems = _playerItems select { // Only log compliance message if no non-compliant items were found if (count _allFoundItemsSoFar isEqualTo 0) exitWith { [ - "logPlayerInventory", + LEVEL_INFO, + QUOTE(COMPONENT), "PLAYER INVENTORY IS COMPLIANT", - [_player] call milsim_fnc_addPlayerInfoToArray - ] call milsim_fnc_log; + [_player] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); }; // Log all non-compliant items @@ -132,13 +137,14 @@ if (count _allFoundItemsSoFar isEqualTo 0) exitWith { private _itemConfig = _itemClassName call CBA_fnc_getItemConfig; // Log to RPT [ - "logPlayerInventory", + LEVEL_WARNING, + QUOTE(COMPONENT), "NON-COMPLIANT ITEM", [_player, [ ["category", _categoryLabel], ["className", _itemClassName], ["displayName", [_itemConfig] call BIS_fnc_displayName] - ]] call milsim_fnc_addPlayerInfoToArray - ] call milsim_fnc_log; + ]] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); } forEach _items; } forEach _foundItemsKeyValue; \ No newline at end of file diff --git a/framework/common/functions/fn_getApprovedAssetsCfg.sqf b/framework/common/functions/fn_getApprovedAssetsCfg.sqf new file mode 100644 index 0000000..bb18e61 --- /dev/null +++ b/framework/common/functions/fn_getApprovedAssetsCfg.sqf @@ -0,0 +1,15 @@ +#include "../script_component.hpp" + +private _approvedAssetsCfg = (missionConfigFile >> "ApprovedAssets"); + +if (!IS_CONFIG(_approvedAssetsCfg) || {!isClass _approvedAssetsCfg}) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "ERROR: Approved assets config not found. Check that the config is present and correctly named in the mission config file. See defines/ApprovedAssets.hpp and framework/util/functions/getApprovedAssetsCfg.sqf.", + [] + ] call EFUNC(common,log); + configNull; +}; + +_approvedAssetsCfg; \ No newline at end of file diff --git a/framework/common/functions/fn_getBattalionCfg.sqf b/framework/common/functions/fn_getBattalionCfg.sqf new file mode 100644 index 0000000..cfac05c --- /dev/null +++ b/framework/common/functions/fn_getBattalionCfg.sqf @@ -0,0 +1,15 @@ +#include "../script_component.hpp" + +private _battalionInfoCfg = (missionConfigFile >> "BattalionInfo"); + +if (!IS_CONFIG(_battalionInfoCfg) || {!isClass _battalionInfoCfg}) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "ERROR: Battalion config not found. Check that the battalion config is present and correctly named in the mission config file. See defines/BattalionInfo.hpp and framework/util/functions/getBattalionCfg.sqf.", + [] + ] call EFUNC(common,log); + configNull; +}; + +_battalionInfoCfg; \ No newline at end of file diff --git a/functions/util/fn_getNameOfBase.sqf b/framework/common/functions/fn_getNameOfBase.sqf similarity index 89% rename from functions/util/fn_getNameOfBase.sqf rename to framework/common/functions/fn_getNameOfBase.sqf index 81ed4ec..c0d56e8 100644 --- a/functions/util/fn_getNameOfBase.sqf +++ b/framework/common/functions/fn_getNameOfBase.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + params [["_base", objNull, [objNull]]]; if (_base == objNull) exitWith {""}; diff --git a/functions/util/fn_getNearestBase.sqf b/framework/common/functions/fn_getNearestBase.sqf similarity index 87% rename from functions/util/fn_getNearestBase.sqf rename to framework/common/functions/fn_getNearestBase.sqf index 68b103c..4dfc208 100644 --- a/functions/util/fn_getNearestBase.sqf +++ b/framework/common/functions/fn_getNearestBase.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + params [["_object", objNull, [objNull]]]; if (isNull _object) exitWith {objNull}; diff --git a/framework/common/functions/fn_log.sqf b/framework/common/functions/fn_log.sqf new file mode 100644 index 0000000..716c0df --- /dev/null +++ b/framework/common/functions/fn_log.sqf @@ -0,0 +1,33 @@ +/* + Function: milsim_common_fnc_log + + Description: + Used to log messages to the server RPT file. + + Parameters: + 0: NUMBER - log level. + 1: STRING - component name. + 2: STRING - message to log. + 3: ARRAY - key value pairs of data to log. +*/ +#include "..\script_component.hpp" + +params [ + ["_logLevel", 1, [-1,0,1,2,3]], // script_mod.hpp + ["_component", "", [""]], + ["_message", "", [""]], + ["_data", [], [[]]] +]; + +if (_logLevel < DEBUG_MODE) exitWith {}; + +private _hash = createHashMapFromArray _data; + +// Replace square brackets with round brackets to avoid parsing issues. +_message regexReplace ['(\[)', "("]; +_message regexReplace ['(\])', ")"]; + +private _json = [_hash] call CBA_fnc_encodeJSON; +_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/functions/util/fn_logMissionInfo.sqf b/framework/common/functions/fn_logMissionInfo.sqf similarity index 91% rename from functions/util/fn_logMissionInfo.sqf rename to framework/common/functions/fn_logMissionInfo.sqf index 6286476..ecba52c 100644 --- a/functions/util/fn_logMissionInfo.sqf +++ b/framework/common/functions/fn_logMissionInfo.sqf @@ -1,5 +1,8 @@ +#include "..\script_component.hpp" + [ - "init", + LEVEL_INFO, + QUOTE(COMPONENT), "MISSION INFO", [ ["serverName", serverName], @@ -20,4 +23,4 @@ ["LOGIC", playableSlotsNumber sideLogic] // 5 is LOGIC side ]] ] -] call milsim_fnc_log; \ No newline at end of file +] call FUNC(log); \ No newline at end of file diff --git a/framework/common/functions/fn_logSettingChanged.sqf b/framework/common/functions/fn_logSettingChanged.sqf new file mode 100644 index 0000000..c8a31e2 --- /dev/null +++ b/framework/common/functions/fn_logSettingChanged.sqf @@ -0,0 +1,16 @@ +#include "..\script_component.hpp" + +params [ + ["_settingName", "", [""]], + "_newValue" +]; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "SETTING CHANGED", + [ + ["setting", _settingName], + ["newValue", _value] + ] +] call EFUNC(common,log); \ No newline at end of file diff --git a/functions/util/fn_padString.sqf b/framework/common/functions/fn_padString.sqf similarity index 92% rename from functions/util/fn_padString.sqf rename to framework/common/functions/fn_padString.sqf index e5d3faf..f387ca5 100644 --- a/functions/util/fn_padString.sqf +++ b/framework/common/functions/fn_padString.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + params [ ["_text", "", [""]], ["_padSide", "left", ["left", "right"]], diff --git a/functions/util/fn_recurseSubclasses.sqf b/framework/common/functions/fn_recurseSubclasses.sqf similarity index 93% rename from functions/util/fn_recurseSubclasses.sqf rename to framework/common/functions/fn_recurseSubclasses.sqf index b4ba431..73cf984 100644 --- a/functions/util/fn_recurseSubclasses.sqf +++ b/framework/common/functions/fn_recurseSubclasses.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + params [ ["_cfg", configNull, [configNull]], ["_code", {}, [{}]] diff --git a/framework/common/script_component.hpp b/framework/common/script_component.hpp new file mode 100644 index 0000000..282e7ad --- /dev/null +++ b/framework/common/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT common +#define COMPONENT_BEAUTIFIED Common +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_addCBASettings.sqf b/framework/fbcb2_assets/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..efad170 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_addCBASettings.sqf @@ -0,0 +1,27 @@ +#include "..\script_component.hpp" + +//--------------------- +// Asset Diary and Markers Settings + +[ + QGVAR(setting_detectionRangeFromBase), // variable + "SLIDER", // type + ["Detection Range From Base", "The range from a base that assets will be detected"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [0, 1000, 750, 0, false], // [_min, _max, _default, _trailingDecimals, _isPercentage] + true, // global setting + { + params ["_value"]; + [ + QGVAR(setting_detectionRangeFromBase), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "CREATED SETTINGS", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_getCallsignFromClassname.sqf b/framework/fbcb2_assets/functions/fn_getCallsignFromClassname.sqf new file mode 100644 index 0000000..09a7d17 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_getCallsignFromClassname.sqf @@ -0,0 +1,15 @@ +#include "..\script_component.hpp" + +params [ + ["_className", "", [""]] +]; + +// Get the approved assets config +private _approvedAssetsCfg = call EFUNC(common,getApprovedAssetsCfg); +if (isNull _approvedAssetsCfg) exitWith {""}; + +// Get the asset definition +private _assetDef = (_approvedAssetsCfg >> _className); +if (isClass _assetDef) exitWith {getText(_assetDef >> "callsign")}; + +""; \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_getCurrentAssetsByBase.sqf b/framework/fbcb2_assets/functions/fn_getCurrentAssetsByBase.sqf new file mode 100644 index 0000000..a42bc1c --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_getCurrentAssetsByBase.sqf @@ -0,0 +1,6 @@ +#include "../script_component.hpp" + +// return each base with its assets +GVARMAIN(baseObjects) apply { + [_x, _x getVariable [QGVAR(assetsAtThisBase), []]] +}; \ No newline at end of file diff --git a/functions/fbcb2/assets/fn_getInventory.sqf b/framework/fbcb2_assets/functions/fn_getInventory.sqf similarity index 100% rename from functions/fbcb2/assets/fn_getInventory.sqf rename to framework/fbcb2_assets/functions/fn_getInventory.sqf diff --git a/functions/fbcb2/assets/fn_getMagsForWeapon.sqf b/framework/fbcb2_assets/functions/fn_getMagsForWeapon.sqf similarity index 100% rename from functions/fbcb2/assets/fn_getMagsForWeapon.sqf rename to framework/fbcb2_assets/functions/fn_getMagsForWeapon.sqf diff --git a/framework/fbcb2_assets/functions/fn_getStartingAndCurrentAssets.sqf b/framework/fbcb2_assets/functions/fn_getStartingAndCurrentAssets.sqf new file mode 100644 index 0000000..76daf37 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_getStartingAndCurrentAssets.sqf @@ -0,0 +1,17 @@ +#include "..\script_component.hpp" + +// get all starting assets at each base and combine to array +private _startingAssetsByBase = call FUNC(getStartingAssetsByBase); +private _startingAssets = []; +{ + _startingAssets append (_x#1); +} forEach _startingAssetsByBase; + +// get all current assets at each base and combine to array +private _assetsByBase = call FUNC(getCurrentAssetsByBase); +private _assets = []; +{ + _assets append (_x#1); +} forEach _assetsByBase; + +[_startingAssets, _assets]; \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_getStartingAssetsByBase.sqf b/framework/fbcb2_assets/functions/fn_getStartingAssetsByBase.sqf new file mode 100644 index 0000000..a0f082b --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_getStartingAssetsByBase.sqf @@ -0,0 +1,6 @@ +#include "../script_component.hpp" + +// return each base with its assets +GVARMAIN(baseObjects) apply { + [_x, _x getVariable [QGVAR(assetsStartedAtThisBase), []]] +}; \ No newline at end of file diff --git a/functions/fbcb2/assets/fn_getVehicleData.sqf b/framework/fbcb2_assets/functions/fn_getVehicleData.sqf similarity index 98% rename from functions/fbcb2/assets/fn_getVehicleData.sqf rename to framework/fbcb2_assets/functions/fn_getVehicleData.sqf index d7ba851..cf5d7b2 100644 --- a/functions/fbcb2/assets/fn_getVehicleData.sqf +++ b/framework/fbcb2_assets/functions/fn_getVehicleData.sqf @@ -39,7 +39,7 @@ private _pylons = getAllPylonsInfo _vic; /////////////////////////////////////////////// // WRITE TITLE /////////////////////////////////////////////// -_title pushBack format["%1", _dispName]; +_title pushBack format["%1", _dispName]; /////////////////////////////////////////////// // WRITE IMAGE diff --git a/functions/fbcb2/assets/fn_getWeaponry.sqf b/framework/fbcb2_assets/functions/fn_getWeaponry.sqf similarity index 100% rename from functions/fbcb2/assets/fn_getWeaponry.sqf rename to framework/fbcb2_assets/functions/fn_getWeaponry.sqf diff --git a/framework/fbcb2_assets/functions/fn_hintAllApprovedAssets.sqf b/framework/fbcb2_assets/functions/fn_hintAllApprovedAssets.sqf new file mode 100644 index 0000000..f419db3 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_hintAllApprovedAssets.sqf @@ -0,0 +1,94 @@ +#include "..\script_component.hpp" + +// get vehicles the mission started with at base locations +(call FUNC(getStartingAndCurrentAssets)) params [ + "_startingAssets", + "_currentAssets" +]; + +// get distinct classnames to group by +private _distinctStartingAssetsClassNames = []; +{ + _x params ["_netId", "_cfg"]; + private _className = configName _cfg; + _distinctStartingAssetsClassNames pushBackUnique _className; +} forEach _startingAssets; + +// get the approved assets config to identify callsigns +private _approvedAssetsCfg = call EFUNC(common,getApprovedAssetsCfg); +if (isNull _approvedAssetsCfg) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "No approved assets defined.", + [] + ] call EFUNC(common,log); + [ + "ERROR: No approved assets defined. See defines/ApprovedAssets.hpp" + ] call BIS_fnc_error; +}; + +_text = parseText "MESSAGE"; +_text = composeText [_text, lineBreak ]; + +_text = composeText [_text, parseText "AssetAvailable", lineBreak ]; + +{ + private _className = _x; + // only approved assets + if (!isClass (_approvedAssetsCfg >> _className)) then {continue}; + + private _callsign = [_className] call FUNC(getCallsignFromClassname); + + private _startingAssetsOfThisType = _startingAssets select { + // select all starting assets of this type + _x params ["_netId", "_cfg"]; + _className isEqualTo (configName _cfg); + }; + private _currentAssetsOfThisType = _currentAssets select { + _x params ["_netId", "_cfg"]; + private _object = _netId call BIS_fnc_objectFromNetId; + // objNull if deleted, then check classname and if alive + !isNull _object && { + _className isEqualTo (typeOf _object) && + alive _object + }; + }; + + (_startingAssetsOfThisType#0) params [ + "_assetNetId", + "_assetCfg" + ]; + + _assigned = count _startingAssetsOfThisType; + _available = count _currentAssetsOfThisType; + // count (getMarkerPos "respawn_west" nearEntities [ _asset, 2000] ); + + + _image = getText(_assetCfg >> "picture"); + + _name = getText(_assetCfg >> "displayName") select [0, 22]; + private _data = format[ + " %2%3 [ %4 ]", + _image, + _name, + _available, + _assigned + ]; + + // private _data = format[ + // " + // %2 + // %3 + // %4", + // _image, + // _name, + // _assigned, + // _available + // ]; + _text = composeText[ _text, parseText _data, lineBreak ]; + + +} foreach _distinctStartingAssetsClassNames; + +hint _text; \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_initClient.sqf b/framework/fbcb2_assets/functions/fn_initClient.sqf new file mode 100644 index 0000000..62dfbf3 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_initClient.sqf @@ -0,0 +1,28 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +call FUNC(updateAssetDiary); + +// once the server has published that assets have been gathered and distributed to bases (respawn modules), +// we can update the asset diary on our end using that data +[QGVAR(assetsGathered), { + [ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "Received gathered base asset data from server", + [] + ] call EFUNC(common,log); + + // update the asset diary with the data we've received + FUNC(updateAssetDiary); +}] call CBA_fnc_addEventHandlerArgs; + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_initServer.sqf b/framework/fbcb2_assets/functions/fn_initServer.sqf new file mode 100644 index 0000000..14dfcbd --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_initServer.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" + +if (!isServer) exitWith {}; + +// init asset stores at bases +[true] call FUNC(updateAssetsByBase); + +// starting 5 minutes after postInit, update asset stores every 5 minutes +[{ + [ + {[false] call FUNC(updateAssetsByBase);}, + 60*5 + ] call CBA_fnc_addPerFrameHandler; +}, 60*5] call CBA_fnc_waitAndExecute; + + +// add end mission EH +addMissionEventHandler ["MPEnded", { + // log the "current" asset counts to RPT + [false, true] call FUNC(updateAssetsByBase); +}]; + + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_isAssetInRangeOfBase.sqf b/framework/fbcb2_assets/functions/fn_isAssetInRangeOfBase.sqf new file mode 100644 index 0000000..e4c80df --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_isAssetInRangeOfBase.sqf @@ -0,0 +1,8 @@ +#include "..\script_component.hpp" + +params [["_asset", objNull, [objNull]]]; + +private _closestBase = [_asset] call EFUNC(common,getNearestBase); +if (isNull _closestBase) exitWith {false}; + +(_asset distance2D _closestBase) <= GVAR(setting_detectionRangeFromBase) \ No newline at end of file diff --git a/functions/fbcb2/assets/fn_removeAssetDiaryRecords.sqf b/framework/fbcb2_assets/functions/fn_removeAssetDiaryRecords.sqf similarity index 64% rename from functions/fbcb2/assets/fn_removeAssetDiaryRecords.sqf rename to framework/fbcb2_assets/functions/fn_removeAssetDiaryRecords.sqf index 400cd7d..98f41eb 100644 --- a/functions/fbcb2/assets/fn_removeAssetDiaryRecords.sqf +++ b/framework/fbcb2_assets/functions/fn_removeAssetDiaryRecords.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + if (!hasInterface) exitWith {}; { @@ -10,7 +12,7 @@ if (!hasInterface) exitWith {}; player removeDiaryRecord [_diarySubject, _diaryRecord]; } forEach _records; } forEach [ - milsim_fbcb2_subjectAssetsFixedWingID, - milsim_fbcb2_subjectAssetsRotaryID, - milsim_fbcb2_subjectAssetsGroundID + EGVAR(fbcb2_main,subjectAssetsFixedWingID), + EGVAR(fbcb2_main,subjectAssetsRotaryID), + EGVAR(fbcb2_main,subjectAssetsGroundID) ]; \ No newline at end of file diff --git a/functions/fbcb2/assets/markers/fn_removeMarkersOnMap.sqf b/framework/fbcb2_assets/functions/fn_removeMarkersOnMap.sqf similarity index 56% rename from functions/fbcb2/assets/markers/fn_removeMarkersOnMap.sqf rename to framework/fbcb2_assets/functions/fn_removeMarkersOnMap.sqf index ef6db27..ea6f78f 100644 --- a/functions/fbcb2/assets/markers/fn_removeMarkersOnMap.sqf +++ b/framework/fbcb2_assets/functions/fn_removeMarkersOnMap.sqf @@ -1,12 +1,11 @@ -private _baseMarkerStoreVar = "milsim_fbcb2_assets_baseMarkerStore"; -private _assetMarkerStoreVar = "milsim_fbcb2_assets_assetMarkerStore"; +#include "..\script_component.hpp" private _baseMarkerStore = localNamespace getVariable [ - _baseMarkerStoreVar, + QGVAR(baseMarkerStore), [] ]; private _assetMarkerStore = localNamespace getVariable [ - _assetMarkerStoreVar, + QGVAR(assetMarkerStore), [] ]; @@ -16,10 +15,10 @@ private _assetMarkerStore = localNamespace getVariable [ } forEach (_baseMarkerStore + _assetMarkerStore); localNamespace setVariable [ - _baseMarkerStoreVar, + QGVAR(baseMarkerStore), [] ]; localNamespace setVariable [ - _assetMarkerStoreVar, + QGVAR(assetMarkerStore), [] ]; diff --git a/functions/fbcb2/assets/markers/fn_showMarkersOnMap.sqf b/framework/fbcb2_assets/functions/fn_showMarkersOnMap.sqf similarity index 78% rename from functions/fbcb2/assets/markers/fn_showMarkersOnMap.sqf rename to framework/fbcb2_assets/functions/fn_showMarkersOnMap.sqf index c804d76..4ca1825 100644 --- a/functions/fbcb2/assets/markers/fn_showMarkersOnMap.sqf +++ b/framework/fbcb2_assets/functions/fn_showMarkersOnMap.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + params [ ["_className", "", [""]], ["_markerType", "hd_dot", [""]], @@ -12,11 +14,11 @@ if (count _markerColor isEqualTo 0) exitWith { ["No marker color provided!"] call BIS_fnc_error; }; if (count _assetObjects isEqualTo 0) exitWith { - ["No vehicles provided!"] call BIS_fnc_error; + ["No vehicles to draw markers for!"] call BIS_fnc_error; }; -private _baseMarkerStoreVar = "milsim_fbcb2_assets_baseMarkerStore"; -private _assetMarkerStoreVar = "milsim_fbcb2_assets_assetMarkerStore"; +private _baseMarkerStoreVar = QGVAR(baseMarkerStore); +private _assetMarkerStoreVar = QGVAR(assetMarkerStore); private _baseMarkerStore = localNamespace getVariable [ _baseMarkerStoreVar, @@ -35,15 +37,15 @@ if (not (count _baseMarkerStore > 0)) then { // create a circle marker with range as the detection range of assets _newMarker = createMarkerLocal [ - format["milsim_fbcb2_assets_base_marker_%1", _forEachIndex + 1], + format["%1_%2", QGVAR(baseCircleMarker), _forEachIndex + 1], getPosASL _base ]; _newMarker setMarkerTypeLocal "mil_dot"; _newMarker setMarkerColorLocal "ColorGreen"; _newMarker setMarkerShapeLocal "ELLIPSE"; _newMarker setMarkerSizeLocal [ - milsim_fbcb2_assets_setting_detectionRangeFromBase, - milsim_fbcb2_assets_setting_detectionRangeFromBase + GVAR(setting_detectionRangeFromBase), + GVAR(setting_detectionRangeFromBase) ]; _newMarker setMarkerAlphaLocal 0.5; _newMarker setMarkerTextLocal str(_forEachIndex + 1); @@ -55,19 +57,19 @@ if (not (count _baseMarkerStore > 0)) then { // create a flag marker at base position _newMarker = createMarkerLocal [ - format["milsim_fbcb2_assets_base_flag_marker_%1", _forEachIndex + 1], + format["%1_%2", QGVAR(baseFlagMarker), _forEachIndex + 1], getPosASL _base ]; _newMarker setMarkerTypeLocal "mil_flag"; _newMarker setMarkerColorLocal "ColorGreen"; _newMarker setMarkerSizeLocal [0.7, 0.7]; - _newMarker setMarkerTextLocal ([_base] call milsim_fnc_getNameOfBase); + _newMarker setMarkerTextLocal ([_base] call EFUNC(common,getNameOfBase)); _baseMarkerStore pushBack [ _base, _newMarker ]; - } forEach milsim_baseObjects; + } forEach GVARMAIN(baseObjects); localNamespace setVariable [_baseMarkerStoreVar, _baseMarkerStore]; }; @@ -85,9 +87,12 @@ private _start = (count _assetMarkerStore) + 1; > -1 ) then {continue}; + // check if the asset is within base detection range + if (not ([_asset] call FUNC(isAssetInRangeOfBase))) then {continue}; + // create a marker for the asset private _newMarker = createMarkerLocal [ - format["milsim_fbcb2_assets_marker_%1", _start], + format["%1_%2", QGVAR(assetMarker), _start], getPosASL _asset ]; _newMarker setMarkerAlphaLocal 1; diff --git a/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf b/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf new file mode 100644 index 0000000..72e516d --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf @@ -0,0 +1,261 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +// create diary records + +// remove any existing asset map markers +call FUNC(removeMarkersOnMap); + +// remove existing asset records +call FUNC(removeAssetDiaryRecords); + +(call FUNC(getStartingAndCurrentAssets)) params [ + "_startingAssets", + "_currentAssets" +]; + +// get distinct vehicle class names +private _distinctVehiclesClassNames = []; +{ + _x params ["_netId", "_cfg"]; + private _className = configName _cfg; + _distinctVehiclesClassNames pushBackUnique _className; +} forEach _startingAssets; + + +// for random color cycling +private _colorSelectionIndex = 0; +private _randomColors = [ + ["ColorRed", "#FF0000", "Red"], + ["ColorGreen", "#00FF00", "Green"], + ["ColorBlue", "#0000FF", "Blue"], + ["ColorYellow", "#FFFF00", "Yellow"], + ["ColorWhite", "#FFFFFF", "White"] +]; + +// ForEach unique vehicle class name, we'll find the first and gather its info +{ + private _className = _x; + private _vehicleCallsign = toUpper ( + [_className] call FUNC(getCallsignFromClassname) + ); + + // Get all starting assets of this type + private _startingAssetsOfThisType = _startingAssets select { + _x params ["_netId", "_cfg"]; + _className isEqualTo (configName _cfg); + }; + // Get all current assets of this type + private _currentAssetsOfThisType = _currentAssets select { + _x params ["_netId", "_cfg"]; + private _object = _netId call BIS_fnc_objectFromNetId; + // objNull if deleted, then check classname and if alive + !isNull _object && {_className isEqualTo (typeOf _object) && alive _object}; + }; + // This should never happen, but... + if (count _startingAssetsOfThisType isEqualTo 0) then {continue}; + + // Try to find a not null vehicle that can be processed + private _exampleVehicleToProcess = objNull; + private _assetCfg = configNull; + + private _exampleVehicleToProcessIndex = _startingAssetsOfThisType findIf { + _x params ["_netId", "_cfg"]; + !isNull (_netId call BIS_fnc_objectFromNetId); + }; + // If found, get the data + if (_exampleVehicleToProcessIndex > -1) then { + private _exampleData = _startingAssetsOfThisType select _exampleVehicleToProcessIndex; + _assetNetId = _exampleData#0; + _assetCfg = _exampleData#1; + _exampleVehicleToProcess = _assetNetId call BIS_fnc_objectFromNetId; + } else { + // otherwise, we only have the config to work with + private _exampleData = _startingAssetsOfThisType#0; + _assetCfg = _exampleData#1; + }; + + private _parentClassNames = [_assetCfg, true] call BIS_fnc_returnParents; + + + + // Process the vehicle for extended info + // Exclusion list for display names + if ( + [_assetCfg] call BIS_fnc_displayName + in ["Helicopter"] + ) then {continue}; + + // Get the vehicle data + private _processed = [configNull, "", []]; + if (!isNull _exampleVehicleToProcess) then { + _processed = [_exampleVehicleToProcess] call FUNC(getVehicleData); + }; + _processed params ["_processedVehicleCfg", "_displayName", "_diaryTextSections"]; + _diaryTextSections params [ + ["_title", "", [""]], + ["_image", "", [""]], + ["_info", "", [""]], + ["_capacity", "", [""]] + // ["_weapons", "", [""]], + // ["_pylonWeapons", "", [""]], + // ["_inventory", "", [""]] + ]; + + // Get what we can from the vehicle cfg + + // Create the diary record + private _recordText = []; + // Add the title and image + if (count _title isEqualTo 0) then { + _title = format["%1", [_assetCfg] call BIS_fnc_displayName]; + }; + _recordText pushBack format[ + "%1", + _title + ]; + if (count _image isEqualTo 0) then { + _image = format["", getText(_assetCfg >> 'editorPreview')]; + }; + _recordText pushBack _image; + _recordText pushBack "
"; + _recordText pushBack format[ + "CALLSIGN: %1", + _vehicleCallsign + ]; + _recordText pushBack format[ + "COUNT STARTED: %1", + count _startingAssetsOfThisType + ]; + _recordText pushBack format[ + "COUNT ACTIVE: %1", + count _currentAssetsOfThisType + ]; + + // Here, we'll create a link to show markers on the map for all vehicles of this kind + // get 'picture' for record + private _icon = getText(_assetCfg >> "picture"); + // determine marker type + private _markerType = "mil_dot"; + switch (true) do { + case ("Helicopter" in _parentClassNames): { + _markerType = "loc_heli"; + }; + case ("Air" in _parentClassNames): { + _markerType = "loc_plane"; + }; + case ("Ship" in _parentClassNames): { + _markerType = "loc_boat"; + }; + case ("Car" in _parentClassNames): { + _markerType = "loc_car"; + }; + default { + _markerType = "loc_truck"; + }; + }; + + private "_randomColor"; + if (_colorSelectionIndex < count _randomColors) then { + _randomColor = _randomColors select _colorSelectionIndex; + INC(_colorSelectionIndex); + } else { + _colorSelectionIndex = 0; + _randomColor = _randomColors select _colorSelectionIndex; + }; + + // Link to show markers + private _showMarkersText = format[ + "SHOW MARKERS for vehicles at base (in %6)", + _className, + _markerType, + _randomColor#0, + (_currentAssetsOfThisType apply { + _x params ["_netId", "_cfg"]; + _netId; + }), + QFUNC(showMarkersOnMap), + format["%2", _randomColor#1, _randomColor#2] + ]; + _recordText pushBack _showMarkersText; + + // Link to hide markers + _recordText pushBack format[ + "REMOVE ALL MARKERS showing asset positions", + QFUNC(removeMarkersOnMap) + ]; + + // Link to update asset diary entries + _recordText pushBack format[ + "UPDATE ENTRIES for all assets", + QFUNC(updateAssetDiary) + ]; + + // link to display hint with all assets + _recordText pushBack format[ + "SHOW APPROVED ASSET COUNTS via hint", + QFUNC(hintAllApprovedAssets) + ]; + + _recordText pushBack format[ + "%1", + "Notes:
+ - Markers are only displayed on your local machine.
+ - The REMOVE ALL option will remove all assets' markers from the map.
+ - UPDATE ENTRIES will update the asset diary with the latest information.
+ - Markers will only be displayed for assets that are within a certain distance of a base." + ]; + + + + // Add info and capacity sections - exclude if no living examples were found + if (count _info > 0) then { + _recordText pushBack _info; + }; + if (count _capacity > 0) then { + _recordText pushBack _capacity; + }; + + + private _subjectID = ""; + switch (true) do { + case ("Helicopter" in _parentClassNames): { + _subjectID = EGVAR(fbcb2_main,subjectAssetsRotaryID); + }; + case ("Air" in _parentClassNames): { + _subjectID = EGVAR(fbcb2_main,subjectAssetsFixedWingID); + }; + default { + _subjectID = EGVAR(fbcb2_main,subjectAssetsGroundID); + }; + }; + + [ + _subjectID, + format[ + "[%1/%2] %3", + count _currentAssetsOfThisType, + count _startingAssetsOfThisType, + (_assetCfg) call BIS_fnc_displayName + ], + _recordText joinString "
", + _icon + ] call EFUNC(fbcb2_main,createOrUpdateDiaryRecord); + +// "\A3\ui_f\data\igui\cfg\simpleTasks\types\car_ca.paa" +} forEach _distinctVehiclesClassNames; + +// log to RPT +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "UPDATED ASSET DIARY", + [ + ["startingAssetCount", count _startingAssets], + ["startingAssetCountDistinct", count _distinctVehiclesClassNames], + ["currentassetCount", count _currentAssets] + ] +] call EFUNC(common,log); + +true; \ No newline at end of file diff --git a/framework/fbcb2_assets/functions/fn_updateAssetsByBase.sqf b/framework/fbcb2_assets/functions/fn_updateAssetsByBase.sqf new file mode 100644 index 0000000..dc0e2e7 --- /dev/null +++ b/framework/fbcb2_assets/functions/fn_updateAssetsByBase.sqf @@ -0,0 +1,141 @@ +#include "..\script_component.hpp" + +params [ + ["_isInit", false, [false]], + ["_logCurrentAssets", false, [false]] +]; + +if (!isServer) exitWith {}; + +GVARMAIN(baseObjects) = allMissionObjects "ModuleRespawnPosition_F"; + +// Get all approved assets on map, find the closest base +// Then determine if it's within range +// If it is, add it to the base's assets list +// This is to ensure bases with overlapping detection range don't have duplicate assets +private _allVehicles = vehicles; +private _allSaved = []; + +private _assetsStartedAtThisBaseVar = QGVAR(assetsStartedAtThisBase); +private _assetsAtThisBaseVar = QGVAR(assetsAtThisBase); + +private _approvedAssetsCfg = call EFUNC(common,getApprovedAssetsCfg); +if (isNull _approvedAssetsCfg) exitWith {}; + +private _currentBaseAssetsGathered = GVARMAIN(baseObjects) apply {[_x, []]};; + +{ + private _className = configName _x; + private _callsign = getText(_x >> "callsign"); + private _found = _allVehicles select { typeOf _x == _className }; + { + private _asset = _x; + + // ignore assets beyond the range of bases + if (not ([_asset] call FUNC(isAssetInRangeOfBase))) then {continue}; + + + // add to base's assets list + private _closestBase = [_asset] call EFUNC(common,getNearestBase); + private _closestBaseCurrentAssets = (_currentBaseAssetsGathered select { _x select 0 isEqualTo _closestBase })#0#1; + _closestBaseCurrentAssets pushBackUnique [ + _asset call BIS_fnc_netId, + configOf _asset + ]; + } forEach _found; +} forEach (_approvedAssetsCfg call BIS_fnc_returnChildren); + +// Add all ground vehicles (LandVehicle) +{ + private _asset = _x; + + // ignore assets beyond the range of bases + if (not ([_asset] call FUNC(isAssetInRangeOfBase))) then {continue}; + + // add to base's assets list + private _closestBase = [_asset] call EFUNC(common,getNearestBase); + private _closestBaseCurrentAssets = (_currentBaseAssetsGathered select { _x select 0 isEqualTo _closestBase })#0#1; + _closestBaseCurrentAssets pushBackUnique [ + _asset call BIS_fnc_netId, + configOf _asset + ]; +} forEach (_allVehicles select { _x isKindOf "LandVehicle" }); + +//////////////////////////////////////////////////////////////////////// +// publish updated base variables +//////////////////////////////////////////////////////////////////////// +{ + private _base = _x; + + private _thisBaseCurrentAssets = (_currentBaseAssetsGathered select { _x select 0 isEqualTo _base })#0#1; + _base setVariable [_assetsAtThisBaseVar, _thisBaseCurrentAssets, true]; + + if (_isInit) then { + _base setVariable [_assetsStartedAtThisBaseVar, _thisBaseCurrentAssets, true]; + }; +} forEach GVARMAIN(baseObjects); + +// send a CBA event to let other scripts know that assets have been gathered +[{[QGVAR(assetsGathered)] call CBA_fnc_globalEvent;}, 2] call CBA_fnc_waitAndExecute; + +//////////////////////////////////////////////////////////////////////// +// log starting assets if init +// log current assets if requested (for end of mission counts) +//////////////////////////////////////////////////////////////////////// +if !(_isInit || _logCurrentAssets) exitWith {}; + +{ + private _base = _x; + + // get current assets + private _baseAssets = (_currentBaseAssetsGathered select { _x select 0 isEqualTo _base })#0#1; + + // prepare key value for logging + private _baseAssetsHashesPrep = _baseAssets apply { + _x params ["_netId", "_cfg"]; + [ + ["callsign", [configName _cfg] call FUNC(getCallsignFromClassname)], + ["className", configName _cfg], + ["displayName", [_cfg] call BIS_fnc_displayName] + ]; + }; + + _baseAssetsHashesPrep = _baseAssetsHashesPrep call BIS_fnc_consolidateArray; + + private _baseAssetsHashes = []; + { + private _out = createHashMapFromArray (_x#0); + _out set ["count", _x#1]; + _baseAssetsHashes pushBack _out; + } forEach _baseAssetsHashesPrep; + + // if logging current assets + if (_logCurrentAssets) then { + { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "CURRENT ASSETS", + [ + ["baseName", [[_base] call EFUNC(common,getNameOfBase)]], + ["asset", _x] + ] + ] call EFUNC(common,log); + } forEach _baseAssetsHashes; + }; + + // if init, log starting assets + if (_isInit) then { + { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "STARTING ASSETS", + [ + ["baseName", [[_base] call EFUNC(common,getNameOfBase)]], + ["asset", _x] + ] + ] call EFUNC(common,log); + } forEach _baseAssetsHashes; + }; +} forEach GVARMAIN(baseObjects); \ No newline at end of file diff --git a/framework/fbcb2_assets/script_component.hpp b/framework/fbcb2_assets/script_component.hpp new file mode 100644 index 0000000..c5a24ae --- /dev/null +++ b/framework/fbcb2_assets/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT fbcb2_assets +#define COMPONENT_BEAUTIFIED FBCB2 - Assets +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf b/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf new file mode 100644 index 0000000..3cc7dda --- /dev/null +++ b/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf @@ -0,0 +1,112 @@ +#include "..\script_component.hpp" + +private _recordTitle = "ENVIRONMENTAL CONDITIONS"; + +private _text = [ + format[ + "%4", + GVAR(recordTitleSize), + GVAR(recordTitleColor), + GVAR(recordTitleFont), + _recordTitle + ] +]; + +private _sunriseColor = "#4A86E8"; +private _sunsetColor = "#6AA84F"; +private _whiteColor = "#FFFFFF"; + +private _sunTimes = date call BIS_fnc_sunriseSunsetTime; +private _nearestBase = [player] call EFUNC(common,getNearestBase); + +if (isNull _nearestBase) exitWith { + [ + LEVEL_WARNING, + QUOTE(COMPONENT), + "WARNING: No bases found nearby to report weather!", + [player, [ + ["position", getPos player] + ]] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); + ["WARNING: No bases found nearby to report weather!"] call BIS_fnc_error; +}; + +_text pushBack format[ + "Current conditions at nearest weather station: %2
", + GVAR(recordTextBodySize), + [_nearestBase] call EFUNC(common,getNameOfBase) +]; + +private _weatherData = []; + +if (isClass (configFile >> "CfgPatches" >> "ace_weather")) then { + // get ace_weather data + private _barometricPressure = ((getPosASL _nearestBase)#2) call ace_weather_fnc_calculateBarometricPressure; + private _relHumidity = missionNamespace getVariable ["ace_weather_currentHumidity", 0.5]; + private _temperature = ((getPosASL _nearestBase)#2) call ace_weather_fnc_calculateTemperatureAtHeight; + private _dewPoint = [_temperature, _relHumidity] call ace_weather_fnc_calculateDewPoint; + private _windSpeed = [getPosASL _nearestBase, false, false, false] call ace_weather_fnc_calculateWindSpeed; + private _windChill = [_temperature, _windSpeed] call ace_weather_fnc_calculateWindChill; + private _heatIndex = [_temperature, _relHumidity] call ace_weather_fnc_calculateHeatIndex; + + toFixed 2; + private _aceData = [ + ["Temperature", format["%1°C / %2°F", _temperature, _temperature * (9/5) + 32]], + ["Wind Chill", format["%1°C / %2°F", _windChill, _windChill * (9/5) + 32]], + ["Heat Index", format["%1°C / %2°F", _heatIndex, _heatIndex * (9/5) + 32]], + ["Dew Point", format["%1°C / %2°F", _dewPoint, _dewPoint * (9/5) + 32]], + ["Wind Speed", format["%1mph / %2kph / %3kts", _windSpeed * 2.237, _windSpeed * 3.6, _windSpeed * 1.944]], + ["Wind Direction", ""], + ["Barometric Pressure", format["%1 hPA", _barometricPressure]], + ["Relative Humidity", format["%1%2", _relHumidity * 100, "%"]], + ["Fog Cover", ""], + ["Rain", ""], + ["Overcast", ""] + ]; + toFixed -1; + + { + _x params ["_name", "_value"]; + [_weatherData, _name, _value] call BIS_fnc_setToPairs; + } forEach _aceData; +}; + +// always add built-in weather +toFixed 2; +private _vanillaData = [ + ["Temperature", format["%1°C", (ambientTemperature)#0]], + ["Fog Cover", format["%1%2", fog * 100, "%"]], + ["Overcast", format["%1%2", overcast * 100, "%"]], + ["Rain", format["%1%2", rain * 100, "%"]], + ["Wind Speed", format["%1m/s", windStr]], + ["Wind Direction", format["%1°", windDir]] +]; +toFixed -1; + +_vanillaData pushBack ["Sunrise", ([_sunTimes select 0, "HH:MM"] call BIS_fnc_timeToString)]; +_vanillaData pushBack ["Sunset", ([_sunTimes select 1, "HH:MM"] call BIS_fnc_timeToString)]; + +// override or set keys for vanilla data into weather data +{ + _x params ["_name", "_value"]; + [_weatherData, _name, _value] call BIS_fnc_setToPairs; +} forEach _vanillaData; + +// write lines +{ + _x params ["_name", "_value"]; + _text pushBack format[ + "%2%3", + GVAR(recordTextBodySize)-4, + [_name, "right", " ", 23] call EFUNC(common,padString), + _value + ]; +} forEach _weatherData; + +_text = _text joinString "
"; + +[ + GVAR(subjectIntelID), + _recordTitle, + _text +] call FUNC(createOrUpdateDiaryRecord); \ No newline at end of file diff --git a/functions/fbcb2/fn_processFBCB2RadioFrequencies.sqf b/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf similarity index 56% rename from functions/fbcb2/fn_processFBCB2RadioFrequencies.sqf rename to framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf index 69270a8..9f5cccb 100644 --- a/functions/fbcb2/fn_processFBCB2RadioFrequencies.sqf +++ b/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf @@ -1,11 +1,32 @@ // updated 2024-02-01 by IndigoFox // now reads from the battalion config structure to generate the diary entries +#include "../script_component.hpp" + //////////////////////////////////////// // Get info from missionConfigFile //////////////////////////////////////// -private _battalionInfoCfg = call milsim_fnc_getBattalionCfg; +private _battalionInfoCfg = call EFUNC(common,getBattalionCfg); +if (isNull _battalionInfoCfg) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "Null Battalion Config", + [] + ] call EFUNC(common,log); + ["Null Battalion Config"] call BIS_fnc_error; +}; + private _battalionElementCfgs = [_battalionInfoCfg >> "Command"] call BIS_fnc_returnChildren; +if (count _battalionElementCfgs == 0) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "ERROR: No battalion elements found. Check that the battalion config is correctly structured. See defines/BattalionInfo.hpp and framework/util/functions/getBattalionCfg.sqf.", + [] + ] call EFUNC(common,log); + ["ERROR: No battalion elements found. Check that the battalion config is correctly structured. See defines/BattalionInfo.hpp and framework/util/functions/getBattalionCfg.sqf."] call BIS_fnc_error; +}; //////////////////////////////////////// // Define formatting constants @@ -29,22 +50,28 @@ private _FREQ_TEXT_COLOR = "#CCCCCC"; reverse _battalionElementCfgs; { - // recursively generate diary text for all child elements of battalion-level elements - private _diaryTitleText = [_x, true] call milsim_fnc_generateElementFrequencyRecordText; [ - milsim_fbcb2_subjectFrequenciesID, + LEVEL_TRACE, + QUOTE(COMPONENT), + format["Processing battalion element %1", configName _x], + [] + ] call EFUNC(common,log); + // recursively generate diary text for all child elements of battalion-level elements + private _diaryTitleText = [_x, true] call FUNC(generateElementFrequencyRecordText); + [ + GVAR(subjectFrequenciesID), _diaryTitleText#0, _diaryTitleText#1 - ] call milsim_fnc_createOrUpdateDiaryRecord; + ] call FUNC(createOrUpdateDiaryRecord); } forEach _battalionElementCfgs; // add the battalion command to the top of the list // don't process child elements -private _diaryTitleText = [_battalionInfoCfg >> "Command", false] call milsim_fnc_generateElementFrequencyRecordText; +private _diaryTitleText = [_battalionInfoCfg >> "Command", false] call FUNC(generateElementFrequencyRecordText); [ - milsim_fbcb2_subjectFrequenciesID, + GVAR(subjectFrequenciesID), _diaryTitleText#0, _diaryTitleText#1 -] call milsim_fnc_createOrUpdateDiaryRecord; +] call FUNC(createOrUpdateDiaryRecord); true; \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf b/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf new file mode 100644 index 0000000..078c72f --- /dev/null +++ b/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf @@ -0,0 +1,59 @@ +#include "../script_component.hpp" + +private _recordTitle = "SIGNAL COLORS"; + +private _text = [ + // Title + format[ + "%4", + GVAR(recordTitleSize), + GVAR(recordTitleColor), + GVAR(recordTitleFont), + _recordTitle + ] +]; + +private _signalColorDefs = (missionConfigFile >> "SignalColors") call BIS_fnc_returnChildren; + +{ + private _cfg = _x; + private _color = getText(_cfg >> "hexCode"); + private _name = getText(_cfg >> "name"); + private _usage = getText(_cfg >> "usage"); + private _itemExamples = getArray(_cfg >> "itemExamples"); + + private _thisText = []; + + _thisText pushBack format[ + "%3 - %4", + GVAR(recordTextHeaderSize), + _color, + _name, + _usage + ]; + + private _imagesLine = []; + + { + private _itemClassname = _x; + private _itemCfg = [_itemClassname] call CBA_fnc_getItemConfig; + private _itemName = getText(_itemCfg >> "displayName"); + private _itemImage = getText(_itemCfg >> "picture"); + _imagesLine pushBack format[ + "", + _itemImage, + _itemName + ]; + } forEach _itemExamples; + + _thisText pushBack (_imagesLine joinString " "); + _text pushBack (_thisText joinString "
"); +} forEach _signalColorDefs; + +_text = _text joinString "

"; + +[ + GVAR(subjectIntelID), + _recordTitle, + _text +] call FUNC(createOrUpdateDiaryRecord); \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_initClient.sqf b/framework/fbcb2_main/functions/fn_initClient.sqf new file mode 100644 index 0000000..b2f717b --- /dev/null +++ b/framework/fbcb2_main/functions/fn_initClient.sqf @@ -0,0 +1,54 @@ +#include "../script_component.hpp" + +if ( !hasInterface ) exitWith {}; + +GVAR(recordTitleColor) = "#ff6666"; +GVAR(recordTitleFont) = "PuristaMedium"; +GVAR(recordTitleSize) = 20; + +GVAR(recordTextHeaderSize) = 16; +GVAR(recordTextBodySize) = 14; + +GVAR(subjectStatusID) = "FBCB2_Status"; +GVAR(subjectIntelID) = "FBCB2_Intel"; +GVAR(subjectMessagesID) = "FBCB2_Messages"; +GVAR(subjectFrequenciesID) = "FBCB2_Frequencies"; +GVAR(subjectAssetsFixedWingID) = "FBCB2_Assets_FixedWing"; +GVAR(subjectAssetsRotaryID) = "FBCB2_Assets_Rotary"; +GVAR(subjectAssetsGroundID) = "FBCB2_Assets_Ground"; + +player createDiarySubject[GVAR(subjectStatusID), "FBCB2 Status"]; +player createDiarySubject[GVAR(subjectMessagesID), "FBCB2 Messages"]; +player createDiarySubject[GVAR(subjectIntelID), "FBCB2 Intel"]; +player createDiarySubject[GVAR(subjectFrequenciesID), "FBCB2 Frequencies"]; +player createDiarySubject[GVAR(subjectAssetsFixedWingID), "FBCB2 Planes"]; +player createDiarySubject[GVAR(subjectAssetsRotaryID), "FBCB2 Helicopters"]; +player createDiarySubject[GVAR(subjectAssetsGroundID), "FBCB2 Ground"]; + +// store records in format: +// [subject, [ +// [title, diaryRecord] +// ]] +GVAR(diaryRecords) = createHashMap; + +// run main inits +[] call FUNC(addFrequenciesRecord); +[] call FUNC(addSignalColorsRecord); +[] call FUNC(addEnvironmentRecord); + +// starting 5 minutes after postInit, update weather diary record every 5 minutes +[{ + [ + {call FUNC(addEnvironmentRecord);}, + 60*5 + ] call CBA_fnc_addPerFrameHandler; +}, 60*5] call CBA_fnc_waitAndExecute; + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/fbcb2_main/script_component.hpp b/framework/fbcb2_main/script_component.hpp new file mode 100644 index 0000000..ef7f377 --- /dev/null +++ b/framework/fbcb2_main/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT fbcb2_main +#define COMPONENT_BEAUTIFIED FBCB2 - Main +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf b/framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf new file mode 100644 index 0000000..7f04abb --- /dev/null +++ b/framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf @@ -0,0 +1,49 @@ +#include "../script_component.hpp" + +if (!hasInterface) exitWith {}; + +params [ + ["_subjectID", GVAR(subjectStatusID), [""]], + ["_recordTitle", "", [""]], + ["_recordText", "", [""]], + ["_recordIcon", "", [""]] +]; + +// Check if already created +private _subjectRecords = GVAR(diaryRecords) getOrDefault [_subjectID, createHashMap, true]; +private _existingRecord = _subjectRecords getOrDefault [_recordTitle, diaryRecordNull, true]; + +if (!isNull _existingRecord) then { + player setDiaryRecordText [[_subjectID, _existingRecord], [_recordTitle, _recordText, _recordIcon]]; + + [ + LEVEL_DEBUG, + QUOTE(COMPONENT), + format ["Updated diary record: %1", _recordTitle], + [ + ["subjectID", _subjectID], + ["recordTitle", _recordTitle] + ] + ] call EFUNC(common,log); +} else { + private _new = player createDiaryRecord [ + _subjectID, + [ + _recordTitle, + _recordText, + _recordIcon + ] + ]; + _subjectRecords set [_recordTitle, _new]; + GVAR(diaryRecords) set [_subjectID, _subjectRecords]; + + [ + LEVEL_DEBUG, + QUOTE(COMPONENT), + format ["Created diary record: %1", _recordTitle], + [ + ["subjectID", _subjectID], + ["recordTitle", _recordTitle] + ] + ] call EFUNC(common,log); +}; \ No newline at end of file diff --git a/functions/fbcb2/radioFrequencies/fn_formatRadioElementForDiary.sqf b/framework/fbcb2_main/util/fn_formatRadioElementForDiary.sqf similarity index 91% rename from functions/fbcb2/radioFrequencies/fn_formatRadioElementForDiary.sqf rename to framework/fbcb2_main/util/fn_formatRadioElementForDiary.sqf index 8a4bdc0..055ea6e 100644 --- a/functions/fbcb2/radioFrequencies/fn_formatRadioElementForDiary.sqf +++ b/framework/fbcb2_main/util/fn_formatRadioElementForDiary.sqf @@ -1,4 +1,6 @@ // called from milsim_fnc_processFBCB2RadioFrequencies +#include "../script_component.hpp" + params ["_cfg", ["_indentCount", 1, [5]]]; ////////////////////////////////////////////////////// @@ -62,8 +64,8 @@ _freqLeadingSpace = _freqLeadingSpace joinString ""; _ELEMENT_FREQ_SIZE, _ELEMENT_FREQ_FONT, _FREQ_TEXT_COLOR, - [_role, "right", " ", _FREQ_PAD_LENGTH] call milsim_fnc_padString, - [_srStr, "right", " ", _FREQ_PAD_LENGTH] call milsim_fnc_padString, + [_role, "right", " ", _FREQ_PAD_LENGTH] call EFUNC(common,padString), + [_srStr, "right", " ", _FREQ_PAD_LENGTH] call EFUNC(common,padString), _lrStr ]; } forEach (getArray (_cfg >> "frequencies")); diff --git a/functions/fbcb2/radioFrequencies/fn_generateElementFrequencyRecordText.sqf b/framework/fbcb2_main/util/fn_generateElementFrequencyRecordText.sqf similarity index 76% rename from functions/fbcb2/radioFrequencies/fn_generateElementFrequencyRecordText.sqf rename to framework/fbcb2_main/util/fn_generateElementFrequencyRecordText.sqf index 113ede7..b329279 100644 --- a/functions/fbcb2/radioFrequencies/fn_generateElementFrequencyRecordText.sqf +++ b/framework/fbcb2_main/util/fn_generateElementFrequencyRecordText.sqf @@ -1,5 +1,8 @@ // called from milsim_fnc_processFBCB2RadioFrequencies ONLY // this function is called recursively to process all child elements of a battalion element in missionConfigFile + +#include "../script_component.hpp" + params [ ["_elementCfg", configNull, [configNull]], ["_shouldProcessChildCfgs", true] @@ -40,9 +43,9 @@ _freqLeadingSpace = _freqLeadingSpace joinString ""; private _headers = [ format[ "%4", - milsim_fbcb2_recordTitleSize, - milsim_fbcb2_recordTitleColor, - milsim_fbcb2_recordTitleFont, + GVAR(recordTitleSize), + GVAR(recordTitleColor), + GVAR(recordTitleFont), _recordTitle ], format[ @@ -51,8 +54,8 @@ private _headers = [ _ELEMENT_FREQ_SIZE, _ELEMENT_FREQ_FONT, _FREQ_TEXT_COLOR, - ["ROLE", "right", " ", _FREQ_PAD_LENGTH] call milsim_fnc_padString, - ["SR", "right", " ", _FREQ_PAD_LENGTH] call milsim_fnc_padString, + ["ROLE", "right", " ", _FREQ_PAD_LENGTH] call EFUNC(common,padString), + ["SR", "right", " ", _FREQ_PAD_LENGTH] call EFUNC(common,padString), "LR" ] ]; @@ -65,16 +68,30 @@ private _allText = []; // get all child elements recursively and format them if (_shouldProcessChildCfgs) then { + [ + LEVEL_TRACE, + QUOTE(COMPONENT), + "Processing child elements for battalion element %1", + [] + ] call EFUNC(common,log); + [_battalionElement, { params ["_cfg", "_recurseCounter"]; // add config - private _lines = [_cfg, _recurseCounter+1] call milsim_fnc_formatRadioElementForDiary; + private _lines = [_cfg, _recurseCounter+1] call FUNC(formatRadioElementForDiary); // private _lines = [_cfg, _indentCount] call t; _allText pushBack (_lines joinString "
"); - }] call milsim_fnc_recurseSubclasses; + }] call EFUNC(common,recurseSubclasses); } else { + [ + LEVEL_TRACE, + QUOTE(COMPONENT), + "Skipping processing of child elements for battalion element %1", + [] + ] call EFUNC(common,log); + // or if the param was false, just add the battalion element - private _lines = [_battalionElement, 1] call milsim_fnc_formatRadioElementForDiary; + private _lines = [_battalionElement, 1] call FUNC(formatRadioElementForDiary); // private _lines = [_cfg, _indentCount] call t; _allText pushBack (_lines joinString "
"); }; diff --git a/framework/init/functions/fn_addAARChatHandler.sqf b/framework/init/functions/fn_addAARChatHandler.sqf new file mode 100644 index 0000000..10f3979 --- /dev/null +++ b/framework/init/functions/fn_addAARChatHandler.sqf @@ -0,0 +1,18 @@ +#include "..\script_component.hpp" + +[ + "saveaar", + { + [] remoteExec["ocap_fnc_exportData", 2]; + }, + "admin" +] call CBA_fnc_registerChatCommand; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "OCAP chat handler registered", + [player] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); + +nil; \ No newline at end of file diff --git a/functions/settings/fn_addRespawnChatHandler.sqf b/framework/init/functions/fn_addRespawnChatHandler.sqf similarity index 53% rename from functions/settings/fn_addRespawnChatHandler.sqf rename to framework/init/functions/fn_addRespawnChatHandler.sqf index fed6acb..b2d0007 100644 --- a/functions/settings/fn_addRespawnChatHandler.sqf +++ b/framework/init/functions/fn_addRespawnChatHandler.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + [ "respawn", { @@ -6,10 +8,11 @@ // log to server RPT [ - "init", + LEVEL_INFO, + QUOTE(COMPONENT), "CHAT COMMAND RESPAWN", - [player] call milsim_fnc_addPlayerInfoToArray - ] remoteExec ["milsim_fnc_log", 2]; + [player] call EFUNC(common,addPlayerInfoToArray) + ] remoteExec [QEFUNC(common,log), 2]; // systemChat to all remote machines format["%1 claims they were glitched and respawned (%2)", name player, netID player] remoteExec["systemChat", -_clientID]; @@ -18,6 +21,11 @@ [clientOwner] ] call CBA_fnc_registerChatCommand; -diag_log text "[MILSIM] (settings) respawn chat handler registered"; +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "Respawn chat handler registered", + [player] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); nil; \ No newline at end of file diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf new file mode 100644 index 0000000..a7d106a --- /dev/null +++ b/framework/init/functions/fn_initClient.sqf @@ -0,0 +1,34 @@ +#include "..\script_component.hpp" + +if ( !hasInterface ) exitWith {}; + +["milsim_logText", { + params [["_strArray", [""], [[]]]]; + { + diag_log text _x; + } forEach _strArray; +}] call CBA_fnc_addEventHandler; + +// make sure the server has finished init +waitUntil {!isNil QGVARMAIN(complete)}; + +["InitializePlayer", [player, true]] call BIS_fnc_dynamicGroups; + + +// initialize other modules +call EFUNC(reinsert,initClient); +call EFUNC(resupply,initClient); +call EFUNC(triageIcons,initClient); +call EFUNC(vehicleFlags,initClient); +call EFUNC(fbcb2_main,initClient); +call EFUNC(fbcb2_assets,initClient); + + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); + +nil; \ No newline at end of file diff --git a/framework/init/functions/fn_initServer.sqf b/framework/init/functions/fn_initServer.sqf new file mode 100644 index 0000000..84e2666 --- /dev/null +++ b/framework/init/functions/fn_initServer.sqf @@ -0,0 +1,42 @@ +#include "..\script_component.hpp" + +if (!isServer) exitWith {}; + +// array of all respawn modules in the mission representing "bases" +GVARMAIN(baseObjects) = allMissionObjects "ModuleRespawnPosition_F"; +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); +call EFUNC(reinsert,initServer); + +// declare init complete to other modules +missionNamespace setVariable [QGVARMAIN(complete), true, true]; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + format["%1: version %2", QGVARMAIN(complete), QUOTE(VERSION_STR)], + [["version", QUOTE(VERSION_STR)]] +] call EFUNC(common,log); + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/init/functions/fn_setDefaults.sqf b/framework/init/functions/fn_setDefaults.sqf new file mode 100644 index 0000000..45a18d3 --- /dev/null +++ b/framework/init/functions/fn_setDefaults.sqf @@ -0,0 +1,34 @@ +#include "..\script_component.hpp" + +enableSaving[false, false]; + +enableRadio false; +enableSentences false; + +missionNamespace setVariable ["ACE_maxWeightDrag", 2400]; +missionNamespace setVariable ["ACE_maxWeightCarry", 1800]; + +if(isClass(configfile >> "CfgPatches" >> "rhs_main")) then { + rhs_vehicleRadioChatter = 0; +}; + +waitUntil {time > 0}; + +enableEnvironment[false, true]; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "Defaults set", + [ + ["enableSaving", [false, false]], + ["enableRadio", false], + ["enableSentences", false], + ["ACE_maxWeightDrag", 2400], + ["ACE_maxWeightCarry", 1800], + ["rhs_vehicleRadioChatter", 0], + ["enableEnvironment", [false, true]] + ] +] call EFUNC(common,log); + +nil; \ No newline at end of file diff --git a/framework/init/script_component.hpp b/framework/init/script_component.hpp new file mode 100644 index 0000000..fedab82 --- /dev/null +++ b/framework/init/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT init +#define COMPONENT_BEAUTIFIED Init +#include "../script_mod.hpp" \ No newline at end of file diff --git a/functions/map/fn_copyMapFromPlayer.sqf b/framework/map/fn_copyMapFromPlayer.sqf similarity index 100% rename from functions/map/fn_copyMapFromPlayer.sqf rename to framework/map/fn_copyMapFromPlayer.sqf diff --git a/functions/map/fn_getPlayerMapMarkers.sqf b/framework/map/fn_getPlayerMapMarkers.sqf similarity index 100% rename from functions/map/fn_getPlayerMapMarkers.sqf rename to framework/map/fn_getPlayerMapMarkers.sqf diff --git a/functions/map/fn_initMapCopy.sqf b/framework/map/fn_initMapCopy.sqf similarity index 100% rename from functions/map/fn_initMapCopy.sqf rename to framework/map/fn_initMapCopy.sqf diff --git a/functions/map/fn_loadMapMarkers.sqf b/framework/map/fn_loadMapMarkers.sqf similarity index 100% rename from functions/map/fn_loadMapMarkers.sqf rename to framework/map/fn_loadMapMarkers.sqf diff --git a/functions/map/fn_mapMarkerToString.sqf b/framework/map/fn_mapMarkerToString.sqf similarity index 100% rename from functions/map/fn_mapMarkerToString.sqf rename to framework/map/fn_mapMarkerToString.sqf diff --git a/functions/map/fn_stringToMapMarker.sqf b/framework/map/fn_stringToMapMarker.sqf similarity index 100% rename from functions/map/fn_stringToMapMarker.sqf rename to framework/map/fn_stringToMapMarker.sqf diff --git a/framework/performance/functions/fn_addCBASettings.sqf b/framework/performance/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..405e72c --- /dev/null +++ b/framework/performance/functions/fn_addCBASettings.sqf @@ -0,0 +1,105 @@ +#include "..\script_component.hpp" + +//--------------------- +// Server CPS +//--------------------- + +[ + QGVAR(server_cps_enable), + "CHECKBOX", + "Server CPS Metrics Enabled", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + true, + true, + { + params ["_value"]; + [ + QGVAR(cps_enable), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[QGVAR(cps_enable), true] call CBA_settings_fnc_set; + +[ + QGVAR(server_cps_interval), + "TIME", + "Server CPS Metrics Interval", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + [60,300,120], + true, + { + if (!isServer) exitWith {}; + + params ["_value"]; + + [ + QGVAR(cps_interval), + _value + ] call EFUNC(common,logSettingChanged); + + _cpsPFH = missionNamespace getVariable [QGVAR(server_cps_handler), ObjNull]; + if (!isNull _cpsPFH) then { + _cpsPFH call CBA_fnc_deletePerFrameHandlerObject; + }; + + [] call FUNC(addServerStatsPFH); + } +] call CBA_fnc_addSetting; + + +//--------------------- +// Client CPS +//--------------------- + +[ + QGVAR(client_cps_enable), + "CHECKBOX", + "Client CPS Metrics Enabled", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + true, + true, + { + params ["_value"]; + [ + QGVAR(client_cps_enable), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[QGVAR(client_cps_enable), true] call CBA_settings_fnc_set; + +[ + QGVAR(client_cps_interval), + "TIME", + "Client CPS Metrics Interval", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + [60,300,120], + true, + { + if (!hasInterface) exitWith {}; + + params ["_value"]; + + [ + QGVAR(client_cps_interval), + _value + ] call EFUNC(common,logSettingChanged); + + _cpsPFH = player getVariable [QGVAR(client_cps_handler), ObjNull]; + if (!isNull _cpsPFH) then { + _cpsPFH call CBA_fnc_deletePerFrameHandlerObject; + }; + + [] call FUNC(addClientStatsPFH); + } +] call CBA_fnc_addSetting; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "CREATED SETTINGS", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/performance/functions/fn_addClientStatsPFH.sqf b/framework/performance/functions/fn_addClientStatsPFH.sqf new file mode 100644 index 0000000..bc466b7 --- /dev/null +++ b/framework/performance/functions/fn_addClientStatsPFH.sqf @@ -0,0 +1,38 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "Initializing client stats PFH", + [] +] call EFUNC(common,log); + +_cpsPFH = [ + { + [] call FUNC(calculateClientStats); + }, + QGVAR(client_cps_interval) call CBA_settings_fnc_get, + [], + { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Client PFH loaded", + [["pfhInterval", QGVAR(client_cps_interval) call CBA_settings_fnc_get]] + ] call EFUNC(common,log); + }, + { [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Client PFH unloaded", + [] + ] call EFUNC(common,log); + }, + { QGVAR(client_cps_enable) call CBA_settings_fnc_get }, + { false }, + [] +] call CBA_fnc_createPerFrameHandlerObject; + +player setVariable [QGVAR(client_cps_handler), _cpsPFH]; diff --git a/functions/client/fn_addDNI_PlayerFPS.sqf b/framework/performance/functions/fn_addDNI_PlayerFPS.sqf similarity index 97% rename from functions/client/fn_addDNI_PlayerFPS.sqf rename to framework/performance/functions/fn_addDNI_PlayerFPS.sqf index e1bea9f..94d8e56 100644 --- a/functions/client/fn_addDNI_PlayerFPS.sqf +++ b/framework/performance/functions/fn_addDNI_PlayerFPS.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + if ( !hasInterface ) exitWith {}; diag_log text "[MILSIM] (DNI) writing variable loop"; diff --git a/functions/server/fn_addServerStatsPFH.sqf b/framework/performance/functions/fn_addServerStatsPFH.sqf similarity index 51% rename from functions/server/fn_addServerStatsPFH.sqf rename to framework/performance/functions/fn_addServerStatsPFH.sqf index 237c171..21ea60c 100644 --- a/functions/server/fn_addServerStatsPFH.sqf +++ b/framework/performance/functions/fn_addServerStatsPFH.sqf @@ -1,28 +1,48 @@ +#include "..\script_component.hpp" + if (!isServer) exitWith {}; -missionNamespace setVariable["milsim_raw_cps", 0]; -missionNamespace setVariable["milsim_cps", 0]; +missionNamespace setVariable[QGVAR(raw_cps), 0]; +missionNamespace setVariable[QGVAR(cps), 0]; -publicVariable "milsim_raw_cps"; -publicVariable "milsim_cps"; +publicVariable QGVAR(raw_cps); +publicVariable QGVAR(cps); -diag_log text format ["[MILSIM] (server) initializing Server Stats PFH"]; +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "Initializing server stats PFH", + [] +] call EFUNC(common,log); _serverCpsPFH = [ { - [] call milsim_fnc_calculateServerStats; + [] call FUNC(calculateServerStats); }, - "milsim_server_cps_interval" call CBA_settings_fnc_get, + QGVAR(server_cps_interval) call CBA_settings_fnc_get, [], - { diag_log text format ["[MILSIM] (server) Server PFH loaded with interval %1 seconds", "milsim_server_cps_interval" call CBA_settings_fnc_get ] }, - { diag_log text format ["[MILSIM] (server) Server PFH unloaded"] }, - { "milsim_server_cps_enable" call CBA_settings_fnc_get }, + { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Server PFH loaded", + [["pfhInterval", QGVAR(server_cps_interval) call CBA_settings_fnc_get]] + ] call EFUNC(common,log); + }, + { [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Server PFH unloaded", + [] + ] call EFUNC(common,log); + }, + { QGVAR(server_cps_enable) call CBA_settings_fnc_get }, { false }, [] ] call CBA_fnc_createPerFrameHandlerObject; -missionNamespace setVariable ["milsim_server_cps_handler", _serverCpsPFH]; +missionNamespace setVariable [QGVAR(server_cps_handler), _serverCpsPFH]; _playerCpsPFH = [ { diff --git a/functions/client/fn_calculateClientStats.sqf b/framework/performance/functions/fn_calculateClientStats.sqf similarity index 53% rename from functions/client/fn_calculateClientStats.sqf rename to framework/performance/functions/fn_calculateClientStats.sqf index accf498..24bd75c 100644 --- a/functions/client/fn_calculateClientStats.sqf +++ b/framework/performance/functions/fn_calculateClientStats.sqf @@ -1,3 +1,5 @@ +#include "..\script_component.hpp" + [] spawn { // warning: while loop without suspension executes multiple times per frame private _counter = 0; @@ -8,8 +10,8 @@ _counter = _counter + 1; }; // in an empty mission, the _counter may go well over 2000 times per frame! - diag_log text format ["[MILSIM] (client) Average Execution: %1 times per frame", _counter / (diag_frameNo - _frameNo)]; - player setVariable ["milsim_player_raw_cps", _counter / (diag_frameNo - _frameNo), true]; + private _rawCPS = _counter / (diag_frameNo - _frameNo); + player setVariable [QGVAR(player_raw_cps), _rawCPS, true]; // with suspension private _counter = 0; @@ -21,9 +23,23 @@ uiSleep 0.001; // waits at least 1 frame }; // _counter says one per frame, as expected - diag_log text format ["[MILSIM] (client) Average Execution: %1 times per frame", _counter / (diag_frameNo - _frameNo)]; - player setVariable ["milsim_player_cps", _counter / (diag_frameNo - _frameNo), true]; + private _playerCPS = _counter / (diag_frameNo - _frameNo); + player setVariable [QGVAR(player_cps), _playerCPS, true]; + // log to RPT + [ + + {_this call EFUNC(common,log);}, + [ + LEVEL_INFO, + QUOTE(COMPONENT), + format ["Average Execution: %1 times per frame", _playerCPS], + [ + ["playerRawCPS", _rawCPS], + ["playerCPS", _playerCPS] + ] + ] + ] call CBA_fnc_directCall; }; nil; \ No newline at end of file diff --git a/framework/performance/functions/fn_calculateServerStats.sqf b/framework/performance/functions/fn_calculateServerStats.sqf new file mode 100644 index 0000000..f4a0a46 --- /dev/null +++ b/framework/performance/functions/fn_calculateServerStats.sqf @@ -0,0 +1,54 @@ +#include "..\script_component.hpp" + +[] spawn { + // warning: while loop without suspension executes multiple times per frame + private _counter = 0; + private _endTime = diag_tickTime + 5; + private _frameNo = diag_frameNo; + while { diag_tickTime < _endTime } do + { + _counter = _counter + 1; + }; + + private _rawCPS = _counter / (diag_frameNo - _frameNo); + missionNamespace setVariable [QGVAR(server_raw_cps), _rawCPS]; + publicVariable QGVAR(server_raw_cps); + + // with suspension + private _counter = 0; + private _endTime = diag_tickTime + 5; + private _frameNo = diag_frameNo; + while { diag_tickTime < _endTime } do + { + _counter = _counter + 1; + uiSleep 0.001; // waits at least 1 frame + }; + + private _serverCPS = _counter / (diag_frameNo - _frameNo); + missionNamespace setVariable [QGVAR(server_cps), _counter / (diag_frameNo - _frameNo)]; + publicVariable QGVAR(server_cps); + + // log to RPT + [ + + {_this call EFUNC(common,log);}, + [ + LEVEL_INFO, + QUOTE(COMPONENT), + format ["Average Server Execution: %1 times per frame", _serverCPS], + [ + ["serverRawCPS", _rawCPS], + ["serverCPS", _serverCPS] + ] + ] + ] call CBA_fnc_directCall; + + [QGVARMAIN(serverEfficiency), [ + [ + ["float", QGVARMAIN(raw_cps), missionNamespace getVariable [QGVAR(server_raw_cps), -1]], + ["float", QGVARMAIN(cps), missionNamespace getVariable [QGVAR(server_cps), -1]] + ] + ]] call CBA_fnc_localEvent; +}; + +nil; \ No newline at end of file diff --git a/framework/performance/script_component.hpp b/framework/performance/script_component.hpp new file mode 100644 index 0000000..5cc7549 --- /dev/null +++ b/framework/performance/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT performance +#define COMPONENT_BEAUTIFIED Performance Monitoring +#include "../script_mod.hpp" \ No newline at end of file diff --git a/functions/reinsert/client/fn_addAceSelfActions.sqf b/framework/reinsert/client/fn_addAceSelfActions.sqf similarity index 60% rename from functions/reinsert/client/fn_addAceSelfActions.sqf rename to framework/reinsert/client/fn_addAceSelfActions.sqf index 137540d..a6f66de 100644 --- a/functions/reinsert/client/fn_addAceSelfActions.sqf +++ b/framework/reinsert/client/fn_addAceSelfActions.sqf @@ -1,36 +1,38 @@ +#include "..\script_component.hpp" + params ["_type"]; // string of the object's classname if (!(_type isKindOf "CAManBase")) exitWith {}; if ( - (localNamespace getVariable ["milsim_reinsert_fileForReinsertClassesAdded", []]) + (localNamespace getVariable [QGVAR(fileForReinsertClassesAdded), []]) find _type != -1 ) exitWith {}; private _fileForReinsertAction = [ - "milsim_reinsert_fileReinsertRequest", + QGVAR(fileReinsertRequestAction), "File Re-insert Request", "\A3\ui_f\data\igui\cfg\simpleTasks\types\takeoff_ca.paa", { // statement params ["_target", "_player", "_params"]; // find nearest base or location - private _base = [_player] call milsim_fnc_getNearestBase; - private _baseName = [_base] call milsim_fnc_getNameOfBase; + private _base = [_player] call EFUNC(common,getNearestBase); + private _baseName = [_base] call EFUNC(common,getNameOfBase); // send event to server - ["milsim_reinsert_fileReinsertRequest", [_player, _base]] call CBA_fnc_serverEvent; + [QGVAR(fileReinsertRequest), [_player, _base]] call CBA_fnc_serverEvent; // notify player their request was filed [["Re-insert Request Filed"], [format["Location: %1", _baseName]]] call CBA_fnc_notify; }, { // condition params ["_target", "_player", "_params"]; // find nearest base or location - private _base = [_player] call milsim_fnc_getNearestBase; + private _base = [_player] call EFUNC(common,getNearestBase); private _baseDistance = _player distance _base; - private _maxRangeToReady = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_maxRangeToReady", 400]; - private _existingQueue = missionNamespace getVariable ["milsim_reinsert_reinsertionQueue", []]; + private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; + private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; // check if module is enabled, player is near a base, and player is not already in the queue - // (serverTime - milsim_reinsert_missionStartServerTime) > 60*5 && // only allow after 15 minutes + // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] && (_baseDistance < _maxRangeToReady) && not (_player in (_existingQueue apply {_x#0})) @@ -39,29 +41,29 @@ private _fileForReinsertAction = [ [_type, 1, ["ACE_SelfActions"], _fileForReinsertAction, true] call ace_interact_menu_fnc_addActionToClass; private _removeFileForReinsertAction = [ - "milsim_reinsert_removeReinsertRequest", + QGVAR(removeReinsertRequestAction), "Remove Re-insert Request", "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", { // statement params ["_target", "_player", "_params"]; // send event to server - ["milsim_reinsert_removeReinsertRequest", [_player]] call CBA_fnc_serverEvent; + [QGVAR(removeReinsertRequest), [_player]] call CBA_fnc_serverEvent; // notify player their request was rescinded "Re-insert Request Rescinded" call CBA_fnc_notify; }, { // condition params ["_target", "_player", "_params"]; - private _existingQueue = missionNamespace getVariable ["milsim_reinsert_reinsertionQueue", []]; + private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; // check if module is enabled, player is in the queue - // (serverTime - milsim_reinsert_missionStartServerTime) > 60*5 && // only allow after 15 minutes + // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] && (_player in (_existingQueue apply {_x#0})) } ] call ace_interact_menu_fnc_createAction; [_type, 1, ["ACE_SelfActions"], _removeFileForReinsertAction, true] call ace_interact_menu_fnc_addActionToClass; -private _classesActionsAddedTo = (localNamespace getVariable ["milsim_reinsert_fileForReinsertClassesAdded", []]); +private _classesActionsAddedTo = (localNamespace getVariable [QGVAR(fileForReinsertClassesAdded), []]); _classesActionsAddedTo pushBackUnique _type; -localNamespace setVariable ["milsim_reinsert_fileForReinsertClassesAdded", _classesActionsAddedTo]; +localNamespace setVariable [QGVAR(fileForReinsertClassesAdded), _classesActionsAddedTo]; diff --git a/functions/reinsert/client/fn_addCheckQueueSelfAction.sqf b/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf similarity index 52% rename from functions/reinsert/client/fn_addCheckQueueSelfAction.sqf rename to framework/reinsert/client/fn_addCheckQueueSelfAction.sqf index 5897b53..341e09f 100644 --- a/functions/reinsert/client/fn_addCheckQueueSelfAction.sqf +++ b/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf @@ -1,28 +1,30 @@ +#include "..\script_component.hpp" + params ["_type"]; // string of the object's classname if (!(_type isKindOf "CAManBase")) exitWith {}; if ( - (localNamespace getVariable ["milsim_reinsert_checkReinsertQueueClassesAdded", []]) + (localNamespace getVariable [QGVAR(checkReinsertQueueClassesAdded), []]) find _type != -1 ) exitWith {}; private _checkReinsertQueueAction = [ - "milsim_reinsert_checkReinsertQueue", + QGVAR(checkReinsertQueue), "[PILOT] Check Re-insert Queue", "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", { params ["_target", "_player", "_params"]; // request notification from the server - call milsim_reinsert_fnc_requestShowQueue; + call FUNC(requestShowQueue); // reset last check time - localNamespace setVariable ["milsim_reinsert_lastReinsertQueueCheck", diag_tickTime]; + localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; }, { - missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] + missionNamespace getVariable [QGVAR(setting_enabled), true] } // always allow ] call ace_interact_menu_fnc_createAction; [_type, 1, ["ACE_SelfActions"], _checkReinsertQueueAction, true] call ace_interact_menu_fnc_addActionToClass; -private _classesActionsAddedTo = (localNamespace getVariable ["milsim_reinsert_checkReinsertQueueClassesAdded", []]); +private _classesActionsAddedTo = (localNamespace getVariable [QGVAR(checkReinsertQueueClassesAdded), []]); _classesActionsAddedTo pushBackUnique _type; -localNamespace setVariable ["milsim_reinsert_checkReinsertQueueClassesAdded", _classesActionsAddedTo]; \ No newline at end of file +localNamespace setVariable [QGVAR(checkReinsertQueueClassesAdded), _classesActionsAddedTo]; \ No newline at end of file diff --git a/functions/reinsert/client/fn_initClient.sqf b/framework/reinsert/client/fn_initClient.sqf similarity index 56% rename from functions/reinsert/client/fn_initClient.sqf rename to framework/reinsert/client/fn_initClient.sqf index cdee922..f262ffe 100644 --- a/functions/reinsert/client/fn_initClient.sqf +++ b/framework/reinsert/client/fn_initClient.sqf @@ -1,26 +1,28 @@ +#include "..\script_component.hpp" + if (!hasInterface) exitWith {}; // ACE SELF-INTERACTIONS FOR FILING AND RESCINDING REINSERT REQUESTS NEAR BASE - ALL PLAYERS -localNamespace setVariable ["milsim_reinsert_fileForReinsertClassesAdded", []]; +localNamespace setVariable [QGVAR(fileForReinsertClassesAdded), []]; // add actions to current class -[typeOf player] call milsim_reinsert_fnc_addAceSelfActions; +[typeOf player] call FUNC(addAceSelfActions); // add actions to future classes ["ace_interact_menu_newControllableObject", { - _this call milsim_reinsert_fnc_addAceSelfActions; + _this call FUNC(addAceSelfActions); }] call CBA_fnc_addEventHandler; ///////////////////////////////////////////////////// // PILOTS ONLY // ACE SELF-INTERACTIONS FOR CHECKING REINSERT QUEUE - ONLY FOR PILOTS if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { - localNamespace setVariable ["milsim_reinsert_checkReinsertQueueClassesAdded", []]; - localNamespace setVariable ["milsim_reinsert_lastReinsertQueueCheck", diag_tickTime]; + localNamespace setVariable [QGVAR(checkReinsertQueueClassesAdded), []]; + localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; // add actions to current class - [typeOf player] call milsim_reinsert_fnc_addCheckQueueSelfAction; + [typeOf player] call FUNC(addCheckQueueSelfAction); // add actions to future classes ["ace_interact_menu_newControllableObject", { - _this call milsim_reinsert_fnc_addCheckQueueSelfAction; + _this call FUNC(addCheckQueueSelfAction); }] call CBA_fnc_addEventHandler; }; ///////////////////////////////////////////////////// @@ -31,13 +33,13 @@ if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { [{ // if module not enabled and pilot forced check not enabled, exit if (not ( - missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] && - missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_pilotForcedCheckEnabled", true] + missionNamespace getVariable [QGVAR(setting_enabled), true] && + missionNamespace getVariable [QGVAR(setting_pilotForcedCheckEnabled), true] )) exitWith {}; // if last check was less than X minutes ago, skip - private _lastCheck = localNamespace getVariable ["milsim_reinsert_lastReinsertQueueCheck", diag_tickTime]; - private _requiredCheckInterval = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_pilotForcedCheckInterval", 60*20]; + private _lastCheck = localNamespace getVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; + private _requiredCheckInterval = missionNamespace getVariable [QGVAR(setting_pilotForcedCheckInterval), 60*20]; if ( diag_tickTime - _lastCheck < _requiredCheckInterval @@ -45,9 +47,16 @@ if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { // last check was greater than X minutes ago // reset last check time - localNamespace setVariable ["milsim_reinsert_lastReinsertQueueCheck", diag_tickTime]; + localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; // request notification from the server - call milsim_reinsert_fnc_requestShowQueue; + call FUNC(requestShowQueue); }, 30] call CBA_fnc_addPerFrameHandler; }; -///////////////////////////////////////////////////// \ No newline at end of file +///////////////////////////////////////////////////// + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/reinsert/client/fn_requestShowQueue.sqf b/framework/reinsert/client/fn_requestShowQueue.sqf new file mode 100644 index 0000000..afb4f03 --- /dev/null +++ b/framework/reinsert/client/fn_requestShowQueue.sqf @@ -0,0 +1,5 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +[] remoteExec [QFUNC(returnReinsertQueueNotification), 2]; \ No newline at end of file diff --git a/framework/reinsert/functions/fn_addCBASettings.sqf b/framework/reinsert/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..b605d6a --- /dev/null +++ b/framework/reinsert/functions/fn_addCBASettings.sqf @@ -0,0 +1,83 @@ +#include "..\script_component.hpp" + +//--------------------- +// Respawn Settings +[ + QGVAR(setting_enabled), // variable + "CHECKBOX", // type + ["Enabled", "Whether or not players can file for reinsert and pilots can check the reinsert queue"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + true, // default value + true, // global setting + { + params ["_value"]; + [ + QGVAR(setting_enabled), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_maxRangeToReady), // variable + "SLIDER", // type + ["Max Request Filing Range", "Maximum distance from a respawn point a player can be to ready up"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [0, 1000, 400, 0, false], // [_min, _max, _default, _trailingDecimals, _isPercentage] + true, // global setting + { + params ["_value"]; + [ + QGVAR(setting_maxRangeToReady), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_maxWait), // variable + "TIME", // type + ["Max Wait Before Global Notify", "How long should at least one person be waiting before prompting a global notification."], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [60*5, 60*30, 60*20], // [_min, _max, _default] + true, + { + params ["_value"]; + [ + QGVAR(setting_maxWait), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_pilotForcedCheckEnabled), // variable + "CHECKBOX", // type + ["Force Queue Checks for Pilots", "Whether or not pilots are forced to view the contents of the reinsertion queue per interval"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + false, // default value + true, // global setting + { + params ["_value"]; + [ + QGVAR(setting_pilotForcedCheckEnabled), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_pilotForcedCheckInterval), // variable + "TIME", // type + ["Pilot Forced Check Interval", "Pilots will be force shown the queue if they haven't checked it in X seconds"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [60*5, 60*30, 60*10], // [_min, _max, _default] + true, + { + params ["_value"]; + [ + QGVAR(setting_pilotForcedCheckInterval), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; diff --git a/framework/reinsert/script_component.hpp b/framework/reinsert/script_component.hpp new file mode 100644 index 0000000..3525b55 --- /dev/null +++ b/framework/reinsert/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT reinsert +#define COMPONENT_BEAUTIFIED Reinsertion +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/reinsert/server/fn_addToQueue.sqf b/framework/reinsert/server/fn_addToQueue.sqf new file mode 100644 index 0000000..6642f98 --- /dev/null +++ b/framework/reinsert/server/fn_addToQueue.sqf @@ -0,0 +1,61 @@ +#include "..\script_component.hpp" + +params [ + ["_player", objNull, [objNull]], + ["_base", objNull, [objNull]], + ["_timeFiled", diag_tickTime, [25]] +]; + +if (!isServer) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "ATTEMPTED RUN ON CLIENT", + [ + ["player", _player], + ["base", _base] + ] + ] call EFUNC(common,log); + ["ATTEMPTED RUN ON CLIENT"] call BIS_fnc_error; +}; +if ( + isNull _player || + isNull _base +) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "NULL PARAMETERS", + [ + ["player", _player], + ["base", _base] + ] + ] call EFUNC(common,log); + ["NULL PARAMETERS"] call BIS_fnc_error; +}; + + +private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; +// nearest base here is the same as the base sent +private _nearestBase = _base; + +GVAR(reinsertionQueue) pushBackUnique [ + _player, _base, _timeFiled +]; +// broadcast new list to all machines +publicVariable QGVAR(reinsertionQueue); + +// log to rpt +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "PLAYER FILED REQUEST", + [_player, [ + ["filedAtBase", [_base] call EFUNC(common,getNameOfBase)], + ["filedAtBaseDistance", _player distance _base], + ["closestBase", [_nearestBase] call EFUNC(common,getNameOfBase)], + ["closestBaseDistance", _player distance _nearestBase], + ["maxDistanceSetting", _maxRangeToReady], + ["inQueueDuration", diag_tickTime - _timeFiled] + ]] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); \ No newline at end of file diff --git a/functions/reinsert/server/fn_globalShowQueue.sqf b/framework/reinsert/server/fn_globalShowQueue.sqf similarity index 56% rename from functions/reinsert/server/fn_globalShowQueue.sqf rename to framework/reinsert/server/fn_globalShowQueue.sqf index ea7e80e..def6061 100644 --- a/functions/reinsert/server/fn_globalShowQueue.sqf +++ b/framework/reinsert/server/fn_globalShowQueue.sqf @@ -1,8 +1,10 @@ +#include "..\script_component.hpp" + if (!isServer) exitWith {}; // if at least 1 player in the queue has been waiting longer than the configured timeout, notify all players -private _timeout = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_max_wait", 60*20]; // default 20 minutes -private _timeoutPlayers = milsim_reinsert_reinsertionQueue select { +private _timeout = missionNamespace getVariable [QGVAR(setting_maxWait), 60*20]; // default 20 minutes +private _timeoutPlayers = GVAR(reinsertionQueue) select { _x params ["_player", "_base", "_timeFiled"]; alive (_player) && (diag_tickTime - (_timeFiled)) > _timeout @@ -10,10 +12,10 @@ private _timeoutPlayers = milsim_reinsert_reinsertionQueue select { if (count _timeoutPlayers > 0) then { // GLOBAL CBA NOTIFY private _playerLines = [["Players are still waiting for Re-insert!", 1.2, [1, 0.64, 0, 1]]]; - private _maxRangeToReady = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_maxRangeToReady", 400]; + private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; // get base objects from queue - private _basesWithPeople = (missionNamespace getVariable ["milsim_reinsert_reinsertionQueue", []]) apply {_x#1}; + private _basesWithPeople = (missionNamespace getVariable [QGVAR(reinsertionQueue), []]) apply {_x#1}; // get unique base objects private _basesWithPeople = _basesWithPeople arrayIntersect _basesWithPeople; @@ -21,7 +23,7 @@ if (count _timeoutPlayers > 0) then { private _thisBase = _x; // Add line for base name - _playerLines pushBack ([[_thisBase] call milsim_fnc_getNameOfBase, 1, [0,1,0,1]]); + _playerLines pushBack ([[_thisBase] call EFUNC(common,getNameOfBase), 1, [0,1,0,1]]); // Get players under this base private _thisBasePlayers = _timeoutPlayers select {_x#1 isEqualTo _thisBase}; @@ -35,36 +37,35 @@ if (count _timeoutPlayers > 0) then { { // for each player under this base, add a line _x params ["_player", "_base", "_timeFiled"]; // get the closest base to the player - private _nearestBase = [_player] call milsim_fnc_getNearestBase; + private _nearestBase = [_player] call EFUNC(common,getNearestBase); // add player to array of players under bases _playerLines pushBack ([format [ "%1: %2 [%3]", groupID (group (_player)), - name (_player), + name _player, [diag_tickTime - (_timeFiled), "MM:SS"] call BIS_fnc_secondsToString ], 0.8, [0.8, 0.8, 0.8, 1]]); // log to rpt - private _logParams = [ - ["filedAtBase", [_base] call milsim_fnc_getNameOfBase], - ["filedAtBaseDistance", _player distance _base], - ["closestBase", [_nearestBase] call milsim_fnc_getNameOfBase], - ["closestBaseDistance", _player distance _nearestBase], - ["maxDistanceSetting", _maxRangeToReady], - ["inQueueDuration", diag_tickTime - _timeFiled] - ]; - _logParams = [_player, _logParams] call milsim_fnc_addPlayerInfoToArray; [ - "respawn_reinsertion", + LEVEL_WARNING, + QUOTE(COMPONENT), "PLAYER WAITING OVER TIMEOUT", - _logParams - ] call milsim_fnc_log; + [_player, [ + ["filedAtBase", [_base] call EFUNC(common,getNameOfBase)], + ["filedAtBaseDistance", _player distance _base], + ["closestBase", [_nearestBase] call EFUNC(common,getNameOfBase)], + ["closestBaseDistance", _player distance _nearestBase], + ["maxDistanceSetting", _maxRangeToReady], + ["inQueueDuration", diag_tickTime - _timeFiled] + ]] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); } forEach _thisBasePlayers; } forEach _basesWithPeople; // SEND NOTIFY _playerLines remoteExec ["CBA_fnc_notify", [0, -2] select isDedicated]; // RESET NOTIFICATION TIMER - milsim_reinsert_reinsertionOverTimeoutLastNotificationTime = diag_tickTime; + GVAR(overTimeoutLastNotificationTime) = diag_tickTime; }; \ No newline at end of file diff --git a/functions/reinsert/server/fn_initServer.sqf b/framework/reinsert/server/fn_initServer.sqf similarity index 55% rename from functions/reinsert/server/fn_initServer.sqf rename to framework/reinsert/server/fn_initServer.sqf index 03370a0..2bd94ce 100644 --- a/functions/reinsert/server/fn_initServer.sqf +++ b/framework/reinsert/server/fn_initServer.sqf @@ -3,48 +3,51 @@ // if a player's time in the queue exceeds the configured timeout, a message will be posted every 5 minutes on a cycle based around // the player's time in the queue stating how long they have been waiting, their name, and their group's name +#include "..\script_component.hpp" + if (!isServer) exitWith {}; -// array of all respawn modules in the mission, used as 'base' locations for reinsertion -milsim_baseObjects = allMissionObjects "ModuleRespawnPosition_F"; -publicVariable "milsim_baseObjects"; - // register queue -milsim_reinsert_reinsertionQueue = []; -publicVariable "milsim_reinsert_reinsertionQueue"; - +GVAR(reinsertionQueue) = []; +publicVariable QGVAR(reinsertionQueue); // server mission start time -milsim_reinsert_missionStartServerTime = serverTime; +GVAR(missionStartServerTime) = serverTime; // FILE REQUEST CBA HANDLER -["milsim_reinsert_fileReinsertRequest", { +[QGVAR(fileReinsertRequest), { params ["_player", "_base"]; - [_player, _base] call milsim_reinsert_fnc_addToQueue; + [_player, _base] call FUNC(addToQueue); }] call CBA_fnc_addEventHandler; // REMOVE REQUEST CBA HANDLER -["milsim_reinsert_removeReinsertRequest", { +[QGVAR(removeReinsertRequest), { params ["_player"]; - [_player] call milsim_reinsert_fnc_removeFromQueue; + [_player] call FUNC(removeFromQueue); }] call CBA_fnc_addEventHandler; // automated wait threshold timer -milsim_reinsert_reinsertionOverTimeoutLastNotificationTime = 0; +GVAR(overTimeoutLastNotificationTime) = 0; [{ // every 60 seconds // validate queue - call milsim_reinsert_fnc_validateQueue; + call FUNC(validateQueue); // check if last overTimeout notification was sent more than X minutes ago if ( - diag_tickTime - milsim_reinsert_reinsertionOverTimeoutLastNotificationTime > 60*5 + diag_tickTime - GVAR(overTimeoutLastNotificationTime) > 60*5 ) then { // show global queue notification with any players that are over timeout - call milsim_reinsert_fnc_globalShowQueue; + call FUNC(globalShowQueue); }; }, 60] call CBA_fnc_addPerFrameHandler; +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); diff --git a/framework/reinsert/server/fn_removeFromQueue.sqf b/framework/reinsert/server/fn_removeFromQueue.sqf new file mode 100644 index 0000000..4a76c82 --- /dev/null +++ b/framework/reinsert/server/fn_removeFromQueue.sqf @@ -0,0 +1,60 @@ +#include "..\script_component.hpp" + +params [["_player", objNull, [objNull]]]; + +if (!isServer) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "ATTEMPTED RUN ON CLIENT", + [ + ["player", _player] + ] + ] call EFUNC(common,log); +}; +if (isNull _player) exitWith { + [ + LEVEL_ERROR, + QUOTE(COMPONENT), + "NULL PARAMETERS", + [ + ["player", _player] + ] + ] call EFUNC(common,log); +}; + +// get entries for this player from queue +private _unitArrs = GVAR(reinsertionQueue) select {_x#0 isEqualTo _player}; +// if player not in queue, skip +if (count _unitArrs isEqualTo 0) exitWith {}; + +private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; + +// remove player from queue +GVAR(reinsertionQueue) = GVAR(reinsertionQueue) - _unitArrs; +// broadcast new list to all machines +publicVariable QGVAR(reinsertionQueue); + +// sort _unitArrs by time in queue, descending, to get longest wait (if for some reason there's a duplicate) +[_unitArrs, [], { + _x#2 +}, "DESCEND"] call BIS_fnc_sortBy; + +// get first entry (longest wait) +(_unitArrs#0) params ["_player", "_base", "_timeFiled"]; // _unitArr = [unit, base, timeInQueue] +// get the closest base to the player +private _nearestBase = [_player] call EFUNC(common,getNearestBase); +// log to rpt +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "PLAYER RESCINDED REQUEST", + [_player, [ + ["filedAtBase", [_base] call EFUNC(common,getNameOfBase)], + ["filedAtBaseDistance", _player distance _base], + ["closestBase", [_nearestBase] call EFUNC(common,getNameOfBase)], + ["closestBaseDistance", _player distance _nearestBase], + ["maxDistanceSetting", _maxRangeToReady], + ["inQueueDuration", diag_tickTime - _timeFiled] + ]] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); \ No newline at end of file diff --git a/functions/reinsert/server/fn_returnReinsertQueueNotification.sqf b/framework/reinsert/server/fn_returnReinsertQueueNotification.sqf similarity index 86% rename from functions/reinsert/server/fn_returnReinsertQueueNotification.sqf rename to framework/reinsert/server/fn_returnReinsertQueueNotification.sqf index ffe648b..14c04df 100644 --- a/functions/reinsert/server/fn_returnReinsertQueueNotification.sqf +++ b/framework/reinsert/server/fn_returnReinsertQueueNotification.sqf @@ -7,6 +7,8 @@ Author: IndigoFox */ +#include "..\script_component.hpp" + if (not isRemoteExecuted) exitWith { diag_log text format ["[milsim] (respawn_reinsertion) SHOW QUEUE NOT REMOTE EXECUTED"]; }; @@ -25,16 +27,16 @@ if (isNull _userObject) exitWith { }; // log to rpt -private _logParams = [_userObject, []] call milsim_fnc_addPlayerInfoToArray; [ - "respawn_reinsertion", + LEVEL_INFO, + QUOTE(COMPONENT), "SHOW QUEUE REQUESTED", - _logParams -] call milsim_fnc_log; + [_userObject] call EFUNC(common,addPlayerInfoToArray) +] call EFUNC(common,log); -private _queue = missionNamespace getVariable ["milsim_reinsert_reinsertionQueue", []]; +private _queue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; // get base objects from queue -private _basesWithPeople = (missionNamespace getVariable ["milsim_reinsert_reinsertionQueue", []]) apply {_x#1}; +private _basesWithPeople = (missionNamespace getVariable [QGVAR(reinsertionQueue), []]) apply {_x#1}; // get unique base objects private _basesWithPeople = _basesWithPeople arrayIntersect _basesWithPeople; @@ -48,7 +50,7 @@ if (count _basesWithPeople isEqualTo 0) then { // forEach _basesWithPeople { private _thisBase = _x; - private _baseName = [_thisBase] call milsim_fnc_getNameOfBase; + private _baseName = [_thisBase] call EFUNC(common,getNameOfBase); // generate player lines for this base private _playerLines = _queue select { diff --git a/framework/reinsert/server/fn_validateQueue.sqf b/framework/reinsert/server/fn_validateQueue.sqf new file mode 100644 index 0000000..9d3be7f --- /dev/null +++ b/framework/reinsert/server/fn_validateQueue.sqf @@ -0,0 +1,57 @@ +// revalidate any players in the queue +// compare their distance to the nearest base, and remove them if they're too far away (or dead) +#include "..\script_component.hpp" + +private _stillValid = []; +private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; +{ + _x params ["_player", "_base", "_timeFiled"]; // _unitArr = [unit, baseName, timeInQueue] + + private _distanceToOriginalBase = _player distance _base; + // get the closest base to the player + private _nearestBase = [_player] call EFUNC(common,getNearestBase); + private _isCloseEnoughToAnyBase = (_player distance _nearestBase) < _maxRangeToReady; + + if (not _isCloseEnoughToAnyBase || not (alive _player)) then { + // don't include player in updated queue + // log to rpt + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "PLAYER DEQUEUED AUTOMATICALLY", + [_player, [ + ["filedAtBase", [_base] call EFUNC(common,getNameOfBase)], + ["filedAtBaseDistance", _player distance _base], + ["closestBase", [_nearestBase] call EFUNC(common,getNameOfBase)], + ["closestBaseDistance", _player distance _nearestBase], + ["maxDistanceSetting", _maxRangeToReady], + ["inQueueDuration", diag_tickTime - _timeFiled] + ]] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); + // continue loop + continue + }; + + // include player in updated queue, and update their location to nearest base + _stillValid pushBackUnique [_player, _nearestBase, _timeFiled]; + // if player's base has changed, log to rpt + if (_base != _nearestBase) then { + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "PLAYER BASE WAS UPDATED", + [_player, [ + ["filedAtBase", [_base] call EFUNC(common,getNameOfBase)], + ["filedAtBaseDistance", _player distance _base], + ["closestBase", [_nearestBase] call EFUNC(common,getNameOfBase)], + ["closestBaseDistance", _player distance _nearestBase], + ["maxDistanceSetting", _maxRangeToReady], + ["inQueueDuration", diag_tickTime - _timeFiled] + ]] call EFUNC(common,addPlayerInfoToArray) + ] call EFUNC(common,log); + }; +} forEach GVAR(reinsertionQueue); + +// broadcast new list to all machines +GVAR(reinsertionQueue) = _stillValid; +publicVariable QGVAR(reinsertionQueue); \ No newline at end of file diff --git a/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf new file mode 100644 index 0000000..74977f9 --- /dev/null +++ b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf @@ -0,0 +1,62 @@ +#include "..\script_component.hpp" + +// adds a scroll wheel action to all arsenal boxes to spawn different supply crate types + +private _arsenalBoxClassName = "Land_PaperBox_open_full_F"; + +// get all instances of the arsenal item +private _arsenalBoxes = (allMissionObjects _arsenalBoxClassName) select { + // only select the ones that already have user actions attached + count (actionIDs _x) > 0; +}; + +private _supplyCratesCfg = call FUNC(getSupplyCratesCfg); +private _supplyCrateTypesCfgs = _supplyCratesCfg call BIS_fnc_returnChildren; + +{ + // add scroll wheel action to spawn different supply box types + private _arsenalBox = _x; + + // always remove old actions if they exist + private _actionIDs = _arsenalBox getVariable [QGVAR(supplyCrateActionIDs), []]; + { + _arsenalBox removeAction _x; + } forEach _actionIDs; + _arsenalBox setVariable [QGVAR(supplyCrateActionIDs), []]; + + + // if setting disabled, skip adding actions + if (not ( + [QGVAR(setting_allowSupplyBoxScrollWheelSpawning)] call CBA_settings_fnc_get + )) then {continue}; + + + { // add an action for each supply crate type + private _cfg = _x; + private _supplyCrateDisplayName = (_cfg >> "displayName") call BIS_fnc_getCfgData; + + + + + private _actionID = _arsenalBox addAction [format ["Spawn %1", _supplyCrateDisplayName], { + params ["_target", "_caller", "_actionId", "_arguments"]; + _arguments params ["_supplyCrateCfg"]; + [ + objNull, + configName _supplyCrateCfg, + getPos _target + ] call FUNC(createBox); + // log action use in server RPT + [ + LEVEL_INFO, + QUOTE(COMPONENT), + "Supply crate spawned", + [player, [ + ["supplyCrateType", _supplyCrateDisplayName], + ["position", getPos _target] + ]] call EFUNC(common,addPlayerInfoToArray) + ] remoteExec [QEFUNC(common,log), 2]; + }, [_cfg], 0, false, true, "", ""]; + (_arsenalBox getVariable [QGVAR(supplyCrateActionIDs), []]) pushBack _actionID; + } forEach _supplyCrateTypesCfgs; +} forEach _arsenalBoxes; \ No newline at end of file diff --git a/framework/resupply/functions/fn_addCBASettings.sqf b/framework/resupply/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..acfe0b9 --- /dev/null +++ b/framework/resupply/functions/fn_addCBASettings.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" + +[ + QGVAR(setting_allowSupplyBoxScrollWheelSpawning), // variable + "CHECKBOX", // type + ["Allow Spawning Boxes from Arsenal Box", "If true, adds scroll wheel options to arsenal boxes to spawn supply boxes"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + false, // default value + true, // global setting + { + params ["_value"]; + [ + QGVAR(setting_allowSupplyBoxScrollWheelSpawning), + _value + ] call EFUNC(common,logSettingChanged); + + if (_value && hasInterface && time > 0) then { + [] call FUNC(addArsenalObjectSpawnBoxActions); + }; + }, + true // requires mission restart +] call CBA_fnc_addSetting; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "CREATED SETTINGS", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/functions/resupply/fn_createBox.sqf b/framework/resupply/functions/fn_createBox.sqf similarity index 98% rename from functions/resupply/fn_createBox.sqf rename to framework/resupply/functions/fn_createBox.sqf index b4576ef..6bbfbb9 100644 --- a/functions/resupply/fn_createBox.sqf +++ b/framework/resupply/functions/fn_createBox.sqf @@ -27,7 +27,8 @@ ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] ]]; */ - + +#include "..\script_component.hpp" params [ ["_box", objNull, [objNull]], @@ -36,7 +37,7 @@ params [ ]; // get defs class -private _supplyCratesCfg = call milsim_resupply_fnc_getSupplyCratesCfg; +private _supplyCratesCfg = call FUNC(getSupplyCratesCfg); if (!isClass _supplyCratesCfg) exitWith { ["Resupply Boxes: Failed to load crate definitions, possibly a bad edit?"] call BIS_fnc_error; objNull; diff --git a/framework/resupply/functions/fn_getSupplyCratesCfg.sqf b/framework/resupply/functions/fn_getSupplyCratesCfg.sqf new file mode 100644 index 0000000..62c7a5e --- /dev/null +++ b/framework/resupply/functions/fn_getSupplyCratesCfg.sqf @@ -0,0 +1,2 @@ +#include "..\script_component.hpp" +(missionConfigFile >> "SupplyCrates"); \ No newline at end of file diff --git a/framework/resupply/functions/fn_initClient.sqf b/framework/resupply/functions/fn_initClient.sqf new file mode 100644 index 0000000..a78233f --- /dev/null +++ b/framework/resupply/functions/fn_initClient.sqf @@ -0,0 +1,13 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +call FUNC(addArsenalObjectSpawnBoxActions); + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/resupply/script_component.hpp b/framework/resupply/script_component.hpp new file mode 100644 index 0000000..fd4aad0 --- /dev/null +++ b/framework/resupply/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT resupply +#define COMPONENT_BEAUTIFIED Resupply +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/script_macros.hpp b/framework/script_macros.hpp new file mode 100644 index 0000000..09f2599 --- /dev/null +++ b/framework/script_macros.hpp @@ -0,0 +1,11 @@ +// all text before cba include +#define SETTINGS_GROUP_NAME 17th Battalion +#define MODULE_CATEGORY_NAME 17th Battalion + +#define LEVEL_TRACE -1 +#define LEVEL_DEBUG 0 +#define LEVEL_INFO 1 +#define LEVEL_WARNING 2 +#define LEVEL_ERROR 3 + +#include "\x\cba\addons\main\script_macros_mission.hpp" \ No newline at end of file diff --git a/framework/script_mod.hpp b/framework/script_mod.hpp new file mode 100644 index 0000000..21deabe --- /dev/null +++ b/framework/script_mod.hpp @@ -0,0 +1,17 @@ +#define PREFIX milsim + +#include "script_version.hpp" + +#define VERSION MAJOR.MINOR.PATCHLVL +#define VERSION_STR MAJOR.MINOR.PATCHLVL +#define VERSION_AR MAJOR,MINOR,PATCHLVL + +// #define DEBUG_MODE -1 // TRACE +// #define DEBUG_MODE 0 // DEBUG +#define DEBUG_MODE 1 // INFO +// #define DEBUG_MODE 2 // WARNING +// #define DEBUG_MODE 3 // ERROR + + +// should always be last +#include "script_macros.hpp" \ No newline at end of file diff --git a/framework/script_version.hpp b/framework/script_version.hpp new file mode 100644 index 0000000..5e3d29c --- /dev/null +++ b/framework/script_version.hpp @@ -0,0 +1,4 @@ +#define MAJOR 3 +#define MINOR 2 +#define PATCHLVL 1 +#define BUILD 0 diff --git a/framework/triageIcons/functions/fn_addCBASettings.sqf b/framework/triageIcons/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..775ff9b --- /dev/null +++ b/framework/triageIcons/functions/fn_addCBASettings.sqf @@ -0,0 +1,138 @@ +#include "..\script_component.hpp" + +//--------------------- +// Medical Overlay +//--------------------- + +[ + QGVAR(setting_enabled), // variable + "CHECKBOX", // type + ["Enable 3D Triage Card State", "For players with medic perms, a colored dot will be shown over unconscious units within Xm indicating current ACE Triage State"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + true, // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_enabled), + _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(addGetEntitiesPFH); + call FUNC(addDrawIconsPFH); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_drawRange), // variable + "LIST", // type + ["Range To Draw Icons", "Determines range at which dots are visible"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [[2, 4, 6, 8, 10], ["2", "4", "6", "8", "10"], 4], // option values, option labels, default index + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_drawRange), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_colorMinimal), // variable + "COLOR", // type + ["Minimal State Color", "Color of the dot for MINIMAL state"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [0, 0.5, 0], // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_colorMinimal), + str _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(updateColors); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_colorDelayed), // variable + "COLOR", // type + ["Delayed State Color", "Color of the dot for DELAYED state"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [1, 0.84, 0], // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_colorDelayed), + str _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(updateColors); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_colorImmediate), // variable + "COLOR", // type + ["Immediate State Color", "Color of the dot for IMMEDIATE state"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [1, 0, 0], // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_colorImmediate), + str _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(updateColors); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_colorDeceased), // variable + "COLOR", // type + ["Deceased State Color", "Color of the dot for DECEASED state"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [0.15, 0.15, 0.15], // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_colorDeceased), + str _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(updateColors); + } +] call CBA_fnc_addSetting; + +[ + QGVAR(setting_colorNone), // variable + "COLOR", // type + ["None State Color", "Color of the dot for NONE state, when a card is not set"], // title + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], // category + [0.5, 0.5, 0.5], // default value + false, // isGlobal + { + params ["_value"]; + [ + QGVAR(setting_colorNone), + str _value + ] call EFUNC(common,logSettingChanged); + + call FUNC(updateColors); + } +] call CBA_fnc_addSetting; + + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "CREATED SETTINGS", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/triageIcons/functions/fn_addDrawIconsPFH.sqf b/framework/triageIcons/functions/fn_addDrawIconsPFH.sqf new file mode 100644 index 0000000..6478264 --- /dev/null +++ b/framework/triageIcons/functions/fn_addDrawIconsPFH.sqf @@ -0,0 +1,62 @@ +/* + +milsim_fnc_addMedicalOverlayPFH + +Author: IndigoFox + +Description: + Affects players with medical permissions. Will see a 3D colored dot over nearby (5-10m) + unconscious players who are not in a vehicle + which indicates their current ACE Triage Card status. + Designed to increase efficiency of CCPs. + +*/ + +#include "..\script_component.hpp" + + +// Per-frame handler to draw icons +// cleanup +if (!isNil QGVAR(drawIconsPfh)) then { + [GVAR(drawIconsPfh)] call CBA_fnc_removePerFrameHandler; +}; +// add pfh +GVAR(drawIconsPfh) = [{ + // 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}; + private _color = GVAR(colors) select (_triageLevel - 1); + _color set [3, 0.9]; // set alpha + // draw position, slightly above the prone unit + private _drawPos = (visiblePosition _unit) vectorAdd [0, 0, 0.5]; + // draw icon + drawIcon3D [ + "\A3\ui_f\data\map\markers\military\dot_CA.paa", // icon texture + _color, // color + _drawPos, // position AGL + 1, // width + 1, // height + 0, // angle + "", // text + true // outline + // further params optional, omitted + ]; + } forEach GVAR(drawTargets); +}, 0, []] call CBA_fnc_addPerFrameHandler; + diff --git a/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf b/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf new file mode 100644 index 0000000..781227e --- /dev/null +++ b/framework/triageIcons/functions/fn_addGetEntitiesPFH.sqf @@ -0,0 +1,18 @@ +#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_initClient.sqf b/framework/triageIcons/functions/fn_initClient.sqf new file mode 100644 index 0000000..79b48ec --- /dev/null +++ b/framework/triageIcons/functions/fn_initClient.sqf @@ -0,0 +1,12 @@ +#include "..\script_component.hpp" + +// List of units to draw icons for +GVAR(drawTargets) = []; + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/triageIcons/functions/fn_updateColors.sqf b/framework/triageIcons/functions/fn_updateColors.sqf new file mode 100644 index 0000000..874c9b3 --- /dev/null +++ b/framework/triageIcons/functions/fn_updateColors.sqf @@ -0,0 +1,18 @@ +#include "..\script_component.hpp" + +// ACE Triage colors, for consistency across UIs and functions +// GVAR(colors) = [ +// (([QGVAR(setting_colorMinimal)] call CBA_settings_fnc_get) + 0.9), // TRIAGE_COLOR_MINIMAL +// (([QGVAR(setting_colorDelayed)] call CBA_settings_fnc_get) + 0.9), // TRIAGE_COLOR_DELAYED +// (([QGVAR(setting_colorImmediate)] call CBA_settings_fnc_get) + 0.9), // TRIAGE_COLOR_IMMEDIATE +// (([QGVAR(setting_colorDeceased)] call CBA_settings_fnc_get) + 0.9), // TRIAGE_COLOR_DECEASED +// (([QGVAR(setting_colorNone)] call CBA_settings_fnc_get) + 0) // TRIAGE_COLOR_NONE +// ]; + +GVAR(colors) = [ + ([QGVAR(setting_colorMinimal)] call CBA_settings_fnc_get), // TRIAGE_COLOR_MINIMAL + ([QGVAR(setting_colorDelayed)] call CBA_settings_fnc_get), // TRIAGE_COLOR_DELAYED + ([QGVAR(setting_colorImmediate)] call CBA_settings_fnc_get), // TRIAGE_COLOR_IMMEDIATE + ([QGVAR(setting_colorDeceased)] call CBA_settings_fnc_get), // TRIAGE_COLOR_DECEASED + ([QGVAR(setting_colorNone)] call CBA_settings_fnc_get) // TRIAGE_COLOR_NONE +]; \ No newline at end of file diff --git a/framework/triageIcons/script_component.hpp b/framework/triageIcons/script_component.hpp new file mode 100644 index 0000000..17b82f3 --- /dev/null +++ b/framework/triageIcons/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT triageIcons +#define COMPONENT_BEAUTIFIED Triage Icons +#include "../script_mod.hpp" \ No newline at end of file diff --git a/functions/vehicleFlags/fn_getActionsFlagCategories.sqf b/framework/vehicleFlags/functions/fn_getActionsFlagCategories.sqf similarity index 100% rename from functions/vehicleFlags/fn_getActionsFlagCategories.sqf rename to framework/vehicleFlags/functions/fn_getActionsFlagCategories.sqf diff --git a/functions/vehicleFlags/fn_getVehicleFlagsCfg.sqf b/framework/vehicleFlags/functions/fn_getVehicleFlagsCfg.sqf similarity index 100% rename from functions/vehicleFlags/fn_getVehicleFlagsCfg.sqf rename to framework/vehicleFlags/functions/fn_getVehicleFlagsCfg.sqf diff --git a/functions/vehicleFlags/fn_initVehicleFlags.sqf b/framework/vehicleFlags/functions/fn_initClient.sqf similarity index 87% rename from functions/vehicleFlags/fn_initVehicleFlags.sqf rename to framework/vehicleFlags/functions/fn_initClient.sqf index 32f2952..7ebe0fd 100644 --- a/functions/vehicleFlags/fn_initVehicleFlags.sqf +++ b/framework/vehicleFlags/functions/fn_initClient.sqf @@ -1,6 +1,8 @@ if (!hasInterface) exitWith {}; -private _vehicleFlagsCfg = call milsim_vehicleFlags_fnc_getVehicleFlagsCfg; +#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; @@ -20,6 +22,8 @@ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_ //////////////////////////////////////////////////////////////////////// [_parentClass, "InitPost", { + + //////////////////////////////////////////////////////////////////////// // create the root action //////////////////////////////////////////////////////////////////////// @@ -34,7 +38,7 @@ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_ // _params params ["_parentActionID", "_flagCategories"]; // check if vehicle is excluded - private _excluded = [typeOf _target] call milsim_vehicleFlags_fnc_isClassExcluded; + private _excluded = [typeOf _target] call FUNC(isClassExcluded); if (_excluded || !alive _target) exitWith {false}; true; @@ -44,13 +48,17 @@ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_ // create the flag category actions (with nested flag actions) //////////////////////////////////////////////////////////////////////// params ["_target", "_player", "_params"]; - _params params ["_rootActionID", "_flagCategoryCfgs"]; + _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 milsim_vehicleFlags_fnc_getActionsFlagCategories; + [_rootActionID, _flagCategoryCfgs] call FUNC(getActionsFlagCategories); }, // child code - [_rootActionID, _flagCategoryCfgs], // params + [_rootActionID], // params nil, // position 4, // distance [false, false, false, false, false], // other params diff --git a/functions/vehicleFlags/fn_isClassExcluded.sqf b/framework/vehicleFlags/functions/fn_isClassExcluded.sqf similarity index 100% rename from functions/vehicleFlags/fn_isClassExcluded.sqf rename to framework/vehicleFlags/functions/fn_isClassExcluded.sqf diff --git a/framework/vehicleFlags/script_component.hpp b/framework/vehicleFlags/script_component.hpp new file mode 100644 index 0000000..bba2e0d --- /dev/null +++ b/framework/vehicleFlags/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT vehicleFlags +#define COMPONENT_BEAUTIFIED Vehicle Flags +#include "../script_mod.hpp" \ No newline at end of file diff --git a/framework/x/cba/addons/main/script_macros_common.hpp b/framework/x/cba/addons/main/script_macros_common.hpp new file mode 100644 index 0000000..c2e5d56 --- /dev/null +++ b/framework/x/cba/addons/main/script_macros_common.hpp @@ -0,0 +1,1835 @@ +/* + Header: script_macros_common.hpp + + Description: + A general set of useful macro functions for use by CBA itself or by any module that uses CBA. + + Authors: + Sickboy and Spooner +*/ + +/* **************************************************** + New - Should be exported to general addon + Aim: + - Simplify (shorten) the amount of characters required for repetitive tasks + - Provide a solid structure that can be dynamic and easy editable (Which sometimes means we cannot adhere to Aim #1 ;-) + An example is the path that is built from defines. Some available in this file, others in mods and addons. + + Follows Standard: + Object variables: PREFIX_COMPONENT + Main-object variables: PREFIX_main + Paths: MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\SCRIPTNAME.sqf + e.g: x\six\addons\sys_menu\fDate.sqf + + Usage: + define PREFIX and COMPONENT, then include this file + (Note, you could have a main addon for your mod, define the PREFIX in a macros.hpp, + and include this script_macros_common.hpp file. + Then in your addons, add a component.hpp, define the COMPONENT, + and include your mod's script_macros.hpp + In your scripts you can then include the addon's component.hpp with relative path) + + use in subcomponents (subconfigs) + define SUBCOMPONENT and include parent component's script_component.hpp + currently only supported by SUBADDON, additional macros may be added in the future + + TODO: + - Try only to use 1 string type " vs ' + - Evaluate double functions, and simplification + - Evaluate naming scheme; current = prototype + - Evaluate "Debug" features.. + - Evaluate "create mini function per precompiled script, that will load the script on first usage, rather than on init" + - Also saw "Namespace" typeName, evaluate which we need :P + - Single/Multi player gamelogics? (Incase of MP, you would want only 1 gamelogic per component, which is pv'ed from server, etc) + */ + +#ifndef MAINPREFIX + #define MAINPREFIX x +#endif + +#ifndef SUBPREFIX + #define SUBPREFIX addons +#endif + +#ifndef MAINLOGIC + #define MAINLOGIC main +#endif + +#define ADDON DOUBLES(PREFIX,COMPONENT) +#define MAIN_ADDON DOUBLES(PREFIX,main) + +#ifdef SUBCOMPONENT + #define SUBADDON DOUBLES(ADDON,SUBCOMPONENT) +#endif + +/* ------------------------------------------- +Macro: VERSION_CONFIG + Define CBA Versioning System config entries. + + VERSION should be a floating-point number (1 separator). + VERSION_STR is a string representation of the version. + VERSION_AR is an array representation of the version. + + VERSION must always be defined, otherwise it is 0. + VERSION_STR and VERSION_AR default to VERSION if undefined. + +Parameters: + None + +Example: + (begin example) + #define VERSION 1.0 + #define VERSION_STR 1.0.1 + #define VERSION_AR 1,0,1 + + class CfgPatches { + class MyMod_main { + VERSION_CONFIG; + }; + }; + (end) + +Author: + ?, Jonpas +------------------------------------------- */ +#ifndef VERSION + #define VERSION 0 +#endif + +#ifndef VERSION_STR + #define VERSION_STR VERSION +#endif + +#ifndef VERSION_AR + #define VERSION_AR VERSION +#endif + +#ifndef VERSION_CONFIG + #define VERSION_CONFIG version = VERSION; versionStr = QUOTE(VERSION_STR); versionAr[] = {VERSION_AR} +#endif + +/* ------------------------------------------- +Group: Debugging +------------------------------------------- */ + +/* ------------------------------------------- +Macros: DEBUG_MODE_x + Managing debugging based on debug level. + + According to the *highest* level of debugging that has been defined *before* script_macros_common.hpp is included, + only the appropriate debugging commands will be functional. With no level explicitely defined, assume DEBUG_MODE_NORMAL. + + DEBUG_MODE_FULL - Full debugging output. + DEBUG_MODE_NORMAL - All debugging except and (Default setting if none specified). + DEBUG_MODE_MINIMAL - Only and enabled. + +Examples: + In order to turn on full debugging for a single file, + (begin example) + // Top of individual script file. + #define DEBUG_MODE_FULL + + (end) + + In order to force minimal debugging for a single component, + (begin example) + // Top of addons\\script_component.hpp + // Ensure that any FULL and NORMAL setting from the individual files are undefined and MINIMAL is set. + #ifdef DEBUG_MODE_FULL + #undef DEBUG_MODE_FULL + #endif + #ifdef DEBUG_MODE_NORMAL + #undef DEBUG_MODE_NORMAL + #endif + #ifndef DEBUG_MODE_MINIMAL + #define DEBUG_MODE_MINIMAL + #endif + + (end) + + In order to turn on full debugging for a whole addon, + (begin example) + // Top of addons\main\script_macros.hpp + #ifndef DEBUG_MODE_FULL + #define DEBUG_MODE_FULL + #endif + + (end) + +Author: + Spooner +------------------------------------------- */ + +// If DEBUG_MODE_FULL, then also enable DEBUG_MODE_NORMAL. +#ifdef DEBUG_MODE_FULL +#define DEBUG_MODE_NORMAL +#endif + +// If DEBUG_MODE_NORMAL, then also enable DEBUG_MODE_MINIMAL. +#ifdef DEBUG_MODE_NORMAL +#define DEBUG_MODE_MINIMAL +#endif + +// If no debug modes specified, use DEBUG_MODE_NORMAL (+ DEBUG_MODE_MINIMAL). +#ifndef DEBUG_MODE_MINIMAL +#define DEBUG_MODE_NORMAL +#define DEBUG_MODE_MINIMAL +#endif + +#define LOG_SYS_FORMAT(LEVEL,MESSAGE) format ['[%1] (%2) %3: %4', toUpper 'PREFIX', 'COMPONENT', LEVEL, MESSAGE] + +#ifdef DEBUG_SYNCHRONOUS +#define LOG_SYS(LEVEL,MESSAGE) diag_log text LOG_SYS_FORMAT(LEVEL,MESSAGE) +#else +#define LOG_SYS(LEVEL,MESSAGE) LOG_SYS_FORMAT(LEVEL,MESSAGE) call CBA_fnc_log +#endif + +#define LOG_SYS_FILELINENUMBERS(LEVEL,MESSAGE) LOG_SYS(LEVEL,format [ARR_4('%1 %2:%3',MESSAGE,__FILE__,__LINE__ + 1)]) + +/* ------------------------------------------- +Macro: LOG() + Log a debug message into the RPT log. + + Only run if is defined. + +Parameters: + MESSAGE - Message to record + +Example: + (begin example) + LOG("Initiated clog-dancing simulator."); + (end) + +Author: + Spooner +------------------------------------------- */ +#ifdef DEBUG_MODE_FULL + +#define LOG(MESSAGE) LOG_SYS('LOG',MESSAGE) +#define LOG_1(MESSAGE,ARG1) LOG(FORMAT_1(MESSAGE,ARG1)) +#define LOG_2(MESSAGE,ARG1,ARG2) LOG(FORMAT_2(MESSAGE,ARG1,ARG2)) +#define LOG_3(MESSAGE,ARG1,ARG2,ARG3) LOG(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) LOG(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) LOG(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) LOG(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) LOG(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) LOG(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +#else + +#define LOG(MESSAGE) /* disabled */ +#define LOG_1(MESSAGE,ARG1) /* disabled */ +#define LOG_2(MESSAGE,ARG1,ARG2) /* disabled */ +#define LOG_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */ +#define LOG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */ +#define LOG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */ +#define LOG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */ +#define LOG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */ +#define LOG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */ + +#endif + +/* ------------------------------------------- +Macro: INFO() + Record a message without file and line number in the RPT log. + +Parameters: + MESSAGE - Message to record + +Example: + (begin example) + INFO("Mod X is loaded, do Y"); + (end) + +Author: + commy2 +------------------------------------------- */ +#define INFO(MESSAGE) LOG_SYS('INFO',MESSAGE) +#define INFO_1(MESSAGE,ARG1) INFO(FORMAT_1(MESSAGE,ARG1)) +#define INFO_2(MESSAGE,ARG1,ARG2) INFO(FORMAT_2(MESSAGE,ARG1,ARG2)) +#define INFO_3(MESSAGE,ARG1,ARG2,ARG3) INFO(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define INFO_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) INFO(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define INFO_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) INFO(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define INFO_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) INFO(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define INFO_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) INFO(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define INFO_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) INFO(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +/* ------------------------------------------- +Macro: WARNING() + Record a non-critical error in the RPT log. + + Only run if or higher is defined. + +Parameters: + MESSAGE - Message to record + +Example: + (begin example) + WARNING("This function has been deprecated. Please don't use it in future!"); + (end) + +Author: + Spooner +------------------------------------------- */ +#ifdef DEBUG_MODE_NORMAL + +#define WARNING(MESSAGE) LOG_SYS('WARNING',MESSAGE) +#define WARNING_1(MESSAGE,ARG1) WARNING(FORMAT_1(MESSAGE,ARG1)) +#define WARNING_2(MESSAGE,ARG1,ARG2) WARNING(FORMAT_2(MESSAGE,ARG1,ARG2)) +#define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) WARNING(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) WARNING(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) WARNING(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) WARNING(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) WARNING(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) WARNING(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +#else + +#define WARNING(MESSAGE) /* disabled */ +#define WARNING_1(MESSAGE,ARG1) /* disabled */ +#define WARNING_2(MESSAGE,ARG1,ARG2) /* disabled */ +#define WARNING_3(MESSAGE,ARG1,ARG2,ARG3) /* disabled */ +#define WARNING_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) /* disabled */ +#define WARNING_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) /* disabled */ +#define WARNING_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) /* disabled */ +#define WARNING_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) /* disabled */ +#define WARNING_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) /* disabled */ + +#endif + +/* ------------------------------------------- +Macro: ERROR() + Record a critical error in the RPT log. + +Parameters: + MESSAGE - Message to record + +Example: + (begin example) + ERROR("value of frog not found in config ...yada...yada..."); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ERROR(MESSAGE) LOG_SYS('ERROR',MESSAGE) +#define ERROR_1(MESSAGE,ARG1) ERROR(FORMAT_1(MESSAGE,ARG1)) +#define ERROR_2(MESSAGE,ARG1,ARG2) ERROR(FORMAT_2(MESSAGE,ARG1,ARG2)) +#define ERROR_3(MESSAGE,ARG1,ARG2,ARG3) ERROR(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define ERROR_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define ERROR_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define ERROR_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define ERROR_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define ERROR_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +/* ------------------------------------------- +Macro: ERROR_MSG() + Record a critical error in the RPT log and display on screen error message. + + Newlines (\n) in the MESSAGE will be put on separate lines. + +Parameters: + MESSAGE - Message to record + +Example: + (begin example) + ERROR_MSG("value of frog not found in config ...yada...yada..."); + (end) + +Author: + commy2 +------------------------------------------- */ +#define ERROR_MSG(MESSAGE) ['PREFIX', 'COMPONENT', nil, MESSAGE, __FILE__, __LINE__ + 1] call CBA_fnc_error +#define ERROR_MSG_1(MESSAGE,ARG1) ERROR_MSG(FORMAT_1(MESSAGE,ARG1)) +#define ERROR_MSG_2(MESSAGE,ARG1,ARG2) ERROR_MSG(FORMAT_2(MESSAGE,ARG1,ARG2)) +#define ERROR_MSG_3(MESSAGE,ARG1,ARG2,ARG3) ERROR_MSG(FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define ERROR_MSG_4(MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR_MSG(FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define ERROR_MSG_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR_MSG(FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define ERROR_MSG_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR_MSG(FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define ERROR_MSG_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR_MSG(FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define ERROR_MSG_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR_MSG(FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +/* ------------------------------------------- +Macro: ERROR_WITH_TITLE() + Record a critical error in the RPT log. + + The title can be specified (in the heading is always just "ERROR") + Newlines (\n) in the MESSAGE will be put on separate lines. + +Parameters: + TITLE - Title of error message + MESSAGE - Body of error message + +Example: + (begin example) + ERROR_WITH_TITLE("Value not found","Value of frog not found in config ...yada...yada..."); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ERROR_WITH_TITLE(TITLE,MESSAGE) ['PREFIX', 'COMPONENT', TITLE, MESSAGE, __FILE__, __LINE__ + 1] call CBA_fnc_error +#define ERROR_WITH_TITLE_1(TITLE,MESSAGE,ARG1) ERROR_WITH_TITLE(TITLE,FORMAT_1(MESSAGE,ARG1)) +#define ERROR_WITH_TITLE_2(TITLE,MESSAGE,ARG1,ARG2) ERROR_WITH_TITLE(TITLE,FORMAT_2(MESSAGE,ARG1,ARG2)) +#define ERROR_WITH_TITLE_3(TITLE,MESSAGE,ARG1,ARG2,ARG3) ERROR_WITH_TITLE(TITLE,FORMAT_3(MESSAGE,ARG1,ARG2,ARG3)) +#define ERROR_WITH_TITLE_4(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4) ERROR_WITH_TITLE(TITLE,FORMAT_4(MESSAGE,ARG1,ARG2,ARG3,ARG4)) +#define ERROR_WITH_TITLE_5(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5) ERROR_WITH_TITLE(TITLE,FORMAT_5(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5)) +#define ERROR_WITH_TITLE_6(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ERROR_WITH_TITLE(TITLE,FORMAT_6(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6)) +#define ERROR_WITH_TITLE_7(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ERROR_WITH_TITLE(TITLE,FORMAT_7(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7)) +#define ERROR_WITH_TITLE_8(TITLE,MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ERROR_WITH_TITLE(TITLE,FORMAT_8(MESSAGE,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8)) + +/* ------------------------------------------- +Macro: MESSAGE_WITH_TITLE() + Record a single line in the RPT log. + +Parameters: + TITLE - Title of log message + MESSAGE - Body of message + +Example: + (begin example) + MESSAGE_WITH_TITLE("Value found","Value of frog found in config "); + (end) + +Author: + Killswitch +------------------------------------------- */ +#define MESSAGE_WITH_TITLE(TITLE,MESSAGE) LOG_SYS_FILELINENUMBERS(TITLE,MESSAGE) + +/* ------------------------------------------- +Macro: RETDEF() + If a variable is undefined, return the default value. Otherwise, return the + variable itself. + +Parameters: + VARIABLE - the variable to check + DEFAULT_VALUE - the default value to use if variable is undefined + +Example: + (begin example) + // _var is undefined + hintSilent format ["_var=%1", RETDEF(_var,5)]; // "_var=5" + _var = 7; + hintSilent format ["_var=%1", RETDEF(_var,5)]; // "_var=7" + (end example) +Author: + 654wak654 +------------------------------------------- */ +#define RETDEF(VARIABLE,DEFAULT_VALUE) (if (isNil {VARIABLE}) then [{DEFAULT_VALUE}, {VARIABLE}]) + +/* ------------------------------------------- +Macro: RETNIL() + If a variable is undefined, return the value nil. Otherwise, return the + variable itself. + +Parameters: + VARIABLE - the variable to check + +Example: + (begin example) + // _var is undefined + hintSilent format ["_var=%1", RETNIL(_var)]; // "_var=any" + (end example) + +Author: + Alef (see CBA issue #8514) +------------------------------------------- */ +#define RETNIL(VARIABLE) RETDEF(VARIABLE,nil) + +/* ------------------------------------------- +Macros: TRACE_n() + Log a message and 1-8 variables to the RPT log. + + Only run if is defined. + + TRACE_1(MESSAGE,A) - Log 1 variable. + TRACE_2(MESSAGE,A,B) - Log 2 variables. + TRACE_3(MESSAGE,A,B,C) - Log 3 variables. + TRACE_4(MESSAGE,A,B,C,D) - Log 4 variables. + TRACE_5(MESSAGE,A,B,C,D,E) - Log 5 variables. + TRACE_6(MESSAGE,A,B,C,D,E,F) - Log 6 variables. + TRACE_7(MESSAGE,A,B,C,D,E,F,G) - Log 7 variables. + TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) - Log 8 variables. + TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) - Log 9 variables. + +Parameters: + MESSAGE - Message to add to the trace [String] + A..H - Variable names to log values of [Any] + +Example: + (begin example) + TRACE_3("After takeoff",_vehicle player,getPos (_vehicle player), getPosASL (_vehicle player)); + (end) + +Author: + Spooner +------------------------------------------- */ +#define PFORMAT_1(MESSAGE,A) \ + format ['%1: A=%2', MESSAGE, RETNIL(A)] + +#define PFORMAT_2(MESSAGE,A,B) \ + format ['%1: A=%2, B=%3', MESSAGE, RETNIL(A), RETNIL(B)] + +#define PFORMAT_3(MESSAGE,A,B,C) \ + format ['%1: A=%2, B=%3, C=%4', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C)] + +#define PFORMAT_4(MESSAGE,A,B,C,D) \ + format ['%1: A=%2, B=%3, C=%4, D=%5', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D)] + +#define PFORMAT_5(MESSAGE,A,B,C,D,E) \ + format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E)] + +#define PFORMAT_6(MESSAGE,A,B,C,D,E,F) \ + format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F)] + +#define PFORMAT_7(MESSAGE,A,B,C,D,E,F,G) \ + format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G)] + +#define PFORMAT_8(MESSAGE,A,B,C,D,E,F,G,H) \ + format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8, H=%9', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G), RETNIL(H)] + +#define PFORMAT_9(MESSAGE,A,B,C,D,E,F,G,H,I) \ + format ['%1: A=%2, B=%3, C=%4, D=%5, E=%6, F=%7, G=%8, H=%9, I=%10', MESSAGE, RETNIL(A), RETNIL(B), RETNIL(C), RETNIL(D), RETNIL(E), RETNIL(F), RETNIL(G), RETNIL(H), RETNIL(I)] + + +#ifdef DEBUG_MODE_FULL +#define TRACE_1(MESSAGE,A) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_1(str diag_frameNo + ' ' + (MESSAGE),A)) +#define TRACE_2(MESSAGE,A,B) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_2(str diag_frameNo + ' ' + (MESSAGE),A,B)) +#define TRACE_3(MESSAGE,A,B,C) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_3(str diag_frameNo + ' ' + (MESSAGE),A,B,C)) +#define TRACE_4(MESSAGE,A,B,C,D) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_4(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D)) +#define TRACE_5(MESSAGE,A,B,C,D,E) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_5(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E)) +#define TRACE_6(MESSAGE,A,B,C,D,E,F) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_6(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F)) +#define TRACE_7(MESSAGE,A,B,C,D,E,F,G) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_7(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G)) +#define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_8(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H)) +#define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) LOG_SYS_FILELINENUMBERS('TRACE',PFORMAT_9(str diag_frameNo + ' ' + (MESSAGE),A,B,C,D,E,F,G,H,I)) +#else +#define TRACE_1(MESSAGE,A) /* disabled */ +#define TRACE_2(MESSAGE,A,B) /* disabled */ +#define TRACE_3(MESSAGE,A,B,C) /* disabled */ +#define TRACE_4(MESSAGE,A,B,C,D) /* disabled */ +#define TRACE_5(MESSAGE,A,B,C,D,E) /* disabled */ +#define TRACE_6(MESSAGE,A,B,C,D,E,F) /* disabled */ +#define TRACE_7(MESSAGE,A,B,C,D,E,F,G) /* disabled */ +#define TRACE_8(MESSAGE,A,B,C,D,E,F,G,H) /* disabled */ +#define TRACE_9(MESSAGE,A,B,C,D,E,F,G,H,I) /* disabled */ +#endif + +/* ------------------------------------------- +Group: General +------------------------------------------- */ + +// ************************************* +// Internal Functions +#define DOUBLES(var1,var2) var1##_##var2 +#define TRIPLES(var1,var2,var3) var1##_##var2##_##var3 +#define QUOTE(var1) #var1 + +#ifdef MODULAR + #define COMPONENT_T DOUBLES(t,COMPONENT) + #define COMPONENT_M DOUBLES(m,COMPONENT) + #define COMPONENT_S DOUBLES(s,COMPONENT) + #define COMPONENT_C DOUBLES(c,COMPONENT) + #define COMPONENT_F COMPONENT_C +#else + #define COMPONENT_T COMPONENT + #define COMPONENT_M COMPONENT + #define COMPONENT_S COMPONENT + #define COMPONENT_F COMPONENT + #define COMPONENT_C COMPONENT +#endif + +/* ------------------------------------------- +Macro: INC() + +Description: + Increase a number by one. + +Parameters: + VAR - Variable to increment [Number] + +Example: + (begin example) + _counter = 0; + INC(_counter); + // _counter => 1 + (end) + +Author: + Spooner +------------------------------------------- */ +#define INC(var) var = (var) + 1 + +/* ------------------------------------------- +Macro: DEC() + +Description: + Decrease a number by one. + +Parameters: + VAR - Variable to decrement [Number] + +Example: + (begin example) + _counter = 99; + DEC(_counter); + // _counter => 98 + (end) + +Author: + Spooner +------------------------------------------- */ +#define DEC(var) var = (var) - 1 + +/* ------------------------------------------- +Macro: ADD() + +Description: + Add a value to a variable. Variable and value should be both Numbers or both Strings. + +Parameters: + VAR - Variable to add to [Number or String] + VALUE - Value to add [Number or String] + +Examples: + (begin example) + _counter = 2; + ADD(_counter,3); + // _counter => 5 + (end) + (begin example) + _str = "hello"; + ADD(_str," "); + ADD(_str,"Fred"); + // _str => "hello Fred" + (end) + +Author: + Sickboy +------------------------------------------- */ +#define ADD(var1,var2) var1 = (var1) + (var2) + +/* ------------------------------------------- +Macro: SUB() + +Description: + Subtract a value from a number variable. VAR and VALUE should both be Numbers. + +Parameters: + VAR - Variable to subtract from [Number] + VALUE - Value to subtract [Number] + +Examples: + (begin example) + _numChickens = 2; + SUB(_numChickens,3); + // _numChickens => -1 + (end) +------------------------------------------- */ +#define SUB(var1,var2) var1 = (var1) - (var2) + +/* ------------------------------------------- +Macro: REM() + +Description: + Remove an element from an array each time it occurs. + + This recreates the entire array, so use BIS_fnc_removeIndex if modification of the original array is required + or if only one of the elements that matches ELEMENT needs to be removed. + +Parameters: + ARRAY - Array to modify [Array] + ELEMENT - Element to remove [Any] + +Examples: + (begin example) + _array = [1, 2, 3, 4, 3, 8]; + REM(_array,3); + // _array = [1, 2, 4, 8]; + (end) + +Author: + Spooner +------------------------------------------- */ +#define REM(var1,var2) SUB(var1,[var2]) + +/* ------------------------------------------- +Macro: PUSH() + +Description: + Appends a single value onto the end of an ARRAY. Change is made to the ARRAY itself, not creating a new array. + +Parameters: + ARRAY - Array to push element onto [Array] + ELEMENT - Element to push [Any] + +Examples: + (begin example) + _fish = ["blue", "green", "smelly"]; + PUSH(_fish,"monkey-flavoured"); + // _fish => ["blue", "green", "smelly", "monkey-flavoured"] + (end) + +Author: + Spooner +------------------------------------------- */ +#define PUSH(var1,var2) (var1) pushBack (var2) + +/* ------------------------------------------- +Macro: MAP() +Description: + Applies given code to each element of the array, then assigns the + resulting array to the original +Parameters: + ARRAY - Array to be modified + CODE - Code that'll be applied to each element of the array. +Example: + (begin example) + _array = [1, 2, 3, 4, 3, 8]; + MAP(_array,_x + 1); + // _array is now [2, 3, 4, 5, 4, 9]; + (end) +Author: + 654wak654 +------------------------------------------- */ +#define MAP(ARR,CODE) ARR = ARR apply {CODE} + +/* ------------------------------------------- +Macro: FILTER() +Description: + Filters an array based on given code, then assigns the resulting array + to the original +Parameters: + ARRAY - Array to be filtered + CODE - Condition to pick elements +Example: + (begin example) + _array = [1, 2, 3, 4, 3, 8]; + FILTER(_array,_x % 2 == 0) + // _array is now [2, 4, 8]; + (end) +Author: + Commy2 +------------------------------------------- */ +#define FILTER(ARR,CODE) ARR = ARR select {CODE} + +/* ------------------------------------------- +Macro: UNIQUE() +Description: + Removes duplicate values in given array +Parameters: + ARRAY - The array to be modified +Example: + (begin example) + _someArray = [4, 4, 5, 5, 5, 2]; + UNIQUE(_someArray); + // _someArray is now [4, 5, 2] + (end) +Author: + Commy2 +------------------------------------------- */ +#define UNIQUE(ARR) ARR = ARR arrayIntersect ARR + +/* ------------------------------------------- +Macro: INTERSECTION() +Description: + Finds unique common elements between two arrays and assigns them + to the first array +Parameters: + ARRAY0 - The array to be modified + ARRAY1 - The array to find intersections with +Example: + (begin example) + _someArray = [1, 2, 3, 4, 5, 5]; + _anotherArray = [4, 5, 6, 7]; + INTERSECTION(_someArray,_anotherArray); + // _someArray is now [4, 5] + (end) +Author: + 654wak654 +------------------------------------------- */ +#define INTERSECTION(ARG0,ARG1) ARG0 = ARG0 arrayIntersect (ARG1) + +/* ------------------------------------------- +Macro: ISNILS() + +Description: + Sets a variable with a value, but only if it is undefined. + +Parameters: + VARIABLE - Variable to set [Any, not nil] + DEFAULT_VALUE - Value to set VARIABLE to if it is undefined [Any, not nil] + +Examples: + (begin example) + // _fish is undefined + ISNILS(_fish,0); + // _fish => 0 + (end) + (begin example) + _fish = 12; + // ...later... + ISNILS(_fish,0); + // _fish => 12 + (end) + +Author: + Sickboy +------------------------------------------- */ +#define ISNILS(VARIABLE,DEFAULT_VALUE) if (isNil #VARIABLE) then { VARIABLE = DEFAULT_VALUE } +#define ISNILS2(var1,var2,var3,var4) ISNILS(TRIPLES(var1,var2,var3),var4) +#define ISNILS3(var1,var2,var3) ISNILS(DOUBLES(var1,var2),var3) +#define ISNIL(var1,var2) ISNILS2(PREFIX,COMPONENT,var1,var2) +#define ISNILMAIN(var1,var2) ISNILS3(PREFIX,var1,var2) + +#define CREATELOGICS(var1,var2) var1##_##var2 = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit ["LOGIC", [0, 0, 0], [], 0, "NONE"] +#define CREATELOGICLOCALS(var1,var2) var1##_##var2 = "LOGIC" createVehicleLocal [0, 0, 0] +#define CREATELOGICGLOBALS(var1,var2) var1##_##var2 = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit ["LOGIC", [0, 0, 0], [], 0, "NONE"]; publicVariable QUOTE(DOUBLES(var1,var2)) +#define CREATELOGICGLOBALTESTS(var1,var2) var1##_##var2 = ([sideLogic] call CBA_fnc_getSharedGroup) createUnit [QUOTE(DOUBLES(ADDON,logic)), [0, 0, 0], [], 0, "NONE"] + +#define GETVARS(var1,var2,var3) (var1##_##var2 getVariable #var3) +#define GETVARMAINS(var1,var2) GETVARS(var1,MAINLOGIC,var2) + +#ifndef PATHTO_SYS + #define PATHTO_SYS(var1,var2,var3) \MAINPREFIX\var1\SUBPREFIX\var2\var3.sqf +#endif +#ifndef PATHTOF_SYS + #define PATHTOF_SYS(var1,var2,var3) \MAINPREFIX\var1\SUBPREFIX\var2\var3 +#endif + +#ifndef PATHTOF2_SYS + #define PATHTOF2_SYS(var1,var2,var3) MAINPREFIX\var1\SUBPREFIX\var2\var3 +#endif + +#define PATHTO_R(var1) PATHTOF2_SYS(PREFIX,COMPONENT_C,var1) +#define PATHTO_T(var1) PATHTOF_SYS(PREFIX,COMPONENT_T,var1) +#define PATHTO_M(var1) PATHTOF_SYS(PREFIX,COMPONENT_M,var1) +#define PATHTO_S(var1) PATHTOF_SYS(PREFIX,COMPONENT_S,var1) +#define PATHTO_C(var1) PATHTOF_SYS(PREFIX,COMPONENT_C,var1) +#define PATHTO_F(var1) PATHTO_SYS(PREFIX,COMPONENT_F,var1) + +// Already quoted "" +#define QPATHTO_R(var1) QUOTE(PATHTO_R(var1)) +#define QPATHTO_T(var1) QUOTE(PATHTO_T(var1)) +#define QPATHTO_M(var1) QUOTE(PATHTO_M(var1)) +#define QPATHTO_S(var1) QUOTE(PATHTO_S(var1)) +#define QPATHTO_C(var1) QUOTE(PATHTO_C(var1)) +#define QPATHTO_F(var1) QUOTE(PATHTO_F(var1)) + +// This only works for binarized configs after recompiling the pbos +// TODO: Reduce amount of calls / code.. +#define COMPILE_FILE2_CFG_SYS(var1) compile preprocessFileLineNumbers var1 +#define COMPILE_FILE2_SYS(var1) COMPILE_FILE2_CFG_SYS(var1) + +#define COMPILE_FILE_SYS(var1,var2,var3) COMPILE_FILE2_SYS('PATHTO_SYS(var1,var2,var3)') +#define COMPILE_FILE_CFG_SYS(var1,var2,var3) COMPILE_FILE2_CFG_SYS('PATHTO_SYS(var1,var2,var3)') + +#define SETVARS(var1,var2) var1##_##var2 setVariable +#define SETVARMAINS(var1) SETVARS(var1,MAINLOGIC) +#define GVARMAINS(var1,var2) var1##_##var2 +#define CFGSETTINGSS(var1,var2) configFile >> "CfgSettings" >> #var1 >> #var2 +//#define SETGVARS(var1,var2,var3) var1##_##var2##_##var3 = +//#define SETGVARMAINS(var1,var2) var1##_##var2 = + +// Compile-Once, JIT: On first use. +// #define PREPMAIN_SYS(var1,var2,var3) var1##_fnc_##var3 = { var1##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)); if (isNil "_this") then { call var1##_fnc_##var3 } else { _this call var1##_fnc_##var3 } } +// #define PREP_SYS(var1,var2,var3) var1##_##var2##_fnc_##var3 = { var1##_##var2##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)); if (isNil "_this") then { call var1##_##var2##_fnc_##var3 } else { _this call var1##_##var2##_fnc_##var3 } } +// #define PREP_SYS2(var1,var2,var3,var4) var1##_##var2##_fnc_##var4 = { var1##_##var2##_fnc_##var4 = COMPILE_FILE_SYS(var1,var3,DOUBLES(fnc,var4)); if (isNil "_this") then { call var1##_##var2##_fnc_##var4 } else { _this call var1##_##var2##_fnc_##var4 } } + +// Compile-Once, at Macro. As opposed to Compile-Once, on first use. +#define PREPMAIN_SYS(var1,var2,var3) var1##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)) +#define PREP_SYS(var1,var2,var3) var1##_##var2##_fnc_##var3 = COMPILE_FILE_SYS(var1,var2,DOUBLES(fnc,var3)) +#define PREP_SYS2(var1,var2,var3,var4) var1##_##var2##_fnc_##var4 = COMPILE_FILE_SYS(var1,var3,DOUBLES(fnc,var4)) + +#define LSTR(var1) TRIPLES(ADDON,STR,var1) + +#ifndef DEBUG_SETTINGS + #define DEBUG_SETTINGS [false, true, false] +#endif + +#define MSG_INIT QUOTE(Initializing: ADDON version: VERSION) + +// ************************************* +// User Functions +#define CFGSETTINGS CFGSETTINGSS(PREFIX,COMPONENT) +#define PATHTO(var1) PATHTO_SYS(PREFIX,COMPONENT_F,var1) +#define PATHTOF(var1) PATHTOF_SYS(PREFIX,COMPONENT,var1) +#define PATHTOEF(var1,var2) PATHTOF_SYS(PREFIX,var1,var2) +#define QPATHTOF(var1) QUOTE(PATHTOF(var1)) +#define QPATHTOEF(var1,var2) QUOTE(PATHTOEF(var1,var2)) + +#define COMPILE_FILE(var1) COMPILE_FILE_SYS(PREFIX,COMPONENT_F,var1) +#define COMPILE_FILE_CFG(var1) COMPILE_FILE_CFG_SYS(PREFIX,COMPONENT_F,var1) +#define COMPILE_FILE2(var1) COMPILE_FILE2_SYS('var1') +#define COMPILE_FILE2_CFG(var1) COMPILE_FILE2_CFG_SYS('var1') + +#define COMPILE_SCRIPT(var1) compileScript ['PATHTO_SYS(PREFIX,COMPONENT_F,var1)'] + + +#define VERSIONING_SYS(var1) class CfgSettings { \ + class CBA { \ + class Versioning { \ + class var1 {}; \ + }; \ + }; \ +}; + +#define VERSIONING VERSIONING_SYS(PREFIX) + +/* ------------------------------------------- +Macro: GVAR() + Get full variable identifier for a global variable owned by this component. + +Parameters: + VARIABLE - Partial name of global variable owned by this component [Any]. + +Example: + (begin example) + GVAR(frog) = 12; + // In SPON_FrogDancing component, equivalent to SPON_FrogDancing_frog = 12 + (end) + +Author: + Sickboy +------------------------------------------- */ +#define GVAR(var1) DOUBLES(ADDON,var1) +#define EGVAR(var1,var2) TRIPLES(PREFIX,var1,var2) +#define QGVAR(var1) QUOTE(GVAR(var1)) +#define QEGVAR(var1,var2) QUOTE(EGVAR(var1,var2)) +#define QQGVAR(var1) QUOTE(QGVAR(var1)) +#define QQEGVAR(var1,var2) QUOTE(QEGVAR(var1,var2)) + +/* ------------------------------------------- +Macro: GVARMAIN() + Get full variable identifier for a global variable owned by this addon. + +Parameters: + VARIABLE - Partial name of global variable owned by this addon [Any]. + +Example: + (begin example) + GVARMAIN(frog) = 12; + // In SPON_FrogDancing component, equivalent to SPON_frog = 12 + (end) + +Author: + Sickboy +------------------------------------------- */ +#define GVARMAIN(var1) GVARMAINS(PREFIX,var1) +#define QGVARMAIN(var1) QUOTE(GVARMAIN(var1)) +#define QQGVARMAIN(var1) QUOTE(QGVARMAIN(var1)) +// TODO: What's this? +#define SETTINGS DOUBLES(PREFIX,settings) +#define CREATELOGIC CREATELOGICS(PREFIX,COMPONENT) +#define CREATELOGICGLOBAL CREATELOGICGLOBALS(PREFIX,COMPONENT) +#define CREATELOGICGLOBALTEST CREATELOGICGLOBALTESTS(PREFIX,COMPONENT) +#define CREATELOGICLOCAL CREATELOGICLOCALS(PREFIX,COMPONENT) +#define CREATELOGICMAIN CREATELOGICS(PREFIX,MAINLOGIC) +#define GETVAR(var1) GETVARS(PREFIX,COMPONENT,var1) +#define SETVAR SETVARS(PREFIX,COMPONENT) +#define SETVARMAIN SETVARMAINS(PREFIX) +#define IFCOUNT(var1,var2,var3) if (count var1 > var2) then { var3 = var1 select var2 }; + +/* ------------------------------------------- +Macro: PREP() + +Description: + Defines a function. + + Full file path: + '\MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\fnc_.sqf' + + Resulting function name: + 'PREFIX_COMPONENT_' + + The PREP macro should be placed in a script run by a XEH preStart and XEH preInit event. + + The PREP macro allows for CBA function caching, which drastically speeds up load times. + Beware though that function caching is enabled by default and as such to disable it, you need to + #define DISABLE_COMPILE_CACHE above your #include "script_components.hpp" include! + + The function will be defined in ui and mission namespace. It can not be overwritten without + a mission restart. + +Parameters: + FUNCTION NAME - Name of the function, unquoted + +Examples: + (begin example) + PREP(banana); + call FUNC(banana); + (end) + +Author: + dixon13 + ------------------------------------------- */ +//#define PREP(var1) PREP_SYS(PREFIX,COMPONENT_F,var1) + +#ifdef DISABLE_COMPILE_CACHE + #define PREP(var1) TRIPLES(ADDON,fnc,var1) = compile preProcessFileLineNumbers 'PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))' + #define PREPMAIN(var1) TRIPLES(PREFIX,fnc,var1) = compile preProcessFileLineNumbers 'PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))' +#else + #define PREP(var1) ['PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))', 'TRIPLES(ADDON,fnc,var1)'] call SLX_XEH_COMPILE_NEW + #define PREPMAIN(var1) ['PATHTO_SYS(PREFIX,COMPONENT_F,DOUBLES(fnc,var1))', 'TRIPLES(PREFIX,fnc,var1)'] call SLX_XEH_COMPILE_NEW +#endif + +/* ------------------------------------------- +Macro: PATHTO_FNC() + +Description: + Defines a function inside CfgFunctions. + + Full file path in addons: + '\MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\fnc_.sqf' + Define 'RECOMPILE' to enable recompiling. + Define 'SKIP_FUNCTION_HEADER' to skip adding function header. + +Parameters: + FUNCTION NAME - Name of the function, unquoted + +Examples: + (begin example) + // file name: fnc_addPerFrameHandler.sqf + class CfgFunctions { + class CBA { + class Misc { + PATHTO_FNC(addPerFrameHandler); + }; + }; + }; + // -> CBA_fnc_addPerFrameHandler + (end) + +Author: + dixon13, commy2 + ------------------------------------------- */ +#ifdef RECOMPILE + #undef RECOMPILE + #define RECOMPILE recompile = 1 +#else + #define RECOMPILE recompile = 0 +#endif +// Set function header type: -1 - no header; 0 - default header; 1 - system header. +#ifdef SKIP_FUNCTION_HEADER + #define CFGFUNCTION_HEADER headerType = -1 +#else + #define CFGFUNCTION_HEADER headerType = 0 +#endif + +#define PATHTO_FNC(func) class func {\ + file = QPATHTOF(DOUBLES(fnc,func).sqf);\ + CFGFUNCTION_HEADER;\ + RECOMPILE;\ +} + +#define FUNC(var1) TRIPLES(ADDON,fnc,var1) +#define FUNCMAIN(var1) TRIPLES(PREFIX,fnc,var1) +#define FUNC_INNER(var1,var2) TRIPLES(DOUBLES(PREFIX,var1),fnc,var2) +#define EFUNC(var1,var2) FUNC_INNER(var1,var2) +#define QFUNC(var1) QUOTE(FUNC(var1)) +#define QFUNCMAIN(var1) QUOTE(FUNCMAIN(var1)) +#define QFUNC_INNER(var1,var2) QUOTE(FUNC_INNER(var1,var2)) +#define QEFUNC(var1,var2) QUOTE(EFUNC(var1,var2)) +#define QQFUNC(var1) QUOTE(QFUNC(var1)) +#define QQFUNCMAIN(var1) QUOTE(QFUNCMAIN(var1)) +#define QQFUNC_INNER(var1,var2) QUOTE(QFUNC_INNER(var1,var2)) +#define QQEFUNC(var1,var2) QUOTE(QEFUNC(var1,var2)) + +#ifndef PRELOAD_ADDONS + #define PRELOAD_ADDONS class CfgAddons { \ + class PreloadAddons { \ + class ADDON { \ + list[]={ QUOTE(ADDON) }; \ + }; \ + }; \ +} +#endif + +/* ------------------------------------------- +Macros: ARG_#() + Select from list of array arguments + +Parameters: + VARIABLE(1-8) - elements for the list + +Author: + Rommel +------------------------------------------- */ +#define ARG_1(A,B) ((A) select (B)) +#define ARG_2(A,B,C) (ARG_1(ARG_1(A,B),C)) +#define ARG_3(A,B,C,D) (ARG_1(ARG_2(A,B,C),D)) +#define ARG_4(A,B,C,D,E) (ARG_1(ARG_3(A,B,C,D),E)) +#define ARG_5(A,B,C,D,E,F) (ARG_1(ARG_4(A,B,C,D,E),F)) +#define ARG_6(A,B,C,D,E,F,G) (ARG_1(ARG_5(A,B,C,D,E,F),G)) +#define ARG_7(A,B,C,D,E,F,G,H) (ARG_1(ARG_6(A,B,C,D,E,E,F,G),H)) +#define ARG_8(A,B,C,D,E,F,G,H,I) (ARG_1(ARG_7(A,B,C,D,E,E,F,G,H),I)) + +/* ------------------------------------------- +Macros: ARR_#() + Create list from arguments. Useful for working around , in macro parameters. + 1-8 arguments possible. + +Parameters: + VARIABLE(1-8) - elements for the list + +Author: + Nou +------------------------------------------- */ +#define ARR_1(ARG1) ARG1 +#define ARR_2(ARG1,ARG2) ARG1, ARG2 +#define ARR_3(ARG1,ARG2,ARG3) ARG1, ARG2, ARG3 +#define ARR_4(ARG1,ARG2,ARG3,ARG4) ARG1, ARG2, ARG3, ARG4 +#define ARR_5(ARG1,ARG2,ARG3,ARG4,ARG5) ARG1, ARG2, ARG3, ARG4, ARG5 +#define ARR_6(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 +#define ARR_7(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 +#define ARR_8(ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8 + +/* ------------------------------------------- +Macros: FORMAT_#(STR, ARG1) + Format - Useful for working around , in macro parameters. + 1-8 arguments possible. + +Parameters: + STRING - string used by format + VARIABLE(1-8) - elements for usage in format + +Author: + Nou & Sickboy +------------------------------------------- */ +#define FORMAT_1(STR,ARG1) format[STR, ARG1] +#define FORMAT_2(STR,ARG1,ARG2) format[STR, ARG1, ARG2] +#define FORMAT_3(STR,ARG1,ARG2,ARG3) format[STR, ARG1, ARG2, ARG3] +#define FORMAT_4(STR,ARG1,ARG2,ARG3,ARG4) format[STR, ARG1, ARG2, ARG3, ARG4] +#define FORMAT_5(STR,ARG1,ARG2,ARG3,ARG4,ARG5) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5] +#define FORMAT_6(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6] +#define FORMAT_7(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7] +#define FORMAT_8(STR,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8) format[STR, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8] + +// CONTROL(46) 12 +#define DISPLAY(A) (findDisplay A) +#define CONTROL(A) DISPLAY(A) displayCtrl + +/* ------------------------------------------- +Macros: IS_x() + Checking the data types of variables. + + IS_ARRAY() - Array + IS_BOOL() - Boolean + IS_BOOLEAN() - UI display handle(synonym for ) + IS_CODE() - Code block (i.e a compiled function) + IS_CONFIG() - Configuration + IS_CONTROL() - UI control handle. + IS_DISPLAY() - UI display handle. + IS_FUNCTION() - A compiled function (synonym for ) + IS_GROUP() - Group. + IS_INTEGER() - Is a number a whole number? + IS_LOCATION() - World location. + IS_NUMBER() - A floating point number (synonym for ) + IS_OBJECT() - World object. + IS_SCALAR() - Floating point number. + IS_SCRIPT() - A script handle (as returned by execVM and spawn commands). + IS_SIDE() - Game side. + IS_STRING() - World object. + IS_TEXT() - Structured text. + +Parameters: + VARIABLE - Variable to check if it is of a particular type [Any, not nil] + +Author: + Spooner +------------------------------------------- */ +#define IS_META_SYS(VAR,TYPE) (if (isNil {VAR}) then {false} else {(VAR) isEqualType TYPE}) +#define IS_ARRAY(VAR) IS_META_SYS(VAR,[]) +#define IS_BOOL(VAR) IS_META_SYS(VAR,false) +#define IS_CODE(VAR) IS_META_SYS(VAR,{}) +#define IS_CONFIG(VAR) IS_META_SYS(VAR,configNull) +#define IS_CONTROL(VAR) IS_META_SYS(VAR,controlNull) +#define IS_DISPLAY(VAR) IS_META_SYS(VAR,displayNull) +#define IS_GROUP(VAR) IS_META_SYS(VAR,grpNull) +#define IS_OBJECT(VAR) IS_META_SYS(VAR,objNull) +#define IS_SCALAR(VAR) IS_META_SYS(VAR,0) +#define IS_SCRIPT(VAR) IS_META_SYS(VAR,scriptNull) +#define IS_SIDE(VAR) IS_META_SYS(VAR,west) +#define IS_STRING(VAR) IS_META_SYS(VAR,"STRING") +#define IS_TEXT(VAR) IS_META_SYS(VAR,text "") +#define IS_LOCATION(VAR) IS_META_SYS(VAR,locationNull) + +#define IS_BOOLEAN(VAR) IS_BOOL(VAR) +#define IS_FUNCTION(VAR) IS_CODE(VAR) +#define IS_INTEGER(VAR) (if (IS_SCALAR(VAR)) then {floor (VAR) == (VAR)} else {false}) +#define IS_NUMBER(VAR) IS_SCALAR(VAR) + +#define FLOAT_TO_STRING(num) (if (_this == 0) then {"0"} else {str parseNumber (str (_this % _this) + str floor abs _this) + "." + (str (abs _this - floor abs _this) select [2]) + "0"}) + +/* ------------------------------------------- +Macro: SCRIPT() + Sets name of script (relies on PREFIX and COMPONENT values being #defined). + Define 'SKIP_SCRIPT_NAME' to skip adding scriptName. + +Parameters: + NAME - Name of script [Indentifier] + +Example: + (begin example) + SCRIPT(eradicateMuppets); + (end) + +Author: + Spooner +------------------------------------------- */ +#ifndef SKIP_SCRIPT_NAME + #define SCRIPT(NAME) scriptName 'PREFIX\COMPONENT\NAME' +#else + #define SCRIPT(NAME) /* nope */ +#endif + +/* ------------------------------------------- +Macros: EXPLODE_n() + DEPRECATED - Use param/params commands added in Arma 3 1.48 + + Splitting an ARRAY into a number of variables (A, B, C, etc). + + Note that this NOT does make the created variables private. + _PVT variants do. + + EXPLODE_1(ARRAY,A,B) - Split a 1-element array into separate variable. + EXPLODE_2(ARRAY,A,B) - Split a 2-element array into separate variables. + EXPLODE_3(ARRAY,A,B,C) - Split a 3-element array into separate variables. + EXPLODE_4(ARRAY,A,B,C,D) - Split a 4-element array into separate variables. + EXPLODE_5(ARRAY,A,B,C,D,E) - Split a 5-element array into separate variables. + EXPLODE_6(ARRAY,A,B,C,D,E,F) - Split a 6-element array into separate variables. + EXPLODE_7(ARRAY,A,B,C,D,E,F,G) - Split a 7-element array into separate variables. + EXPLODE_8(ARRAY,A,B,C,D,E,F,G,H) - Split a 8-element array into separate variables. + EXPLODE_9(ARRAY,A,B,C,D,E,F,G,H,I) - Split a 9-element array into separate variables. + +Parameters: + ARRAY - Array to read from [Array] + A..H - Names of variables to set from array [Identifier] + +Example: + (begin example) + _array = ["fred", 156.8, 120.9]; + EXPLODE_3(_array,_name,_height,_weight); + (end) + +Author: + Spooner +------------------------------------------- */ +#define EXPLODE_1_SYS(ARRAY,A) A = ARRAY param [0] +#define EXPLODE_1(ARRAY,A) EXPLODE_1_SYS(ARRAY,A); TRACE_1("EXPLODE_1, " + QUOTE(ARRAY),A) +#define EXPLODE_1_PVT(ARRAY,A) ARRAY params [#A]; TRACE_1("EXPLODE_1, " + QUOTE(ARRAY),A) + +#define EXPLODE_2_SYS(ARRAY,A,B) EXPLODE_1_SYS(ARRAY,A); B = ARRAY param [1] +#define EXPLODE_2(ARRAY,A,B) EXPLODE_2_SYS(ARRAY,A,B); TRACE_2("EXPLODE_2, " + QUOTE(ARRAY),A,B) +#define EXPLODE_2_PVT(ARRAY,A,B) ARRAY params [#A,#B]; TRACE_2("EXPLODE_2, " + QUOTE(ARRAY),A,B) + +#define EXPLODE_3_SYS(ARRAY,A,B,C) EXPLODE_2_SYS(ARRAY,A,B); C = ARRAY param [2] +#define EXPLODE_3(ARRAY,A,B,C) EXPLODE_3_SYS(ARRAY,A,B,C); TRACE_3("EXPLODE_3, " + QUOTE(ARRAY),A,B,C) +#define EXPLODE_3_PVT(ARRAY,A,B,C) ARRAY params [#A,#B,#C]; TRACE_3("EXPLODE_3, " + QUOTE(ARRAY),A,B,C) + +#define EXPLODE_4_SYS(ARRAY,A,B,C,D) EXPLODE_3_SYS(ARRAY,A,B,C); D = ARRAY param [3] +#define EXPLODE_4(ARRAY,A,B,C,D) EXPLODE_4_SYS(ARRAY,A,B,C,D); TRACE_4("EXPLODE_4, " + QUOTE(ARRAY),A,B,C,D) +#define EXPLODE_4_PVT(ARRAY,A,B,C,D) ARRAY params [#A,#B,#C,#D]; TRACE_4("EXPLODE_4, " + QUOTE(ARRAY),A,B,C,D) + +#define EXPLODE_5_SYS(ARRAY,A,B,C,D,E) EXPLODE_4_SYS(ARRAY,A,B,C,D); E = ARRAY param [4] +#define EXPLODE_5(ARRAY,A,B,C,D,E) EXPLODE_5_SYS(ARRAY,A,B,C,D,E); TRACE_5("EXPLODE_5, " + QUOTE(ARRAY),A,B,C,D,E) +#define EXPLODE_5_PVT(ARRAY,A,B,C,D,E) ARRAY params [#A,#B,#C,#D,#E]; TRACE_5("EXPLODE_5, " + QUOTE(ARRAY),A,B,C,D,E) + +#define EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F) EXPLODE_5_SYS(ARRAY,A,B,C,D,E); F = ARRAY param [5] +#define EXPLODE_6(ARRAY,A,B,C,D,E,F) EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F); TRACE_6("EXPLODE_6, " + QUOTE(ARRAY),A,B,C,D,E,F) +#define EXPLODE_6_PVT(ARRAY,A,B,C,D,E,F) ARRAY params [#A,#B,#C,#D,#E,#F]; TRACE_6("EXPLODE_6, " + QUOTE(ARRAY),A,B,C,D,E,F) + +#define EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G) EXPLODE_6_SYS(ARRAY,A,B,C,D,E,F); G = ARRAY param [6] +#define EXPLODE_7(ARRAY,A,B,C,D,E,F,G) EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G); TRACE_7("EXPLODE_7, " + QUOTE(ARRAY),A,B,C,D,E,F,G) +#define EXPLODE_7_PVT(ARRAY,A,B,C,D,E,F,G) ARRAY params [#A,#B,#C,#D,#E,#F,#G]; TRACE_7("EXPLODE_7, " + QUOTE(ARRAY),A,B,C,D,E,F,G) + +#define EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H) EXPLODE_7_SYS(ARRAY,A,B,C,D,E,F,G); H = ARRAY param [7] +#define EXPLODE_8(ARRAY,A,B,C,D,E,F,G,H) EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H); TRACE_8("EXPLODE_8, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H) +#define EXPLODE_8_PVT(ARRAY,A,B,C,D,E,F,G,H) ARRAY params [#A,#B,#C,#D,#E,#F,#G,#H]; TRACE_8("EXPLODE_8, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H) + +#define EXPLODE_9_SYS(ARRAY,A,B,C,D,E,F,G,H,I) EXPLODE_8_SYS(ARRAY,A,B,C,D,E,F,G,H); I = ARRAY param [8] +#define EXPLODE_9(ARRAY,A,B,C,D,E,F,G,H,I) EXPLODE_9_SYS(ARRAY,A,B,C,D,E,F,G,H,I); TRACE_9("EXPLODE_9, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H,I) +#define EXPLODE_9_PVT(ARRAY,A,B,C,D,E,F,G,H,I) ARRAY params [#A,#B,#C,#D,#E,#F,#G,#H,#I]; TRACE_9("EXPLODE_9, " + QUOTE(ARRAY),A,B,C,D,E,F,G,H,I) + +/* ------------------------------------------- +Macro: xSTRING() + Get full string identifier from a stringtable owned by this component. + +Parameters: + VARIABLE - Partial name of global variable owned by this component [Any]. + +Example: + ADDON is CBA_Balls. + (begin example) + // Localized String (localize command must still be used with it) + LSTRING(Example); // STR_CBA_Balls_Example; + // Config String (note the $) + CSTRING(Example); // $STR_CBA_Balls_Example; + (end) + +Author: + Jonpas +------------------------------------------- */ +#ifndef STRING_MACROS_GUARD +#define STRING_MACROS_GUARD + #define LSTRING(var1) QUOTE(TRIPLES(STR,ADDON,var1)) + #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)) + #define SUBCSTRING(var1) QUOTE(TRIPLES($STR,SUBADDON,var1)) + + #define LLSTRING(var1) localize QUOTE(TRIPLES(STR,ADDON,var1)) + #define LELSTRING(var1,var2) localize QUOTE(TRIPLES(STR,DOUBLES(PREFIX,var1),var2)) + #define LSUBLSTRING(var1) localize QUOTE(TRIPLES(STR,SUBADDON,var1)) +#endif + + +/* ------------------------------------------- +Group: Managing Function Parameters +------------------------------------------- */ + +/* ------------------------------------------- +Macros: PARAMS_n() + DEPRECATED - Use param/params commands added in Arma 3 1.48 + + Setting variables based on parameters passed to a function. + + Each parameter is defines as private and set to the appropriate value from _this. + + PARAMS_1(A) - Get 1 parameter from the _this array (or _this if it's not an array). + PARAMS_2(A,B) - Get 2 parameters from the _this array. + PARAMS_3(A,B,C) - Get 3 parameters from the _this array. + PARAMS_4(A,B,C,D) - Get 4 parameters from the _this array. + PARAMS_5(A,B,C,D,E) - Get 5 parameters from the _this array. + PARAMS_6(A,B,C,D,E,F) - Get 6 parameters from the _this array. + PARAMS_7(A,B,C,D,E,F,G) - Get 7 parameters from the _this array. + PARAMS_8(A,B,C,D,E,F,G,H) - Get 8 parameters from the _this array. + +Parameters: + A..H - Name of variable to read from _this [Identifier] + +Example: + A function called like this: + (begin example) + [_name,_address,_telephone] call recordPersonalDetails; + (end) + expects 3 parameters and those variables could be initialised at the start of the function definition with: + (begin example) + recordPersonalDetails = { + PARAMS_3(_name,_address,_telephone); + // Rest of function follows... + }; + (end) + +Author: + Spooner +------------------------------------------- */ +#define PARAMS_1(A) EXPLODE_1_PVT(_this,A) +#define PARAMS_2(A,B) EXPLODE_2_PVT(_this,A,B) +#define PARAMS_3(A,B,C) EXPLODE_3_PVT(_this,A,B,C) +#define PARAMS_4(A,B,C,D) EXPLODE_4_PVT(_this,A,B,C,D) +#define PARAMS_5(A,B,C,D,E) EXPLODE_5_PVT(_this,A,B,C,D,E) +#define PARAMS_6(A,B,C,D,E,F) EXPLODE_6_PVT(_this,A,B,C,D,E,F) +#define PARAMS_7(A,B,C,D,E,F,G) EXPLODE_7_PVT(_this,A,B,C,D,E,F,G) +#define PARAMS_8(A,B,C,D,E,F,G,H) EXPLODE_8_PVT(_this,A,B,C,D,E,F,G,H) +#define PARAMS_9(A,B,C,D,E,F,G,H,I) EXPLODE_9_PVT(_this,A,B,C,D,E,F,G,H,I) + +/* ------------------------------------------- +Macro: DEFAULT_PARAM() + DEPRECATED - Use param/params commands added in Arma 3 1.48 + + Getting a default function parameter. This may be used together with to have a mix of required and + optional parameters. + +Parameters: + INDEX - Index of parameter in _this [Integer, 0+] + NAME - Name of the variable to set [Identifier] + DEF_VALUE - Default value to use in case the array is too short or the value at INDEX is nil [Any] + +Example: + A function called with optional parameters: + (begin example) + [_name] call myFunction; + [_name, _numberOfLegs] call myFunction; + [_name, _numberOfLegs, _hasAHead] call myFunction; + (end) + 1 required parameter and 2 optional parameters. Those variables could be initialised at the start of the function + definition with: + (begin example) + myFunction = { + PARAMS_1(_name); + DEFAULT_PARAM(1,_numberOfLegs,2); + DEFAULT_PARAM(2,_hasAHead,true); + // Rest of function follows... + }; + (end) + +Author: + Spooner +------------------------------------------- */ +#define DEFAULT_PARAM(INDEX,NAME,DEF_VALUE) \ + private [#NAME,"_this"]; \ + ISNILS(_this,[]); \ + NAME = _this param [INDEX, DEF_VALUE]; \ + TRACE_3("DEFAULT_PARAM",INDEX,NAME,DEF_VALUE) + +/* ------------------------------------------- +Macro: KEY_PARAM() + Get value from key in _this list, return default when key is not included in list. + +Parameters: + KEY - Key name [String] + NAME - Name of the variable to set [Identifier] + DEF_VALUE - Default value to use in case key not found [ANY] + +Example: + + +Author: + Muzzleflash +------------------------------------------- */ +#define KEY_PARAM(KEY,NAME,DEF_VALUE) \ + private #NAME; \ + NAME = [toLower KEY, toUpper KEY, DEF_VALUE, RETNIL(_this)] call CBA_fnc_getArg; \ + TRACE_3("KEY_PARAM",KEY,NAME,DEF_VALUE) + +/* ------------------------------------------- +Group: Assertions +------------------------------------------- */ + +#define ASSERTION_ERROR(MESSAGE) ERROR_WITH_TITLE("Assertion failed!",MESSAGE) + +/* ------------------------------------------- +Macro: ASSERT_TRUE() + Asserts that a CONDITION is true. When an assertion fails, an error is raised with the given MESSAGE. + +Parameters: + CONDITION - Condition to assert as true [Boolean] + MESSSAGE - Message to display if (A OPERATOR B) is false [String] + +Example: + (begin example) + ASSERT_TRUE(_frogIsDead,"The frog is alive"); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ASSERT_TRUE(CONDITION,MESSAGE) \ + if (not (CONDITION)) then \ + { \ + ASSERTION_ERROR('Assertion (CONDITION) failed!\n\n' + (MESSAGE)); \ + } + +/* ------------------------------------------- +Macro: ASSERT_FALSE() + Asserts that a CONDITION is false. When an assertion fails, an error is raised with the given MESSAGE. + +Parameters: + CONDITION - Condition to assert as false [Boolean] + MESSSAGE - Message to display if (A OPERATOR B) is true [String] + +Example: + (begin example) + ASSERT_FALSE(_frogIsDead,"The frog died"); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ASSERT_FALSE(CONDITION,MESSAGE) \ + if (CONDITION) then \ + { \ + ASSERTION_ERROR('Assertion (not (CONDITION)) failed!\n\n' + (MESSAGE)) \ + } + +/* ------------------------------------------- +Macro: ASSERT_OP() + Asserts that (A OPERATOR B) is true. When an assertion fails, an error is raised with the given MESSAGE. + +Parameters: + A - First value [Any] + OPERATOR - Binary operator to use [Operator] + B - Second value [Any] + MESSSAGE - Message to display if (A OPERATOR B) is false. [String] + +Example: + (begin example) + ASSERT_OP(_fish,>,5,"Too few fish!"); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ASSERT_OP(A,OPERATOR,B,MESSAGE) \ + if (not ((A) OPERATOR (B))) then \ + { \ + ASSERTION_ERROR('Assertion (A OPERATOR B) failed!\n' + 'A: ' + (str (A)) + '\n' + 'B: ' + (str (B)) + "\n\n" + (MESSAGE)); \ + } + +/* ------------------------------------------- +Macro: ASSERT_DEFINED() + Asserts that a VARIABLE is defined. When an assertion fails, an error is raised with the given MESSAGE.. + +Parameters: + VARIABLE - Variable to test if defined [String or Function]. + MESSAGE - Message to display if variable is undefined [String]. + +Examples: + (begin example) + ASSERT_DEFINED("_anUndefinedVar","Too few fish!"); + ASSERT_DEFINED({ obj getVariable "anUndefinedVar" },"Too many fish!"); + (end) + +Author: + Spooner +------------------------------------------- */ +#define ASSERT_DEFINED(VARIABLE,MESSAGE) \ + if (isNil VARIABLE) then \ + { \ + ASSERTION_ERROR('Assertion (VARIABLE is defined) failed!\n\n' + (MESSAGE)); \ + } + +/* ------------------------------------------- +Group: Unit tests +------------------------------------------- */ +#define TEST_SUCCESS(MESSAGE) MESSAGE_WITH_TITLE("Test OK",MESSAGE) +#define TEST_FAIL(MESSAGE) ERROR_WITH_TITLE("Test FAIL",MESSAGE) + +/* ------------------------------------------- +Macro: TEST_TRUE() + Tests that a CONDITION is true. + If the condition is not true, an error is raised with the given MESSAGE. + +Parameters: + CONDITION - Condition to assert as true [Boolean] + MESSSAGE - Message to display if (A OPERATOR B) is false [String] + +Example: + (begin example) + TEST_TRUE(_frogIsDead,"The frog is alive"); + (end) + +Author: + Killswitch +------------------------------------------- */ +#define TEST_TRUE(CONDITION, MESSAGE) \ + if (CONDITION) then \ + { \ + TEST_SUCCESS('(CONDITION)'); \ + } \ + else \ + { \ + TEST_FAIL('(CONDITION) ' + (MESSAGE)); \ + } + +/* ------------------------------------------- +Macro: TEST_FALSE() + Tests that a CONDITION is false. + If the condition is not false, an error is raised with the given MESSAGE. + +Parameters: + CONDITION - Condition to test as false [Boolean] + MESSSAGE - Message to display if (A OPERATOR B) is true [String] + +Example: + (begin example) + TEST_FALSE(_frogIsDead,"The frog died"); + (end) + +Author: + Killswitch +------------------------------------------- */ +#define TEST_FALSE(CONDITION, MESSAGE) \ + if (not (CONDITION)) then \ + { \ + TEST_SUCCESS('(not (CONDITION))'); \ + } \ + else \ + { \ + TEST_FAIL('(not (CONDITION)) ' + (MESSAGE)); \ + } + +/* ------------------------------------------- +Macro: TEST_OP() + Tests that (A OPERATOR B) is true. + If the test fails, an error is raised with the given MESSAGE. + +Parameters: + A - First value [Any] + OPERATOR - Binary operator to use [Operator] + B - Second value [Any] + MESSSAGE - Message to display if (A OPERATOR B) is false. [String] + +Example: + (begin example) + TEST_OP(_fish,>,5,"Too few fish!"); + (end) + +Author: + Killswitch +------------------------------------------- */ +#define TEST_OP(A,OPERATOR,B,MESSAGE) \ + if ((A) OPERATOR (B)) then \ + { \ + TEST_SUCCESS('(A OPERATOR B)') \ + } \ + else \ + { \ + TEST_FAIL('(A OPERATOR B)') \ + }; + +/* ------------------------------------------- +Macro: TEST_DEFINED_AND_OP() + Tests that A and B are defined and (A OPERATOR B) is true. + If the test fails, an error is raised with the given MESSAGE. + +Parameters: + A - First value [Any] + OPERATOR - Binary operator to use [Operator] + B - Second value [Any] + MESSSAGE - Message to display [String] + +Example: + (begin example) + TEST_OP(_fish,>,5,"Too few fish!"); + (end) + +Author: + Killswitch, PabstMirror +------------------------------------------- */ +#define TEST_DEFINED_AND_OP(A,OPERATOR,B,MESSAGE) \ + if (isNil #A) then { \ + TEST_FAIL('(A is not defined) ' + (MESSAGE)); \ + } else { \ + if (isNil #B) then { \ + TEST_FAIL('(B is not defined) ' + (MESSAGE)); \ + } else { \ + if ((A) OPERATOR (B)) then { \ + TEST_SUCCESS('(A OPERATOR B) ' + (MESSAGE)) \ + } else { \ + TEST_FAIL('(A OPERATOR B) ' + (MESSAGE)) \ + }; }; }; + + +/* ------------------------------------------- +Macro: TEST_DEFINED() + Tests that a VARIABLE is defined. + +Parameters: + VARIABLE - Variable to test if defined [String or Function]. + MESSAGE - Message to display if variable is undefined [String]. + +Examples: + (begin example) + TEST_DEFINED("_anUndefinedVar","Too few fish!"); + TEST_DEFINED({ obj getVariable "anUndefinedVar" },"Too many fish!"); + (end) + +Author: + Killswitch +------------------------------------------- */ +#define TEST_DEFINED(VARIABLE,MESSAGE) \ + if (not isNil VARIABLE) then \ + { \ + TEST_SUCCESS('(' + VARIABLE + ' is defined)'); \ + } \ + else \ + { \ + TEST_FAIL('(' + VARIABLE + ' is not defined)' + (MESSAGE)); \ + } + +/* ------------------------------------------- +Group: Managing Deprecation +------------------------------------------- */ + +/* ------------------------------------------- +Macro: DEPRECATE_SYS() + Allow deprecation of a function that has been renamed. + + Replaces an old OLD_FUNCTION (which will have PREFIX_ prepended) with a NEW_FUNCTION + (PREFIX_ prepended) with the intention that the old function will be disabled in the future. + + Shows a warning in RPT each time the deprecated function is used, but runs the new function. + +Parameters: + OLD_FUNCTION - Full name of old function [Identifier for function that does not exist any more] + NEW_FUNCTION - Full name of new function [Function] + +Example: + (begin example) + // After renaming CBA_fnc_frog as CBA_fnc_fish + DEPRECATE_SYS(CBA_fnc_frog,CBA_fnc_fish); + (end) + +Author: + Sickboy +------------------------------------------- */ +#define DEPRECATE_SYS(OLD_FUNCTION,NEW_FUNCTION) \ + OLD_FUNCTION = { \ + WARNING('Deprecated function used: OLD_FUNCTION (new: NEW_FUNCTION) in ADDON'); \ + if (isNil "_this") then { call NEW_FUNCTION } else { _this call NEW_FUNCTION }; \ + } + +/* ------------------------------------------- +Macro: DEPRECATE() + Allow deprecation of a function, in the current component, that has been renamed. + + Replaces an OLD_FUNCTION (which will have PREFIX_ prepended) with a NEW_FUNCTION + (PREFIX_ prepended) with the intention that the old function will be disabled in the future. + + Shows a warning in RPT each time the deprecated function is used, but runs the new function. + +Parameters: + OLD_FUNCTION - Name of old function, assuming PREFIX [Identifier for function that does not exist any more] + NEW_FUNCTION - Name of new function, assuming PREFIX [Function] + +Example: + (begin example) + // After renaming CBA_fnc_frog as CBA_fnc_fish + DEPRECATE(fnc_frog,fnc_fish); + (end) + +Author: + Sickboy +------------------------------------------- */ +#define DEPRECATE(OLD_FUNCTION,NEW_FUNCTION) \ + DEPRECATE_SYS(DOUBLES(PREFIX,OLD_FUNCTION),DOUBLES(PREFIX,NEW_FUNCTION)) + +/* ------------------------------------------- +Macro: OBSOLETE_SYS() + Replace a function that has become obsolete. + + Replace an obsolete OLD_FUNCTION with a simple COMMAND_FUNCTION, with the intention that anyone + using the function should replace it with the simple command, since the function will be disabled in the future. + + Shows a warning in RPT each time the deprecated function is used, and runs the command function. + +Parameters: + OLD_FUNCTION - Full name of old function [Identifier for function that does not exist any more] + COMMAND_CODE - Code to replace the old function [Function] + +Example: + (begin example) + // In Arma2, currentWeapon command made the CBA_fMyWeapon function obsolete: + OBSOLETE_SYS(CBA_fMyWeapon,{ currentWeapon player }); + (end) + +Author: + Spooner +------------------------------------------- */ +#define OBSOLETE_SYS(OLD_FUNCTION,COMMAND_CODE) \ + OLD_FUNCTION = { \ + WARNING('Obsolete function used: (use: OLD_FUNCTION) in ADDON'); \ + if (isNil "_this") then { call COMMAND_CODE } else { _this call COMMAND_CODE }; \ + } + +/* ------------------------------------------- +Macro: OBSOLETE() + Replace a function, in the current component, that has become obsolete. + + Replace an obsolete OLD_FUNCTION (which will have PREFIX_ prepended) with a simple + COMMAND_CODE, with the intention that anyone using the function should replace it with the simple + command. + + Shows a warning in RPT each time the deprecated function is used. + +Parameters: + OLD_FUNCTION - Name of old function, assuming PREFIX [Identifier for function that does not exist any more] + COMMAND_CODE - Code to replace the old function [Function] + +Example: + (begin example) + // In Arma2, currentWeapon command made the CBA_fMyWeapon function obsolete: + OBSOLETE(fMyWeapon,{ currentWeapon player }); + (end) + +Author: + Spooner +------------------------------------------- */ +#define OBSOLETE(OLD_FUNCTION,COMMAND_CODE) \ + OBSOLETE_SYS(DOUBLES(PREFIX,OLD_FUNCTION),COMMAND_CODE) + +#define BWC_CONFIG(NAME) class NAME { \ + units[] = {}; \ + weapons[] = {}; \ + requiredVersion = REQUIRED_VERSION; \ + requiredAddons[] = {}; \ + version = VERSION; \ +} + +// XEH Specific +#define XEH_CLASS CBA_Extended_EventHandlers +#define XEH_CLASS_BASE DOUBLES(XEH_CLASS,base) +#define XEH_DISABLED class EventHandlers { class XEH_CLASS {}; }; SLX_XEH_DISABLED = 1 +#define XEH_ENABLED class EventHandlers { class XEH_CLASS { EXTENDED_EVENTHANDLERS }; }; SLX_XEH_DISABLED = 0 + +// TODO: These are actually outdated; _Once ? +#define XEH_PRE_INIT QUOTE(call COMPILE_FILE(XEH_PreInit_Once)) +#define XEH_PRE_CINIT QUOTE(call COMPILE_FILE(XEH_PreClientInit_Once)) +#define XEH_PRE_SINIT QUOTE(call COMPILE_FILE(XEH_PreServerInit_Once)) + +#define XEH_POST_INIT QUOTE(call COMPILE_FILE(XEH_PostInit_Once)) +#define XEH_POST_CINIT QUOTE(call COMPILE_FILE(XEH_PostClientInit_Once)) +#define XEH_POST_SINIT QUOTE(call COMPILE_FILE(XEH_PostServerInit_Once)) + +/* ------------------------------------------- +Macro: IS_ADMIN + Check if the local machine is an admin in the multiplayer environment. + + Reports 'true' for logged and voted in admins. + +Parameters: + None + +Example: + (begin example) + // print "true" if player is admin + systemChat str IS_ADMIN; + (end) + +Author: + commy2 +------------------------------------------- */ +#define IS_ADMIN_SYS(x) x##kick +#define IS_ADMIN serverCommandAvailable 'IS_ADMIN_SYS(#)' + +/* ------------------------------------------- +Macro: IS_ADMIN_LOGGED + Check if the local machine is a logged in admin in the multiplayer environment. + + Reports 'false' if the player was voted to be the admin. + +Parameters: + None + +Example: + (begin example) + // print "true" if player is admin and entered in the server password + systemChat str IS_ADMIN_LOGGED; + (end) + +Author: + commy2 +------------------------------------------- */ +#define IS_ADMIN_LOGGED_SYS(x) x##shutdown +#define IS_ADMIN_LOGGED serverCommandAvailable 'IS_ADMIN_LOGGED_SYS(#)' + +/* ------------------------------------------- +Macro: FILE_EXISTS + Check if a file exists + + Reports "false" if the file does not exist. + +Parameters: + FILE - Path to the file + +Example: + (begin example) + // print "true" if file exists + systemChat str FILE_EXISTS("\A3\ui_f\data\igui\cfg\cursors\weapon_ca.paa"); + (end) + +Author: + commy2 +------------------------------------------- */ +#define FILE_EXISTS(FILE) (fileExists (FILE)) \ No newline at end of file diff --git a/framework/x/cba/addons/main/script_macros_mission.hpp b/framework/x/cba/addons/main/script_macros_mission.hpp new file mode 100644 index 0000000..d2eae33 --- /dev/null +++ b/framework/x/cba/addons/main/script_macros_mission.hpp @@ -0,0 +1,85 @@ +#include "script_macros_common.hpp" + +/* + Header: script_macros_mission.hpp + + Description: + Modifies script_common_macros.hpp for compatiblity with missions. + Some addon specific functionality might be lost. + + Authors: + Muzzleflash + + Changes from script_macros_mission.hpp: + Follows Standard: + Object variables: PREFIX_COMPONENT + Main-object variables: PREFIX_main + Paths: PREFIX\COMPONENT\SCRIPTNAME.sqf + Or if CUSTOM_FOLDER is defined: + CUSTOM_FOLDER\SCRIPTNAME.sqf + eg. six\sys_menu\fDate.sqf + + Usage: + Define PREFIX and COMPONENT, then include this file: + + +*/ + +/* + CUSTOM_FOLDER + + Custom folder to search for files in. Will not change variable names. + Default is PREFIX\COMPONENT + + Example: + (begin example) + #define CUSTOM_FOLDER MyPackage\ScriptA + (end) + + (begin example) + #define CUSTOM_FOLDER COMPONENT\functions + (end) + + +*/ + +#undef PATHTO_SYS +#undef PATHTOF_SYS +#undef PATHTOF2_SYS +#ifdef CUSTOM_FOLDER + #define PATHTO_SYS(var1,var2,var3) ##CUSTOM_FOLDER\##var3.sqf + #define PATHTOF_SYS(var1,var2,var3) ##CUSTOM_FOLDER\##var3 + #define PATHTOF2_SYS(var1,var2,var3) ##CUSTOM_FOLDER\##var3 +#else + #define PATHTO_SYS(var1,var2,var3) ##var1\##var2\##var3.sqf + #define PATHTOF_SYS(var1,var2,var3) ##var1\##var2\##var3 + #define PATHTOF2_SYS(var1,var2,var3) ##var1\##var2\##var3 +#endif + +/************************** REMOVAL OF MACROS ***********************/ + +#undef MAINPREFIX +#undef SUBPREFIX +#undef VERSION_AR +#undef VERSION_CONFIG + +#undef VERSIONING_SYS +#undef VERSIONING + +#undef PRELOAD_ADDONS + +#undef BWC_CONFIG + +#undef XEH_DISABLED +#undef XEH_PRE_INIT +#undef XEH_PRE_CINIT +#undef XEH_PRE_SINIT +#undef XEH_POST_INIT +#undef XEH_POST_CINIT +#undef XEH_POST_SINIT + +#undef PATHTO_FNC +#define PATHTO_FNC(func) class func {\ + file = QUOTE(DOUBLES(fnc,func).sqf);\ + RECOMPILE;\ +} \ No newline at end of file diff --git a/functions/CfgFunctions.hpp b/functions/CfgFunctions.hpp deleted file mode 100644 index 4c4a8d1..0000000 --- a/functions/CfgFunctions.hpp +++ /dev/null @@ -1,145 +0,0 @@ -class milsim -{ - class settings - { - class setDefaults { postInit = 1; }; - class addCBASettings { postInit = 1; }; - class addAARChatHandler { postInit = 1; }; - class addRespawnChatHandler { postInit = 1; }; - }; - - class init - { - class initServer { postInit = 1;}; //needs refactor - class initPlayerLocal { postInit = 1;}; - }; - - class fbcb2 { - class initFBCB2 { postInit = 1; }; - class processFBCB2RadioFrequencies {}; - class processFBCB2SmokeColors {}; - class processFBCB2Environment {}; - class hintFBCB2AssetStatus {}; - }; - class fbcb2_util { - file = "functions\fbcb2\util"; - class createOrUpdateDiaryRecord {}; - }; - class fbcb2_radioFrequencies { - file = "functions\fbcb2\radioFrequencies"; - class formatRadioElementForDiary {}; - class generateElementFrequencyRecordText {}; - }; - - class client { - class addZenModules { postInit = 1; }; - class addDNI_PlayerFPS { postInit = 1; }; // needs refactor - class bindEventHandlers { postInit = 1; }; - class bindVehicleActions { postInit = 1; }; - class addClientStatsPFH {}; - class addMedicalOverlayPFH { postInit = 1; }; - class calculateClientStats {}; - class bindEmptyGroupGarbageCleanup { postInit = 1; }; - }; - - class server { - class addServerStatsPFH {}; - class calculateServerStats {}; - class logPlayerInventory {}; - }; - - class ambience { - class flakInitVehicle {}; - class flakEH {}; - }; - - class map - { - class initMapCopy { postInit = 1; }; - class copyMapFromPlayer {}; //needs refactor - class getPlayerMapMarkers {}; //needs refactor - class loadMapMarkers {}; //needs refactor - class mapMarkerToString {}; //needs refactor - class stringToMapMarker {}; //needs refactor - }; - - class util - { - class logMissionInfo { postInit = 1; }; - class addPlayerInfoToArray {}; - class log {}; - class padString {}; - class recurseSubclasses {}; - class getBattalionCfg {}; - class getNameOfBase {}; - class getNearestBase {}; - }; -}; - -class milsim_resupply { - class functions { - file = "functions\resupply"; - class createAmmoBox {}; - class createBox {}; - class createCSWBox {}; - class createLaunchersBox {}; - class createMedicalBox {}; - class createMortarBox {}; - class createWeaponsBox {}; - class getSupplyCratesCfg {}; - class addArsenalObjectSpawnBoxActions {}; - class addCBASettings {postInit=1;}; - }; -}; - -class milsim_fbcb2_assets { - class functions { - file = "functions\fbcb2\assets"; - class updateAssetDiary {}; - class removeAssetDiaryRecords {}; - class getMagsForWeapon {}; - class getWeaponry {}; - class getInventory {}; - class getVehicleData {}; - }; - class assetsByBase { - file = "functions\fbcb2\assets\byBase"; - class getAssetsByBase {}; - class getStartingAssetsByBase {}; - class updateAssetsByBase {}; - }; - class markers { - file = "functions\fbcb2\assets\markers"; - class showMarkersOnMap {}; - class removeMarkersOnMap {}; - } -}; - -class milsim_reinsert { - class server { - file = "functions\reinsert\server"; - class initServer { postInit = 1; }; - class addToQueue {}; - class globalShowQueue {}; - class removeFromQueue {}; - class returnReinsertQueueNotification {}; - class validateQueue {}; - }; - class client { - file = "functions\reinsert\client"; - class initClient { postInit = 1; }; - class addAceSelfActions {}; - class addCheckQueueSelfAction {}; - class requestShowQueue {}; - }; -}; - -class milsim_vehicleFlags { - class functions { - file = "functions\vehicleFlags"; - class initVehicleFlags {postInit = 1}; - class getActionsFlagCategories {}; - class getVehicleFlagsCfg {}; - class isClassExcluded{}; - }; -}; \ No newline at end of file diff --git a/functions/client/fn_addClientStatsPFH.sqf b/functions/client/fn_addClientStatsPFH.sqf deleted file mode 100644 index f85603e..0000000 --- a/functions/client/fn_addClientStatsPFH.sqf +++ /dev/null @@ -1,18 +0,0 @@ -if (!hasInterface) exitWith {}; - -diag_log text "[MILSIM] (client) initializing Stats PFH"; - -_cpsPFH = [ - { - [] call milsim_fnc_calculateClientStats; - }, - "milsim_client_cps_interval" call CBA_settings_fnc_get, - [], - { diag_log text format ["[MILSIM] (client) PFH loaded with interval %1 seconds", "milsim_client_cps_interval" call CBA_settings_fnc_get ] }, - { diag_log text format ["[MILSIM] (client) PFH unloaded"] }, - { "milsim_client_cps_enable" call CBA_settings_fnc_get }, - { false }, - [] -] call CBA_fnc_createPerFrameHandlerObject; - -player setVariable ["milsim_client_cps_handler", _cpsPFH]; diff --git a/functions/client/fn_addMedicalOverlayPFH.sqf b/functions/client/fn_addMedicalOverlayPFH.sqf deleted file mode 100644 index bf3d6b3..0000000 --- a/functions/client/fn_addMedicalOverlayPFH.sqf +++ /dev/null @@ -1,99 +0,0 @@ -/* - -milsim_fnc_addMedicalOverlayPFH - -Author: IndigoFox - -Description: - Affects players with medical permissions. Will see a 3D colored dot over nearby (5-10m) - unconscious players who are not in a vehicle - which indicates their current ACE Triage Card status. - Designed to increase efficiency of CCPs. - -*/ - -// Force setting if CBA doesn't work? -if (isNil "milsim_client_medState3D_enabled") then { - milsim_client_medState3D_enabled = true; -}; -if (isNil "milsim_client_medState3D_drawRange") then { - milsim_client_medState3D_drawRange = 10; -}; - -// List of units to draw icons for -milsim_client_medState3D_drawTargets = []; - -// ACE Triage colors, for consistency across UIs and functions -// #define TRIAGE_COLOR_NONE 0.5, 0.5, 0.5, 0.1 -// #define TRIAGE_COLOR_MINIMAL 0, 0.5, 0, 0.9 -// #define TRIAGE_COLOR_DELAYED 1, 0.84, 0, 0.9 -// #define TRIAGE_COLOR_IMMEDIATE 1, 0, 0, 0.9 -// #define TRIAGE_COLOR_DECEASED 0, 0, 0, 0.9 - -// ACE Triage colors, for consistency across UIs and functions -milsim_client_medState3D_colors = [ - [0, 0.5, 0, 0.9], // TRIAGE_COLOR_MINIMAL - [1, 0.84, 0, 0.9], // TRIAGE_COLOR_DELAYED - [1, 0, 0, 0.9], // TRIAGE_COLOR_IMMEDIATE - [0.15, 0.15, 0.15, 0.9], // TRIAGE_COLOR_DECEASED - [0.5, 0.5, 0.5, 0] // TRIAGE_COLOR_NONE -]; - -// Per-frame handler to draw icons -// cleanup -if (!isNil "milsim_client_medState3D_pfh") then { - [milsim_client_medState3D_pfh] call CBA_fnc_removePerFrameHandler; -}; -// add pfh -milsim_client_medState3D_pfh = [{ - // if disabled, skip processing - if (!milsim_client_medState3D_enabled) exitWith {false}; - // if no targets, skip processing - if (count milsim_client_medState3D_drawTargets == 0) exitWith {false}; - if !([player] call ace_medical_treatment_fnc_isMedic) exitWith {false}; - { - // distance within 10 meters - if (player distance _x > milsim_client_medState3D_drawRange) then {continue}; - // check unit not null, not conscious, and not in a vehicle - if ( - !(_x getVariable ["ACE_isUnconscious", false]) || - !isNull (objectParent _x) - ) then {continue}; - - // color based on triage level - private _triageLevel = _x getVariable ["ace_medical_triageLevel", -1]; - if (_triageLevel == -1) then {continue}; - private _color = milsim_client_medState3D_colors select ( - (_x getVariable ["ace_medical_triageLevel", -1]) -1 - ); - // draw position, slightly above the prone unit - private _drawPos = (visiblePosition _x) vectorAdd [0, 0, 0.5]; - // draw icon - drawIcon3D [ - "\A3\ui_f\data\map\markers\military\dot_CA.paa", // icon texture - _color, // color - _drawPos, // position AGL - 1, // width - 1, // height - 0 // angle - // further params optional, omitted - ]; - } forEach milsim_client_medState3D_drawTargets; -}, 0, []] call CBA_fnc_addPerFrameHandler; - -// subroutine to gather nearest 50 units every 5 seconds and store in milsim_client_medState3D_drawTargets -// cleanup -if (!isNil "milsim_client_medState3D_drawTargetsPfh") then { - [milsim_client_medState3D_drawTargetsPfh] call CBA_fnc_removePerFrameHandler; -}; -// add pfh -milsim_client_medState3D_drawTargetsPfh = [{ - milsim_client_medState3D_drawTargets = ( - (allUnits + allDeadMen) select { - _x isKindOf "CAManBase" && - player distance _x < 50 && - !isNull _x && - player isNotEqualTo _x - } - ); -}, 5, false] call CBA_fnc_addPerFrameHandler; diff --git a/functions/client/fn_bindEmptyGroupGarbageCleanup.sqf b/functions/client/fn_bindEmptyGroupGarbageCleanup.sqf deleted file mode 100644 index 7cb7771..0000000 --- a/functions/client/fn_bindEmptyGroupGarbageCleanup.sqf +++ /dev/null @@ -1,23 +0,0 @@ -diag_log text format ["[MILSIM] (client) initializing empty group deletion PFH"]; - -_emptyGroupPFH = [ - { - { - if (local _x) then { - if ((count units _x) == 0) then { - deleteGroup _x; - }; - }; - } forEach allGroups; - }, - 300, - [], - { diag_log text format ["[MILSIM] (client) Empty Group Deletion PFH loaded"] }, - { diag_log text format ["[MILSIM] (client) Empty Group Deletion"] }, - { true }, - { false }, - [] -] call CBA_fnc_createPerFrameHandlerObject; - - - diff --git a/functions/fbcb2/assets/byBase/fn_getAssetsByBase.sqf b/functions/fbcb2/assets/byBase/fn_getAssetsByBase.sqf deleted file mode 100644 index 05dcd14..0000000 --- a/functions/fbcb2/assets/byBase/fn_getAssetsByBase.sqf +++ /dev/null @@ -1,4 +0,0 @@ -// return each base with its assets -milsim_baseObjects apply { - [_x, _x getVariable ["milsim_fbcb2_assets_assetsAtThisBase", []]] -}; \ No newline at end of file diff --git a/functions/fbcb2/assets/byBase/fn_getStartingAssetsByBase.sqf b/functions/fbcb2/assets/byBase/fn_getStartingAssetsByBase.sqf deleted file mode 100644 index 4c83db4..0000000 --- a/functions/fbcb2/assets/byBase/fn_getStartingAssetsByBase.sqf +++ /dev/null @@ -1,4 +0,0 @@ -// return each base with its assets -milsim_baseObjects apply { - [_x, _x getVariable ["milsim_fbcb2_assets_assetsStartedAtThisBase", []]] -}; \ No newline at end of file diff --git a/functions/fbcb2/assets/byBase/fn_updateAssetsByBase.sqf b/functions/fbcb2/assets/byBase/fn_updateAssetsByBase.sqf deleted file mode 100644 index e243526..0000000 --- a/functions/fbcb2/assets/byBase/fn_updateAssetsByBase.sqf +++ /dev/null @@ -1,179 +0,0 @@ -params [ - ["_isInit", false, [false]], - ["_logCurrentAssets", false, [false]] -]; - -if (!isServer) exitWith {}; - -// Get all approved assets on map, find the closest base -// Then determine if it's within range -// If it is, add it to the base's assets list -// This is to ensure bases with overlapping detection range don't have duplicate assets -private _allVehicles = vehicles; -private _allSaved = []; - -private _assetsAtThisBaseVar = "milsim_fbcb2_assets_assetsAtThisBase"; -private _assetsStartedAtThisBaseVar = "milsim_fbcb2_assets_assetsStartedAtThisBase"; - -{ - private _className = configName _x; - private _callsign = getText(_x >> "callsign"); - private _found = _allVehicles select { typeOf _x == _className }; - { - private _asset = _x; - // avoid duplicates - if (_asset in _allSaved) then {continue}; - private _closestBase = [_asset] call milsim_fnc_getNearestBase; - if (isNull _closestBase) then { - // no base found - continue; - }; - if ( - _asset distance _closestBase > - milsim_fbcb2_assets_setting_detectionRangeFromBase - ) then { - // not within range - continue; - }; - - _asset setVariable ["milsim_fbcb2_assets_callsign", _callsign, true]; - - // add to base's assets list - private _baseAssets = _closestBase getVariable [_assetsAtThisBaseVar, []]; - _baseAssets pushBackUnique _asset; - // broadcast later so we're not spamming network - _closestBase setVariable [ - _assetsAtThisBaseVar, - _baseAssets - ]; - - // if this is the init, set the base's assets started at this base - if (_isInit) then { - // broadcast later so we're not spamming network - _closestBase setVariable [ - _assetsStartedAtThisBaseVar, - _baseAssets - ]; - }; - - _allSaved pushBack _asset; - } forEach _found; -} forEach ((missionConfigFile >> "ApprovedAssets") call BIS_fnc_returnChildren); - -// Add all ground vehicles (LandVehicle) -{ - private _asset = _x; - // avoid duplicates - if (_asset in _allSaved) then {continue}; - - private _closestBase = [_asset] call milsim_fnc_getNearestBase; - if (isNull _closestBase) then { - // no base found - continue; - }; - - if ( - _asset distance _closestBase > - milsim_fbcb2_assets_setting_detectionRangeFromBase - ) then { - // not within range - continue; - }; - - // add to base's assets list - private _baseAssets = _closestBase getVariable [_assetsAtThisBaseVar, []]; - _baseAssets pushBackUnique _asset; - // broadcast later so we're not spamming network - _closestBase setVariable [ - _assetsAtThisBaseVar, - _baseAssets - ]; - - // if this is the init, set the base's assets started at this base - if (_isInit) then { - // broadcast later so we're not spamming network - _closestBase setVariable [ - _assetsStartedAtThisBaseVar, - _baseAssets - ]; - }; -} forEach (_allVehicles select { _x isKindOf "LandVehicle" }); - -//////////////////////////////////////////////////////////////////////// -// publish updated base variables -//////////////////////////////////////////////////////////////////////// -{ - private _base = _x; - - // save current assets - private _baseAssets = _base getVariable [_assetsAtThisBaseVar, []]; - _base setVariable [_assetsAtThisBaseVar, _baseAssets, true]; - - // if init, save starting assets - if (_isInit) then { - _base setVariable [_assetsStartedAtThisBaseVar, _baseAssets, true]; - }; -} forEach milsim_baseObjects; - -//////////////////////////////////////////////////////////////////////// -// log starting assets if init -// log current assets if requested (for end of mission counts) -//////////////////////////////////////////////////////////////////////// -if !(_isInit || _logCurrentAssets) exitWith {}; - -{ - private _base = _x; - - // get current assets - private _baseAssets = _base getVariable [_assetsAtThisBaseVar, []]; - - // prepare key value for logging - private _baseAssetsHashesPrep = _baseAssets apply { - private _asset = _x; - [ - ["callsign", _asset getVariable [ - "milsim_fbcb2_assets_callsign", - "N/A" - ]], - ["className", typeOf _asset], - ["displayName", (configOf _asset) call BIS_fnc_displayName] - ]; - }; - - _baseAssetsHashesPrep = _baseAssetsHashesPrep call BIS_fnc_consolidateArray; - - private _baseAssetsHashes = []; - { - private _out = createHashMapFromArray (_x#0); - _out set ["count", _x#1]; - _baseAssetsHashes pushBack _out; - } forEach _baseAssetsHashesPrep; - - // if logging current assets - if (_logCurrentAssets) then { - { - [ - "fbcb2_assets", - "CURRENT ASSETS", - [ - ["baseName", [[_base] call milsim_fnc_getNameOfBase]], - ["asset", _x] - ] - ] call milsim_fnc_log; - } forEach _baseAssetsHashes; - }; - - // if init, log starting assets - if (_isInit) then { - { - [ - "fbcb2_assets", - "STARTING ASSETS", - [ - ["baseName", [[_base] call milsim_fnc_getNameOfBase]], - ["asset", _x] - ] - ] call milsim_fnc_log; - } forEach _baseAssetsHashes; - }; -} forEach milsim_baseObjects; \ No newline at end of file diff --git a/functions/fbcb2/assets/fn_updateAssetDiary.sqf b/functions/fbcb2/assets/fn_updateAssetDiary.sqf deleted file mode 100644 index 784242f..0000000 --- a/functions/fbcb2/assets/fn_updateAssetDiary.sqf +++ /dev/null @@ -1,185 +0,0 @@ -if (!hasInterface) exitWith {}; - -// create diary records - - -// remove any existing asset map markers -call milsim_fbcb2_assets_fnc_removeMarkersOnMap; - -// remove existing asset records -call milsim_fbcb2_assets_fnc_removeAssetDiaryRecords; - -// get all vehicles by base -private _vehiclesByBase = call milsim_fbcb2_assets_fnc_getAssetsByBase; -if (count _vehiclesByBase isEqualTo 0) exitWith {false}; - -// put vehicles from each base into a single array -private _vehicles = []; -{ - _vehicles append (_x#1); -} forEach _vehiclesByBase; - -if (count _vehicles isEqualTo 0) exitWith {false}; -private _distinctVehiclesClassNames = []; -{ - _distinctVehiclesClassNames pushBackUnique (typeOf _x); -} forEach _vehicles; - - -// ForEach unique vehicle class name, we'll find the first and gather its info -{ - private _className = _x; - private _vehiclesOfThisKind = _vehicles select {typeOf _x isEqualTo _className}; - // This should never happen, but... - if (count _vehiclesOfThisKind isEqualTo 0) then {continue}; - - // Take the first vehicle as a representative - private _representativeVehicle = _vehiclesOfThisKind#0; - private _vehicleCfg = configOf _representativeVehicle; - private _vehicleCallsign = toUpper ( - _representativeVehicle getVariable [ - "milsim_fbcb2_assets_callsign", - "NONE ASSIGNED" - ] - ); - - // Process the vehicle for extended info - // Exclusion list for display names - if ( - ((configOf _representativeVehicle) call BIS_fnc_displayName) - in ["Helicopter"] - ) then {continue}; - - // Get the vehicle data - private _processed = [_representativeVehicle] call milsim_fbcb2_assets_fnc_getVehicleData; - - if (isNil "_processed") then {continue}; - _processed params ["_vehicleCfg", "_displayName", "_diaryTextSections"]; - _diaryTextSections params [ - "_title", - "_image", - "_info", - "_capacity" - // "_weapons", - // "_pylonWeapons", - // "_inventory" - ]; - - // Create the diary record - private _recordText = []; - // Add the title and image - _recordText pushBack _title; - _recordText pushBack _image; - _recordText pushBack "
"; - _recordText pushBack format[ - "CALLSIGN: %1", - _vehicleCallsign - ]; - _recordText pushBack format[ - "COUNT ACTIVE: %1", - count _vehiclesOfThisKind - ]; - - // Here, we'll create a link to show markers on the map for all vehicles of this kind - private _randomColor = selectRandom [ - ["ColorRed", "#FF0000", "Red"], - ["ColorGreen", "#00FF00", "Green"], - ["ColorBlue", "#0000FF", "Blue"], - ["ColorYellow", "#FFFF00", "Yellow"], - ["ColorWhite", "#FFFFFF", "White"] - ]; - private _vehicleCfg = configFile >> "CfgVehicles" >> _className; - // get 'picture' for record - private _icon = getText(_vehicleCfg >> "picture"); - // determine marker type - private _markerType = "mil_dot"; - switch (true) do { - case (_representativeVehicle isKindOf "Helicopter"): { - _markerType = "loc_heli"; - }; - case (_representativeVehicle isKindOf "Air"): { - _markerType = "loc_plane"; - }; - case (_representativeVehicle isKindOf "Ship"): { - _markerType = "loc_boat"; - }; - case (_representativeVehicle isKindOf "Car"): { - _markerType = "loc_car"; - }; - default { - _markerType = "loc_truck"; - }; - }; - - // Link to show markers - private _showMarkersText = format[ - "SHOW MARKERS at vehicle positions (in %5)", - _className, - _markerType, - _randomColor#0, - (_vehiclesOfThisKind apply { - format["%1", _x call BIS_fnc_netId] - }), - format["%2", _randomColor#1, _randomColor#2] - ]; - _recordText pushBack _showMarkersText; - - // Link to hide markers - _recordText pushBack "REMOVE ALL MARKERS showing asset positions"; - - // Link to update asset diary entries - _recordText pushBack "UPDATE ENTRIES for all assets"; - - _recordText pushBack format[ - "%1", - "Notes:
- - Markers are only displayed on your local machine.
- - The REMOVE ALL option will remove all assets' markers from the map.
- - UPDATE ENTRIES will update the asset diary with the latest information (~5 minutes at most)." - ]; - - - - // Add info and capacity sections - _recordText pushBack _info; - _recordText pushBack _capacity; - - - private _subjectID = ""; - switch (true) do { - case (_representativeVehicle isKindOf "Helicopter"): { - _subjectID = milsim_fbcb2_subjectAssetsRotaryID; - }; - case (_representativeVehicle isKindOf "Air"): { - _subjectID = milsim_fbcb2_subjectAssetsFixedWingID; - }; - default { - _subjectID = milsim_fbcb2_subjectAssetsGroundID; - }; - }; - - [ - _subjectID, - format[ - "%1x %2", - count _vehiclesOfThisKind, - (configOf _representativeVehicle) call BIS_fnc_displayName - ], - _recordText joinString "
", - _icon - ] call milsim_fnc_createOrUpdateDiaryRecord; - -// "\A3\ui_f\data\igui\cfg\simpleTasks\types\car_ca.paa" -} forEach _distinctVehiclesClassNames; - -// log to RPT -[ - "fbcb2_assets", - "UPDATED ASSET DIARY", - [ - ["assetCount", count _vehicles], - ["distinctAssetCount", count _distinctVehiclesClassNames] - ] -] call milsim_fnc_log; - -true; \ No newline at end of file diff --git a/functions/fbcb2/fn_hintFBCB2AssetStatus.sqf b/functions/fbcb2/fn_hintFBCB2AssetStatus.sqf deleted file mode 100644 index 6571a0b..0000000 --- a/functions/fbcb2/fn_hintFBCB2AssetStatus.sqf +++ /dev/null @@ -1,31 +0,0 @@ -_assetList = param [0, [objNull], [[objNull]]]; - -_text = parseText "MESSAGE"; -_text = composeText [_text, lineBreak ]; - -_text = composeText [_text, parseText "AssetAvailable", lineBreak ]; - -{ - _callSign = _x select 0; - _asset = _x select 1; - _assigned = _x select 2; - _available = 0; //count (getMarkerPos "respawn_west" nearEntities [ _asset, 2000] ); - - _homes = allMissionObjects "ModuleRespawnPosition_F"; - - { - _home = _x; - _available = _available + count( _home nearEntities [ _asset, 750] ); - } forEach _homes; - - - _image = getText(configFile >> "CfgVehicles" >> _asset >> "picture"); - - _name = getText(configFile >> "CfgVehicles" >> _asset >> "displayName") select [0, 24]; - _data = " " + _name + "" + str _available + " [ " + str _assigned +" ]"; - _text = composeText[ _text, parseText _data, lineBreak ]; - - -} foreach _assetList; - -hint _text; diff --git a/functions/fbcb2/fn_initFBCB2.sqf b/functions/fbcb2/fn_initFBCB2.sqf deleted file mode 100644 index 1f3e864..0000000 --- a/functions/fbcb2/fn_initFBCB2.sqf +++ /dev/null @@ -1,39 +0,0 @@ - -if ( !hasInterface ) exitWith {}; - -waitUntil { !isNil "milsim_complete" }; - -milsim_fbcb2_recordTitleColor = "#ff6666"; -milsim_fbcb2_recordTitleFont = "PuristaMedium"; -milsim_fbcb2_recordTitleSize = 20; - -milsim_fbcb2_recordTextHeaderSize = 16; -milsim_fbcb2_recordTextBodySize = 14; - -milsim_fbcb2_subjectStatusID = "FBCB2_Status"; -milsim_fbcb2_subjectIntelID = "FBCB2_Intel"; -milsim_fbcb2_subjectMessagesID = "FBCB2_Messages"; -milsim_fbcb2_subjectFrequenciesID = "FBCB2_Frequencies"; -milsim_fbcb2_subjectAssetsFixedWingID = "FBCB2_Assets_FixedWing"; -milsim_fbcb2_subjectAssetsRotaryID = "FBCB2_Assets_Rotary"; -milsim_fbcb2_subjectAssetsGroundID = "FBCB2_Assets_Ground"; - -player createDiarySubject[milsim_fbcb2_subjectStatusID, "FBCB2 - Status"]; -player createDiarySubject[milsim_fbcb2_subjectMessagesID, "FBCB2 - Messages"]; -player createDiarySubject[milsim_fbcb2_subjectIntelID, "FBCB2 - Intel"]; -player createDiarySubject[milsim_fbcb2_subjectFrequenciesID, "FBCB2 - Frequencies"]; -player createDiarySubject[milsim_fbcb2_subjectAssetsFixedWingID, "FBCB2 - Assets Plane"]; -player createDiarySubject[milsim_fbcb2_subjectAssetsRotaryID, "FBCB2 - Assets Rotary"]; -player createDiarySubject[milsim_fbcb2_subjectAssetsGroundID, "FBCB2 - Assets Ground"]; - -// store records in format: -// [subject, [ -// [title, diaryRecord] -// ]] -milsim_fbcb2_diaryRecords = createHashMap; - -// populate diary -[] call milsim_fnc_processFBCB2RadioFrequencies; -[] call milsim_fnc_processFBCB2SmokeColors; -[] call milsim_fnc_processFBCB2Environment; -[] call milsim_fbcb2_assets_fnc_updateAssetDiary; diff --git a/functions/fbcb2/fn_processFBCB2Environment.sqf b/functions/fbcb2/fn_processFBCB2Environment.sqf deleted file mode 100644 index 91c8bac..0000000 --- a/functions/fbcb2/fn_processFBCB2Environment.sqf +++ /dev/null @@ -1,45 +0,0 @@ -private _recordTitle = "MDS - INTEL - ENVIRONMENT"; - -private _text = [ - format[ - "%4

", - milsim_fbcb2_recordTitleSize, - milsim_fbcb2_recordTitleColor, - milsim_fbcb2_recordTitleFont, - _recordTitle - ] -]; - -private _sunriseColor = "#4A86E8"; -private _sunsetColor = "#6AA84F"; -private _whiteColor = "#FFFFFF"; - -private _sunTimes = date call BIS_fnc_sunriseSunsetTime; - -_text pushBack format[ - "Local Sunrise
- %5

", - milsim_fbcb2_recordTextHeaderSize, - _sunriseColor, - milsim_fbcb2_recordTextBodySize, - _whiteColor, - ([_sunTimes select 0, "HH:MM"] call BIS_fnc_timeToString) -]; - -_text pushBack format[ - "Local Sunset
- %5

", - milsim_fbcb2_recordTextHeaderSize, - _sunsetColor, - milsim_fbcb2_recordTextBodySize, - _whiteColor, - ([_sunTimes select 1, "HH:MM"] call BIS_fnc_timeToString) -]; - -_text = _text joinString ""; - -[ - milsim_fbcb2_subjectIntelID, - _recordTitle, - _text -] call milsim_fnc_createOrUpdateDiaryRecord; \ No newline at end of file diff --git a/functions/fbcb2/fn_processFBCB2SmokeColors.sqf b/functions/fbcb2/fn_processFBCB2SmokeColors.sqf deleted file mode 100644 index 1797d06..0000000 --- a/functions/fbcb2/fn_processFBCB2SmokeColors.sqf +++ /dev/null @@ -1,41 +0,0 @@ -private _recordTitle = "MDS - INTEL - SMOKES"; - -private _text = [ - // Title - format[ - "%4", - milsim_fbcb2_recordTitleSize, - milsim_fbcb2_recordTitleColor, - milsim_fbcb2_recordTitleFont, - _recordTitle - ] -]; - -private _smokeColors = [ - ["#FFFFFF", "WHITE", "Concealment"], - ["#008800", "GREEN", "Friendly Forces"], - ["#0000FF", "BLUE", "LZ Markers"], - ["#FF0000", "RED", "Enemy Location"], - ["#FFA500", "ORANGE", "Resupply Marker"], - ["#FFFF00", "YELLOW", "Medical Emergency"], - ["#800080", "PURPLE", "Broken Arrow - 100m radius"] -]; - -{ - _x params ["_color", "_name", "_description"]; - _text pushBack format[ - "%3 - %4", - milsim_fbcb2_recordTextHeaderSize, - _color, - _name, - _description - ]; -} forEach _smokeColors; - -_text = _text joinString "

"; - -[ - milsim_fbcb2_subjectIntelID, - _recordTitle, - _text -] call milsim_fnc_createOrUpdateDiaryRecord; \ No newline at end of file diff --git a/functions/fbcb2/util/fn_createOrUpdateDiaryRecord.sqf b/functions/fbcb2/util/fn_createOrUpdateDiaryRecord.sqf deleted file mode 100644 index 6cd8330..0000000 --- a/functions/fbcb2/util/fn_createOrUpdateDiaryRecord.sqf +++ /dev/null @@ -1,28 +0,0 @@ -if (!hasInterface) exitWith {}; - -params [ - ["_subjectID", milsim_fbcb2_subjectStatusID, [""]], - ["_recordTitle", "", [""]], - ["_recordText", "", [""]], - ["_recordIcon", "", [""]] -]; - -// Check if already created -private _subjectRecords = milsim_fbcb2_diaryRecords getOrDefault [_subjectID, createHashMap, true]; -private _existingRecord = _subjectRecords getOrDefault [_recordTitle, diaryRecordNull, true]; - -if (!isNull _existingRecord) then { - player setDiaryRecordText [[_subjectID, _existingRecord], [_recordTitle, _recordText, _recordIcon]]; - systemChat format ["Updated diary record: %1", _recordTitle]; -} else { - private _new = player createDiaryRecord [ - _subjectID, - [ - _recordTitle, - _recordText, - _recordIcon - ] - ]; - _subjectRecords set [_recordTitle, _new]; - milsim_fbcb2_diaryRecords set [_subjectID, _subjectRecords]; -}; \ No newline at end of file diff --git a/functions/fbcb2/util/fn_removeDiaryRecord.sqf b/functions/fbcb2/util/fn_removeDiaryRecord.sqf deleted file mode 100644 index e69de29..0000000 diff --git a/functions/init/fn_initPlayerLocal.sqf b/functions/init/fn_initPlayerLocal.sqf deleted file mode 100644 index 1ba5f10..0000000 --- a/functions/init/fn_initPlayerLocal.sqf +++ /dev/null @@ -1,25 +0,0 @@ -if ( !hasInterface ) exitWith {}; - -if (!isServer) then { - ["milsim_logText", { - params [["_strArray", [""], [[]]]]; - { - diag_log text _x; - } forEach _strArray; - }] call CBA_fnc_addEventHandler; -}; - -// 5 seconds after the client is loaded, add the resupply action to all arsenal boxes -[ - {time > 5}, - { - if (missionNamespace getVariable [ - "milsim_resupply_setting_allowSupplyBoxScrollWheelSpawning", - false - ]) then {call milsim_resupply_fnc_addSpawnBoxActions} - } -] call CBA_fnc_waitUntilAndExecute; - -["InitializePlayer", [player, true]] call BIS_fnc_dynamicGroups; - -nil; \ No newline at end of file diff --git a/functions/init/fn_initServer.sqf b/functions/init/fn_initServer.sqf deleted file mode 100644 index d70c518..0000000 --- a/functions/init/fn_initServer.sqf +++ /dev/null @@ -1,35 +0,0 @@ -if (!isServer) exitWith {}; - -milsim_baseObjects = allMissionObjects "ModuleRespawnPosition_F"; -publicVariable "milsim_baseObjects"; - -// init asset stores at bases -[true] call milsim_fbcb2_assets_fnc_updateAssetsByBase; -// starting 5 minutes after postInit, update asset stores every 5 minutes -[{ - [ - {[false] call milsim_fbcb2_assets_fnc_updateAssetsByBase;}, - 60*5 - ] call CBA_fnc_addPerFrameHandler; -}, 60*5] call CBA_fnc_waitAndExecute; - -// add end mission EH -addMissionEventHandler ["MPEnded", { - // log the "current" asset counts to RPT - [false, true] call milsim_fbcb2_assets_fnc_updateAssetsByBase; -}]; - -// Initializes the Dynamic Groups framework and groups -["Initialize", [true]] call BIS_fnc_dynamicGroups; - -["milsim_logText", { - params [["_strArray", [""], [[]]]]; - { - diag_log text _x; - } forEach _strArray; -}] call CBA_fnc_addEventHandler; - -missionNamespace setVariable ["milsim_complete", true]; -diag_log text "[MILSIM] (initServer) milsim_complete: version 2.3"; - -publicVariable "milsim_complete"; diff --git a/functions/reinsert/client/fn_requestShowQueue.sqf b/functions/reinsert/client/fn_requestShowQueue.sqf deleted file mode 100644 index 1afed4e..0000000 --- a/functions/reinsert/client/fn_requestShowQueue.sqf +++ /dev/null @@ -1,3 +0,0 @@ -if (!hasInterface) exitWith {}; - -[] remoteExec ["milsim_reinsert_fnc_returnReinsertQueueNotification", 2]; \ No newline at end of file diff --git a/functions/reinsert/server/fn_addToQueue.sqf b/functions/reinsert/server/fn_addToQueue.sqf deleted file mode 100644 index 55d14a3..0000000 --- a/functions/reinsert/server/fn_addToQueue.sqf +++ /dev/null @@ -1,56 +0,0 @@ -params [ - ["_player", objNull, [objNull]], - ["_base", objNull, [objNull]], - ["_timeFiled", diag_tickTime, [25]] -]; - -if (!isServer) exitWith { - [ - "respawn_reinsertion", - "ATTEMPTED RUN ON CLIENT", - [ - ["player", _player], - ["base", _base] - ] - ] call milsim_fnc_log; -}; -if ( - isNull _player || - isNull _base -) exitWith { - [ - "respawn_reinsertion", - "NULL PARAMETERS", - [ - ["player", _player], - ["base", _base] - ] - ] call milsim_fnc_log; -}; - - -private _maxRangeToReady = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_maxRangeToReady", 400]; -// nearest base here is the same as the base sent -private _nearestBase = _base; - -milsim_reinsert_reinsertionQueue pushBackUnique [ - _player, _base, _timeFiled -]; -// broadcast new list to all machines -publicVariable "milsim_reinsert_reinsertionQueue"; - -// log to rpt -private _logParams = [ - ["filedAtBase", [_base] call milsim_fnc_getNameOfBase], - ["filedAtBaseDistance", _player distance _base], - ["closestBase", [_nearestBase] call milsim_fnc_getNameOfBase], - ["closestBaseDistance", _player distance _nearestBase], - ["maxDistanceSetting", _maxRangeToReady], - ["inQueueDuration", diag_tickTime - _timeFiled] -]; -_logParams = [_player, _logParams] call milsim_fnc_addPlayerInfoToArray; -[ - "respawn_reinsertion", - "PLAYER FILED REQUEST", - _logParams -] call milsim_fnc_log; \ No newline at end of file diff --git a/functions/reinsert/server/fn_removeFromQueue.sqf b/functions/reinsert/server/fn_removeFromQueue.sqf deleted file mode 100644 index 7c131a1..0000000 --- a/functions/reinsert/server/fn_removeFromQueue.sqf +++ /dev/null @@ -1,57 +0,0 @@ -params [["_player", objNull, [objNull]]]; - -if (!isServer) exitWith { - [ - "respawn_reinsertion", - "ATTEMPTED RUN ON CLIENT", - [ - ["player", _player] - ] - ] call milsim_fnc_log; -}; -if (isNull _player) exitWith { - [ - "respawn_reinsertion", - "NULL PARAMETERS", - [ - ["player", _player] - ] - ] call milsim_fnc_log; -}; - -// get entries for this player from queue -private _unitArrs = milsim_reinsert_reinsertionQueue select {_x#0 isEqualTo _player}; -// if player not in queue, skip -if (count _unitArrs isEqualTo 0) exitWith {}; - -private _maxRangeToReady = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_maxRangeToReady", 400]; - -// remove player from queue -milsim_reinsert_reinsertionQueue = milsim_reinsert_reinsertionQueue - _unitArrs; -// broadcast new list to all machines -publicVariable "milsim_reinsert_reinsertionQueue"; - -// sort _unitArrs by time in queue, descending, to get longest wait (if for some reason there's a duplicate) -[_unitArrs, [], { - _x#2 -}, "DESCEND"] call BIS_fnc_sortBy; - -// get first entry (longest wait) -(_unitArrs#0) params ["_player", "_base", "_timeFiled"]; // _unitArr = [unit, base, timeInQueue] -// get the closest base to the player -private _nearestBase = [_player] call milsim_fnc_getNearestBase; -// log to rpt -private _logParams = [ - ["filedAtBase", [_base] call milsim_fnc_getNameOfBase], - ["filedAtBaseDistance", _player distance _base], - ["closestBase", [_nearestBase] call milsim_fnc_getNameOfBase], - ["closestBaseDistance", _player distance _nearestBase], - ["maxDistanceSetting", _maxRangeToReady], - ["inQueueDuration", diag_tickTime - _timeFiled] -]; -_logParams = [_player, _logParams] call milsim_fnc_addPlayerInfoToArray; -[ - "respawn_reinsertion", - "PLAYER RESCINDED REQUEST", - _logParams -] call milsim_fnc_log; \ No newline at end of file diff --git a/functions/reinsert/server/fn_validateQueue.sqf b/functions/reinsert/server/fn_validateQueue.sqf deleted file mode 100644 index 5e27733..0000000 --- a/functions/reinsert/server/fn_validateQueue.sqf +++ /dev/null @@ -1,57 +0,0 @@ -// revalidate any players in the queue -// compare their distance to the nearest base, and remove them if they're too far away (or dead) -private _stillValid = []; -private _maxRangeToReady = missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_maxRangeToReady", 400]; -{ - _x params ["_player", "_base", "_timeFiled"]; // _unitArr = [unit, baseName, timeInQueue] - - private _distanceToOriginalBase = _player distance _base; - // get the closest base to the player - private _nearestBase = [_player] call milsim_fnc_getNearestBase; - private _isCloseEnoughToAnyBase = (_player distance _nearestBase) < _maxRangeToReady; - - if (not _isCloseEnoughToAnyBase || not (alive _player)) then { - // don't include player in updated queue - // log to rpt - private _logParams = [ - ["filedAtBase", [_base] call milsim_fnc_getNameOfBase], - ["filedAtBaseDistance", _player distance _base], - ["closestBase", [_nearestBase] call milsim_fnc_getNameOfBase], - ["closestBaseDistance", _player distance _nearestBase], - ["maxDistanceSetting", _maxRangeToReady], - ["inQueueDuration", diag_tickTime - _timeFiled] - ]; - _logParams = [_player, _logParams] call milsim_fnc_addPlayerInfoToArray; - [ - "respawn_reinsertion", - "PLAYER DEQUEUED AUTOMATICALLY", - _logParams - ] call milsim_fnc_log; - // continue loop - continue - }; - - // include player in updated queue, and update their location to nearest base - _stillValid pushBackUnique [_player, _nearestBase, _timeFiled]; - // if player's base has changed, log to rpt - if (_base != _nearestBase) then { - private _logParams = [ - ["filedAtBase", [_base] call milsim_fnc_getNameOfBase], - ["filedAtBaseDistance", _player distance _base], - ["closestBase", [_nearestBase] call milsim_fnc_getNameOfBase], - ["closestBaseDistance", _player distance _nearestBase], - ["maxDistanceSetting", _maxRangeToReady], - ["inQueueDuration", diag_tickTime - _timeFiled] - ]; - _logParams = [_player, _logParams] call milsim_fnc_addPlayerInfoToArray; - [ - "respawn_reinsertion", - "PLAYER BASE WAS UPDATED", - _logParams - ] call milsim_fnc_log; - }; -} forEach milsim_reinsert_reinsertionQueue; - -// broadcast new list to all machines -milsim_reinsert_reinsertionQueue = _stillValid; -publicVariable "milsim_reinsert_reinsertionQueue"; \ No newline at end of file diff --git a/functions/resupply/fn_addArsenalObjectSpawnBoxActions.sqf b/functions/resupply/fn_addArsenalObjectSpawnBoxActions.sqf deleted file mode 100644 index 74963ac..0000000 --- a/functions/resupply/fn_addArsenalObjectSpawnBoxActions.sqf +++ /dev/null @@ -1,31 +0,0 @@ -// adds a scroll wheel action to all arsenal boxes to spawn different supply crate types - -private _arsenalBoxClassName = "Land_PaperBox_open_full_F"; - -// get all instances of the arsenal item -private _arsenalBoxes = (allMissionObjects _arsenalBoxClassName) select { - // only select the ones that already have user actions attached - count (actionIDs _x) > 0; -}; - -private _supplyCratesCfg = call milsim_resupply_fnc_getSupplyCratesCfg; -private _supplyCrateTypesCfgs = _supplyCratesCfg call BIS_fnc_returnChildren; - -{ - // add scroll wheel action to spawn different supply box types - private _arsenalBox = _x; - { - private _cfg = _x; - private _supplyCrateDisplayName = (_cfg >> "displayName") call BIS_fnc_getCfgData; - - _arsenalBox addAction [format ["Spawn %1", _supplyCrateDisplayName], { - params ["_target", "_caller", "_actionId", "_arguments"]; - _arguments params ["_supplyCrateCfg"]; - [ - objNull, - configName _supplyCrateCfg, - getPos _target - ] call milsim_resupply_fnc_createBox; - }, [_cfg], 0, false, true, "", ""]; - } forEach _supplyCrateTypesCfgs; -} forEach _arsenalBoxes; \ No newline at end of file diff --git a/functions/resupply/fn_addCBASettings.sqf b/functions/resupply/fn_addCBASettings.sqf deleted file mode 100644 index 47d700a..0000000 --- a/functions/resupply/fn_addCBASettings.sqf +++ /dev/null @@ -1,22 +0,0 @@ -[ - "milsim_resupply_setting_allowSupplyBoxScrollWheelSpawning", // variable - "CHECKBOX", // type - ["Enabled", "If true, adds scroll wheel options to arsenal boxes to spawn supply boxes"], // title - ["17th Battalion", "Resupply"], // category - false, // default value - true, // global setting - { - params ["_value"]; - [ - "resupply", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_resupply_setting_allowSupplyBoxScrollWheelSpawning" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; \ No newline at end of file diff --git a/functions/resupply/fn_createAmmoBox.sqf b/functions/resupply/fn_createAmmoBox.sqf deleted file mode 100644 index 06da1f4..0000000 --- a/functions/resupply/fn_createAmmoBox.sqf +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Author: Hizumi - * - * Create Ammo resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createAmmoBox; // create ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createAmmoBox; // create ammo box via zeus module - * - * Public: Yes - * - * Note: For gathering: - formatText ["%1", [ - ["containerClassname", typeOf cursorObject], - ["backpack", (backpackCargo cursorObject) call BIS_fnc_consolidateArray], - ["item", (itemCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazine", (magazineCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazineAmmo", magazinesAmmoCargo cursorObject], - ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] - ]]; - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "AMMO LIGHT", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_createCSWBox.sqf b/functions/resupply/fn_createCSWBox.sqf deleted file mode 100644 index 180e21c..0000000 --- a/functions/resupply/fn_createCSWBox.sqf +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Author: Hizumi & IndigoFox - * - * Create Ammo resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createCSWBox; // create ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createCSWBox; // create ammo box via zeus module - * - * Public: Yes - * - * Note: For gathering: - formatText ["%1", [ - ["containerClassname", typeOf cursorObject], - ["backpack", (backpackCargo cursorObject) call BIS_fnc_consolidateArray], - ["item", (itemCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazine", (magazineCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazineAmmo", magazinesAmmoCargo cursorObject], - ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] - ]]; - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "CSW", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_createLaunchersBox.sqf b/functions/resupply/fn_createLaunchersBox.sqf deleted file mode 100644 index a702aa0..0000000 --- a/functions/resupply/fn_createLaunchersBox.sqf +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Author: Hizumi & IndigoFox - * - * Create Ammo resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createLaunchersBox; // create ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createLaunchersBox; // create ammo box via zeus module - * - * Public: Yes - * - * Note: For gathering: - formatText ["%1", [ - ["containerClassname", typeOf cursorObject], - ["backpack", (backpackCargo cursorObject) call BIS_fnc_consolidateArray], - ["item", (itemCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazine", (magazineCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazineAmmo", magazinesAmmoCargo cursorObject], - ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] - ]]; - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "LAUNCHERS", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_createMedicalBox.sqf b/functions/resupply/fn_createMedicalBox.sqf deleted file mode 100644 index 0b0b0a0..0000000 --- a/functions/resupply/fn_createMedicalBox.sqf +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Author: Hizumi - * - * Create Ammo resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createMedicalBox; // create ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createMedicalBox // create ammo box via zeus module - * - * Public: Yes - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "MEDICAL", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_createMortarBox.sqf b/functions/resupply/fn_createMortarBox.sqf deleted file mode 100644 index 8d63374..0000000 --- a/functions/resupply/fn_createMortarBox.sqf +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Author: Hizumi & IndigoFox - * - * Create Mortar resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createMortarBox; // create mortar ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createMortarBox; // create mortar ammo box via zeus module - * - * Public: Yes - * - * Note: For gathering: - formatText ["%1", [ - ["containerClassname", typeOf cursorObject], - ["backpack", (backpackCargo cursorObject) call BIS_fnc_consolidateArray], - ["item", (itemCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazine", (magazineCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazineAmmo", magazinesAmmoCargo cursorObject], - ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] - ]]; - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "AMMO MORTAR", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_createWeaponsBox.sqf b/functions/resupply/fn_createWeaponsBox.sqf deleted file mode 100644 index 5907845..0000000 --- a/functions/resupply/fn_createWeaponsBox.sqf +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Author: Hizumi - * - * Create Ammo resupply box for the 17th Battalion - * - * Arguments: - * 0: Vehicle - - * 1: Position - - * - * Return Value: - * Function executed - * - * Example: - * [box] call milsim_fnc_createWeaponsBox; // create ammo box via init line of editor object - * [objNull, pos] call milsim_fnc_createWeaponsBox; // create ammo box via zeus module - * - * Public: Yes - * - * Note: For gathering: - formatText ["%1", [ - ["containerClassname", typeOf cursorObject], - ["backpack", (backpackCargo cursorObject) call BIS_fnc_consolidateArray], - ["item", (itemCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazine", (magazineCargo cursorObject) call BIS_fnc_consolidateArray], - ["magazineAmmo", magazinesAmmoCargo cursorObject], - ["weapon", (weaponCargo cursorObject) call BIS_fnc_consolidateArray] - ]]; - */ - - -params [ - ["_box", objNull, [objNull]], - ["_pos", [0,0,0], [[]], 3] -]; - -[_box, "AMMO HEAVY", _pos] call milsim_fnc_createBox; \ No newline at end of file diff --git a/functions/resupply/fn_getSupplyCratesCfg.sqf b/functions/resupply/fn_getSupplyCratesCfg.sqf deleted file mode 100644 index 2bf1a5f..0000000 --- a/functions/resupply/fn_getSupplyCratesCfg.sqf +++ /dev/null @@ -1 +0,0 @@ -(missionConfigFile >> "SupplyCrates"); \ No newline at end of file diff --git a/functions/server/fn_calculateServerStats.sqf b/functions/server/fn_calculateServerStats.sqf deleted file mode 100644 index 5f58b67..0000000 --- a/functions/server/fn_calculateServerStats.sqf +++ /dev/null @@ -1,34 +0,0 @@ -[] spawn { - // warning: while loop without suspension executes multiple times per frame - private _counter = 0; - private _endTime = diag_tickTime + 5; - private _frameNo = diag_frameNo; - while { diag_tickTime < _endTime } do - { - _counter = _counter + 1; - }; - - diag_log text format ["[MILSIM] (server) Average Server Execution: %1 times per frame", _counter / (diag_frameNo - _frameNo)]; - - missionNamespace setVariable ["milsim_raw_cps", _counter / (diag_frameNo - _frameNo)]; - publicVariable "milsim_raw_cps"; - - // with suspension - private _counter = 0; - private _endTime = diag_tickTime + 5; - private _frameNo = diag_frameNo; - while { diag_tickTime < _endTime } do - { - _counter = _counter + 1; - uiSleep 0.001; // waits at least 1 frame - }; - - diag_log text format ["[MILSIM] (server) Average Server Execution: %1 times per frame", _counter / (diag_frameNo - _frameNo)]; - - missionNamespace setVariable ["milsim_cps", _counter / (diag_frameNo - _frameNo)]; - publicVariable "milsim_cps"; - - ["milsim_serverEfficiency", [ [ ["float", "milsim_raw_cps", missionNamespace getVariable ["milsim_raw_cps", -1]], ["float", "milsim_cps", missionNamespace getVariable ["milsim_cps", -1]] ] ] ] call CBA_fnc_localEvent; -}; - -nil; \ No newline at end of file diff --git a/functions/settings/fn_addAARChatHandler.sqf b/functions/settings/fn_addAARChatHandler.sqf deleted file mode 100644 index b419a0e..0000000 --- a/functions/settings/fn_addAARChatHandler.sqf +++ /dev/null @@ -1,11 +0,0 @@ -[ - "saveaar", - { - [] remoteExec["ocap_fnc_exportData", 2]; - }, - "admin" -] call CBA_fnc_registerChatCommand; - -diag_log text "[MILSIM] (settings) OCAP chat handler registered"; - -nil; \ No newline at end of file diff --git a/functions/settings/fn_addCBASettings.sqf b/functions/settings/fn_addCBASettings.sqf deleted file mode 100644 index 703bab9..0000000 --- a/functions/settings/fn_addCBASettings.sqf +++ /dev/null @@ -1,273 +0,0 @@ -//--------------------- -// Side Chat -//--------------------- - -[ - "milsim_sideChat", - "CHECKBOX", - "Side Chat Text Enabled", - ["17th Battalion", "Side Chat"], - false, - true, - { - params ["_value"]; - diag_log format["side chat activation set to %1", _value]; - } -] call CBA_fnc_addSetting; - -["milsim_sideChat", false] call CBA_settings_fnc_set; - -//--------------------- -// Server CPS -//--------------------- - -[ - "milsim_server_cps_enable", - "CHECKBOX", - "CPS Metrics Enabled", - ["17th Battalion", "Server Metrics"], - true, - true, - { - params ["_value"]; - diag_log format["server cps activation set to %1", _value]; - } -] call CBA_fnc_addSetting; - -["milsim_server_cps_enable", true] call CBA_settings_fnc_set; - -[ - "milsim_server_cps_interval", - "TIME", - "Metrics Interval", - ["17th Battalion", "Server Metrics"], - [60,300,120], - true, - { - if (!isServer) exitWith {}; - - params ["_value"]; - diag_log format["server cps interval set to %1", _value]; - _cpsPFH = missionNamespace getVariable ["milsim_server_cps_handler", ObjNull]; - if (!isNull _cpsPFH) then { - _cpsPFH call CBA_fnc_deletePerFrameHandlerObject; - }; - - _playerCpsPFH = missionNamespace getVariable ["milsim_player_cps_handler", ObjNull]; - if (!isNull _playerCpsPFH) then { - _playerCpsPFH call CBA_fnc_deletePerFrameHandlerObject; - }; - - [] call milsim_fnc_addServerStatsPFH; - - } -] call CBA_fnc_addSetting; - -//--------------------- -// Client CPS -//--------------------- - -[ - "milsim_client_cps_enable", - "CHECKBOX", - "CPS Metrics Enabled", - ["17th Battalion", "Client Metrics"], - true, - true, - { - params ["_value"]; - diag_log format["client cps activation set to %1", _value]; - } -] call CBA_fnc_addSetting; - -["milsim_client_cps_enable", true] call CBA_settings_fnc_set; - -[ - "milsim_client_cps_interval", - "TIME", - "CPS Metrics Interval", - ["17th Battalion", "Client Metrics"], - [60,300,120], - true, - { - if (!hasInterface) exitWith {}; - - params ["_value"]; - diag_log format["client cps interval set to %1", _value]; - _cpsPFH = player getVariable ["milsim_client_cps_handler", ObjNull]; - if (!isNull _cpsPFH) then { - _cpsPFH call CBA_fnc_deletePerFrameHandlerObject; - }; - - [] call milsim_fnc_addClientStatsPFH; - - } -] call CBA_fnc_addSetting; - -//--------------------- -// Medical Overlay -//--------------------- - -[ - "milsim_client_medState3D_enabled", // variable - "CHECKBOX", // type - ["Enable 3D Triage Card State", "Draws a colored dot over units within 10m indicating current ACE Triage State"], // title - ["17th Battalion", "Medical"], // category - true // default value -] call CBA_fnc_addSetting; - -[ - "milsim_client_medState3D_drawRange", // variable - "LIST", // type - ["Range To Draw Icons", "Determines range at which dots are visible"], // title - ["17th Battalion", "Medical"], // category - [[2, 4, 6, 8, 10], ["2", "4", "6", "8", "10"], 4] // option values, option labels, default index -] call CBA_fnc_addSetting; - - -//--------------------- -// Respawn Settings -[ - "milsim_reinsert_setting_reinsertion_enabled", // variable - "CHECKBOX", // type - ["Enabled", "Whether or not players can file for reinsert and pilots can check the reinsert queue"], // title - ["17th Battalion", "Re-insert Queue"], // category - true, // default value - true, // global setting - { - params ["_value"]; - [ - "respawn_reinsertion", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_reinsert_setting_reinsertion_enabled" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -[ - "milsim_reinsert_setting_reinsertion_maxRangeToReady", // variable - "SLIDER", // type - ["Max Request Filing Range", "Maximum distance from a respawn point a player can be to ready up"], // title - ["17th Battalion", "Re-insert Queue"], // category - [0, 1000, 400, 0, false], // [_min, _max, _default, _trailingDecimals, _isPercentage] - true, // global setting - { - params ["_value"]; - [ - "respawn_reinsertion", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_reinsert_setting_reinsertion_maxRangeToReady" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -[ - "milsim_reinsert_setting_reinsertion_pilotForcedCheckEnabled", // variable - "CHECKBOX", // type - ["Enabled", "Whether or not pilots are forced to view the contents of the reinsertion queue per interval"], // title - ["17th Battalion", "Re-insert Queue"], // category - true, // default value - true, // global setting - { - params ["_value"]; - [ - "respawn_reinsertion", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_reinsert_setting_reinsertion_pilotForcedCheckEnabled" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -[ - "milsim_reinsert_setting_reinsertion_pilotForcedCheckInterval", // variable - "TIME", // type - ["Pilot Forced Check Interval", "Pilots will be force shown the queue if they haven't checked it in X seconds"], // title - ["17th Battalion", "Re-insert Queue"], // category - [60*5, 60*30, 60*10], // [_min, _max, _default] - true, - { - params ["_value"]; - [ - "respawn_reinsertion", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_reinsert_setting_reinsertion_pilotForcedCheckInterval" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -[ - "milsim_reinsert_setting_reinsertion_max_wait", // variable - "TIME", // type - ["Max Wait Threshold", "How long should at least one person be waiting before prompting a global notification."], // title - ["17th Battalion", "Re-insert Queue"], // category - [60*5, 60*30, 60*20], // [_min, _max, _default] - true, - { - params ["_value"]; - [ - "respawn_reinsertion", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_reinsert_setting_reinsertion_max_wait" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -//--------------------- -// Asset Diary and Markers Settings - -[ - "milsim_fbcb2_assets_setting_detectionRangeFromBase", // variable - "SLIDER", // type - ["Detection Range From Base", "The range from a base that assets will be detected"], // title - ["17th Battalion", "Asset Diary and Markers"], // category - [0, 1000, 750, 0, false], // [_min, _max, _default, _trailingDecimals, _isPercentage] - true, // global setting - { - params ["_value"]; - [ - "fbcb2_assets", - "SETTING CHANGED", - [ - [ - "setting", - "milsim_fbcb2_assets_setting_detectionRangeFromBase" - ], - ["newValue", _value] - ] - ] call milsim_fnc_log; - } -] call CBA_fnc_addSetting; - -diag_log text "[MILSIM] (settings) Custom CBA settings initialized"; - -nil; \ No newline at end of file diff --git a/functions/settings/fn_setDefaults.sqf b/functions/settings/fn_setDefaults.sqf deleted file mode 100644 index 2302972..0000000 --- a/functions/settings/fn_setDefaults.sqf +++ /dev/null @@ -1,19 +0,0 @@ -enableSaving[false, false]; - -enableRadio false; -enableSentences false; - -missionNamespace setVariable ["ACE_maxWeightDrag", 2400]; -missionNamespace setVariable ["ACE_maxWeightCarry", 1800]; - -if(isClass(configfile >> "CfgPatches" >> "rhs_main")) then { - rhs_vehicleRadioChatter = 0; -}; - -waitUntil {time > 0}; - -enableEnvironment[false, true]; - -diag_log text "[MILSIM] (settings) defaults set"; - -nil; \ No newline at end of file diff --git a/functions/util/fn_getBattalionCfg.sqf b/functions/util/fn_getBattalionCfg.sqf deleted file mode 100644 index b239a24..0000000 --- a/functions/util/fn_getBattalionCfg.sqf +++ /dev/null @@ -1 +0,0 @@ -(missionConfigFile >> "BattalionInfo") \ No newline at end of file diff --git a/functions/util/fn_log.sqf b/functions/util/fn_log.sqf deleted file mode 100644 index d80dbc2..0000000 --- a/functions/util/fn_log.sqf +++ /dev/null @@ -1,28 +0,0 @@ -/* - Function: milsim_fnc_log - - Description: - Used to log messages to the server RPT file. - - Parameters: - 0: STRING - component name. - 1: STRING - message to log. - 2: ARRAY - Key value pairs of data to log. -*/ - -params [ - ["_component", "", [""]], - ["_message", "", [""]], - ["_data", [], [[]]] -]; - -private _hash = createHashMapFromArray _data; - -// Replace square brackets with round brackets to avoid parsing issues. -_message regexReplace ["\[", "("]; -_message regexReplace ["\]", ")"]; - -private _json = [_hash] call CBA_fnc_encodeJSON; -_log = format ["[milsim] [%1] [%2] [%3] :: %4", _component, _fnc_scriptNameParent, _message, _json]; - -diag_log text _log; \ No newline at end of file