From c13d751047a213a511dcef1e7002692ed18d7236 Mon Sep 17 00:00:00 2001 From: eraser1 Date: Wed, 6 Jan 2016 18:38:55 -0600 Subject: [PATCH] Release Candidate --- .gitignore | 4 ++ @ExileServer/addons/a3_dms/config.cpp | 1 + @ExileServer/addons/a3_dms/config.sqf | 59 +++++++++++++---- .../addons/a3_dms/fn_DMS_postInit.sqf | 25 +++++-- @ExileServer/addons/a3_dms/fn_DMS_preInit.sqf | 12 ++-- .../a3_dms/missions/static/saltflats.sqf | 6 +- .../addons/a3_dms/missions/static/slums.sqf | 8 +-- .../a3_dms/scripts/fn_AddMissionToMonitor.sqf | 12 ++-- .../scripts/fn_AddMissionToMonitor_Static.sqf | 10 +-- .../scripts/fn_BroadcastMissionStatus.sqf | 38 +++++------ .../addons/a3_dms/scripts/fn_FillCrate.sqf | 11 ++-- .../scripts/fn_GroupReinforcementsManager.sqf | 44 ++++++++----- .../a3_dms/scripts/fn_IsValidPosition.sqf | 14 ++-- .../a3_dms/scripts/fn_MissionSuccessState.sqf | 10 ++- .../scripts/fn_MissionsMonitor_Dynamic.sqf | 57 ++++++++++------ .../scripts/fn_MissionsMonitor_Static.sqf | 46 ++++++++----- .../addons/a3_dms/scripts/fn_OnKilled.sqf | 28 ++++---- .../a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf | 23 ++++++- .../a3_dms/scripts/fn_SetAILocality.sqf | 10 ++- .../a3_dms/scripts/fn_SetGroupBehavior.sqf | 39 ++++++++--- .../scripts/fn_SetGroupBehavior_Separate.sqf | 54 +++++++++++++++ .../a3_dms/scripts/fn_SpawnAISoldier.sqf | 47 +++++++++---- .../a3_dms/scripts/fn_SpawnAIVehicle.sqf | 28 ++++---- .../scripts/fn_SpawnPersistentVehicle.sqf | 6 +- .../a3_dms/scripts/fn_TargetsKilled.sqf | 65 ++++-------------- README.md | 66 ++++++++++++++++--- 26 files changed, 477 insertions(+), 246 deletions(-) create mode 100644 @ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior_Separate.sqf diff --git a/.gitignore b/.gitignore index 96374c4..7415548 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,7 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + + +# Private files/missions +@ExileServer/addons/a3_dms/missions/static/sectorB.sqf diff --git a/@ExileServer/addons/a3_dms/config.cpp b/@ExileServer/addons/a3_dms/config.cpp index 4679725..49aee45 100644 --- a/@ExileServer/addons/a3_dms/config.cpp +++ b/@ExileServer/addons/a3_dms/config.cpp @@ -65,6 +65,7 @@ class CfgFunctions class SelectOffsetPos {}; class SetAILocality {}; class SetGroupBehavior {}; + class SetGroupBehavior_Separate {}; class SpawnAIGroup {}; class SpawnAIGroup_MultiPos {}; class SpawnAIVehicle {}; diff --git a/@ExileServer/addons/a3_dms/config.sqf b/@ExileServer/addons/a3_dms/config.sqf index fcb2065..f387a4a 100644 --- a/@ExileServer/addons/a3_dms/config.sqf +++ b/@ExileServer/addons/a3_dms/config.sqf @@ -30,15 +30,17 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_TimeBetweenMissions = [600,900]; // [Minimum,Maximum] time between missions (if mission limit is not reached) | DEFAULT: 10-15 mins DMS_MissionTimeOut = [900,1800]; // [Minimum,Maximum] time it will take for a mission to timeout | DEFAULT: 15-30 mins DMS_MissionTimeoutResetRange = 1500; // If a player is this close to a mission then it won't time-out. Set to 0 to disable this check. + DMS_MissionTimeoutResetFrequency = 180; // How often (in seconds) to check for nearby players and reset the mission timeout. /*General settings for dynamic missions*/ /*General settings for static missions*/ DMS_StaticMission = true; // Enable/disable static mission system. DMS_MaxStaticMissions = 1; // Maximum number of Static Missions running at the same time. It's recommended you set this to the same amount of static missions that you have in total. - DMS_TimeToFirstStaticMission = [180,420]; // [Minimum,Maximum] time between first static mission spawn. | DEFAULT: 3-7 minutes. + DMS_TimeToFirstStaticMission = [30,30]; // [Minimum,Maximum] time between first static mission spawn. | DEFAULT: 3-7 minutes. DMS_TimeBetweenStaticMissions = [900,1800]; // [Minimum,Maximum] time between static missions (if static mission limit is not reached) | DEFAULT: 15-30 mins DMS_StaticMissionTimeOut = [1800,3600]; // [Minimum,Maximum] time it will take for a static mission to timeout | DEFAULT: 30-60 mins DMS_StaticMissionTimeoutResetRange = 1500; // If a player is this close to a mission then it won't time-out. Set to 0 to disable this check. + DMS_SMissionTimeoutResetFrequency = 180; // How often (in seconds) to check for nearby players and reset the mission timeout for static missions. DMS_StaticMinPlayerDistance = 1500; // If a player is this close to a mission location, then it won't spawn the mission and will wait 60 seconds before attempting to spawn it. DMS_AllowStaticReinforcements = true; // Whether or not static missions will receive reinforcements. This will simply disable the calling of GroupReinforcementsMonitor; DMS_SpawnFlareOnReinforcements = true; // Whether or not to spawn a flare and noise when AI reinforcements have spawned. @@ -114,6 +116,8 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_MinDistFromEastBorder = 250; // Missions won't spawn in a position this many meters close to the easter map border. DMS_MinDistFromSouthBorder = 250; // Missions won't spawn in a position this many meters close to the southern map border. DMS_MinDistFromNorthBorder = 250; // Missions won't spawn in a position this many meters close to the northern map border. + DMS_SpawnZoneMarkerTypes = ["ExileSpawnZone"]; // If you're using custom spawn zone markers, make sure you define them here. CASE SENSITIVE!!! + DMS_TraderZoneMarkerTypes = ["ExileTraderZone"]; // If you're using custom trader markers, make sure you define them here. CASE SENSITIVE!!! /*Mission spawn location settings*/ DMS_MinWaterDepth = 20; // Minimum depth of water that an underwater mission can spawn at. @@ -136,15 +140,15 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_SpawnMineWarningSigns = true; // Whether or not to spawn mine warning signs around a minefield. DMS_BulletProofMines = true; // Whether or not you want to make the mines bulletproof. Prevents players from being able to shoot the mines and creating explosions. /*Mine settings*/ - + DMS_MinPlayerCount = 0; // Minimum number of players until mission start DMS_MinServerFPS = 5; // Minimum server FPS for missions to start /*Mission notification settings*/ - DMS_PlayerNotificationTypes = [ // Notification types. Supported values are: ["dynamicTextRequest", "standardHintRequest", "systemChatRequest", "textTilesRequest"] - "dynamicTextRequest", // You should use either "dynamicTextRequest" or "textTilesRequest", and I think "textTilesRequest" looks better. + DMS_PlayerNotificationTypes = [ // Notification types. Supported values are: ["dynamicTextRequest", "standardHintRequest", "systemChatRequest", "textTilesRequest"]. Details below + "dynamicTextRequest", // You should use either "dynamicTextRequest" or "textTilesRequest", and I think "textTilesRequest" looks better, but this is less performance-intensive. //"standardHintRequest", // Hints are a bit wonky... - //"textTilesRequest", // Keep in mind you can only have 1 "text tile" message up at a time, so the message will disappear if the player gets a kill or something while the message is shown. + //"textTilesRequest", // Keep in mind you can only have 1 "text tile" message up at a time, so the message will disappear if the player gets a kill or something while the message is shown. This message type is also performance-intensive, so I advise against it. "systemChatRequest" // Always nice to show in chat so that players can scroll up to read the info if they need to. ]; @@ -159,7 +163,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t /*Dynamic Text Notification Settings*/ /*Standard Hint Notification Settings*/ - DMS_standardHint_Title_Size = 2.5; // Size for Client Standard Hint mission titles. + DMS_standardHint_Title_Size = 2; // Size for Client Standard Hint mission titles. DMS_standardHint_Title_Font = "puristaMedium"; // Font for Client Standard Hint mission titles. DMS_standardHint_Message_Color = "#FFFFFF"; // Standard Hint color for "standardHintRequest" client notification type. DMS_standardHint_Message_Size = 1; // Standard Hint size for "standardHintRequest" client notification type. @@ -197,20 +201,40 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t ["behindenemylines",2], ["mercbase",1] ]; - + DMS_StaticMissionTypes = [ // List of STATIC missions with spawn chances. - + //["saltflats",1], //<--Example (already imported by default on Altis) + //["slums",1] //<--Example (already imported by default on Altis) + + //["sectorB",1] //<--Example for Taviana ]; DMS_BasesToImportOnServerStart = [ // List of static bases to import on server startup (spawned post-init). This will reduce the amount of work the server has to do when it actually spawns static missions, and players won't be surprised when a base suddenly pops up. You can also include any other M3E-exported bases to spawn here. + //"saltflatsbase", //<--Example (already imported by default on Altis) + //"slums_objects" //<--Example (already imported by default on Altis) + ]; + DMS_BanditMissionsOnServerStart = [ + //"construction" //<-- Example + ]; + + DMS_StaticMissionsOnServerStart = [ // List of STATIC missions with spawn chances. + //"saltflats", //<--Example + //"slums //<--Example + + //"sectorB" //<--Example for Taviana ]; - DMS_findSafePosBlacklist = [ // For BIS_fnc_findSafePos position blacklist info refer to: http://www.exilemod.com/topic/61-dms-defents-mission-system/?page=18#comment-31190 + DMS_findSafePosBlacklist = [ // For BIS_fnc_findSafePos position blacklist info refer to: http://www.exilemod.com/topic/61-dms-defents-mission-system/?page=18#comment-31190 // An example is given in the altis_config.sqf (it blacklists the salt flats). + /* + // Blacklists most of the Northern Taviana Volcano + [[11375,16170],[14302,18600]], + [[13300,14670],[14875,16170]] + */ ]; /* Mission System Settings */ @@ -220,6 +244,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_Show_Kill_Poptabs_Notification = true; // Whether or not to show the poptabs gained/lost message on the player's screen when killing an AI. (It will still change the player's money, it just won't show the "Money Received" notification) DMS_Show_Kill_Respect_Notification = true; // Whether or not to show the "Frag Message" on the player's screen when killing an AI. (It will still change the player's respect, it just won't show the "AI Killed" frag message) + DMS_Show_Party_Kill_Notification = true; // Whether or not to show in chat when a party member kills an AI. DMS_Bandit_Soldier_MoneyGain = 50; // The amount of Poptabs gained for killing a bandit soldier DMS_Bandit_Soldier_RepGain = 10; // The amount of Respect gained for killing a bandit soldier @@ -227,7 +252,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_Bandit_Static_RepGain = 15; // The amount of Respect gained for killing a bandit static gunner DMS_Bandit_Vehicle_MoneyGain = 100; // The amount of Poptabs gained for killing a bandit vehicle crew member DMS_Bandit_Vehicle_RepGain = 25; // The amount of Respect gained for killing a bandit vehicle crew member - + DMS_AIKill_DistanceBonusMinDistance = 100; // Minimum distance from the player to the AI to apply the distance bonus. DMS_AIKill_DistanceBonusCoefficient = 0.05; // If the distance from the player to the killed unit is more than "DMS_AIKill_DistanceBonusMinDistance" meters then the player gets a respect bonus equivalent to the distance multiplied by this coefficient. For example, killing an AI from 400 meters will give 100 extra respect (when the coefficient is 0.25). Set to 0 to disable the bonus. This bonus will not be applied if there isn't a regular AI kill bonus. @@ -253,6 +278,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_ai_offload_to_client = true; // Offload spawned AI groups to random clients. Helps with server performance. DMS_ai_offload_Only_DMS_AI = false; // Do you use other mission systems on your server but still want to offload AI? You should probably enable this then, unless you have tested it for compatibility. + DMS_ai_offload_notifyClient = false; // Notify the client when AI has been offloaded to the client. DMS_ai_share_info = true; // Share info about killer DMS_ai_share_info_distance = 300; // The distance killer's info will be shared to other AI @@ -267,6 +293,9 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_ai_skill_difficult = [["aimingAccuracy",0.70],["aimingShake",0.70],["aimingSpeed",0.70],["spotDistance",0.70],["spotTime",0.80],["courage",1.00],["reloadSpeed",1.00],["commanding",1.00],["general",0.70]]; // Difficult DMS_ai_skill_hardcore = [["aimingAccuracy",1.00],["aimingShake",1.00],["aimingSpeed",1.00],["spotDistance",1.00],["spotTime",1.00],["courage",1.00],["reloadSpeed",1.00],["commanding",1.00],["general",1.00]]; // Hardcore DMS_ai_skill_random = ["hardcore","difficult","difficult","difficult","moderate","moderate","moderate","moderate","easy","easy"]; // Skill frequencies for "random" AI skills | Default: 10% hardcore, 30% difficult, 40% moderate, and 20% easy + DMS_ai_skill_randomDifficult = ["hardcore","hardcore","difficult","difficult","difficult"]; // 60% chance for "difficult", 40% chance for "hardcore" AI. + DMS_ai_skill_randomEasy = ["moderate","moderate","easy","easy","easy"]; // 60% chance for "easy", 40% chance for "moderate" AI. + DMS_ai_skill_randomIntermediate = ["difficult","difficult","moderate","moderate","moderate"]; // 60% chance for "moderate", 40% chance for "difficult" AI. DMS_AI_WP_Radius_easy = 20; // Waypoint radius for "easy" AI DMS_AI_WP_Radius_moderate = 30; // Waypoint radius for "moderate" AI DMS_AI_WP_Radius_difficult = 50; // Waypoint radius for "difficult" AI @@ -294,7 +323,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t "ItemCompass", "ItemRadio" ]; - + DMS_ai_BipodList = [ "bipod_01_F_blk", "bipod_01_F_mtp", @@ -548,7 +577,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t "B_Carryall_cbr", "B_Bergen_blk" ]; - + DMS_ai_SupportedClasses = [ // Allowed AI classes. If you want to create your own class, make sure you define everything as I've defined above, and add it here "assault", "MG", @@ -608,6 +637,8 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t /* Loot Settings */ DMS_GodmodeCrates = true; // Whether or not crates will have godmode after being filled with loot. + DMS_MinimumMagCount = 3; // Minimum number of magazines for weapons. + DMS_MaximumMagCount = 5; // Maximum number of magazines for weapons. DMS_CrateCase_Sniper = [ // If you pass "Sniper" in _lootValues, then it will spawn these weapons/items/backpacks [ ["Rangefinder",1], @@ -721,7 +752,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t DMS_ArmedVehicles = [ // List of armed vehicles that can spawn "Exile_Car_Offroad_Armed_Guerilla01" ]; - + DMS_MilitaryVehicles = [ // List of military vehicles that can spawn "Exile_Car_Strider", "Exile_Car_Hunter", @@ -753,7 +784,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t "Exile_Car_Offroad_Rusty2", "Exile_Bike_QuadBike_Fia" ]; - + DMS_TransportHelis = [ // List of transport helis that can spawn "Exile_Chopper_Hummingbird_Green", "Exile_Chopper_Orca_BlackCustom", diff --git a/@ExileServer/addons/a3_dms/fn_DMS_postInit.sqf b/@ExileServer/addons/a3_dms/fn_DMS_postInit.sqf index b4459a5..d3e6843 100644 --- a/@ExileServer/addons/a3_dms/fn_DMS_postInit.sqf +++ b/@ExileServer/addons/a3_dms/fn_DMS_postInit.sqf @@ -24,9 +24,9 @@ if (isNil "DMS_DynamicMission") exitWith // This code is NECESSARY for spawning persistent vehicles. DO NOT REMOVE THIS CODE UNLESS YOU KNOW WHAT YOU ARE DOING -if !("isKnownAccount:76561198027700602" call ExileServer_system_database_query_selectSingleField) then +if !("isKnownAccount:DMS_PersistentVehicle" call ExileServer_system_database_query_selectSingleField) then { - "createAccount:76561198027700602:eraser1" call ExileServer_system_database_query_fireAndForget; + "createAccount:DMS_PersistentVehicle:DMS_PersistentVehicle" call ExileServer_system_database_query_fireAndForget; }; @@ -36,7 +36,7 @@ if !("isKnownAccount:76561198027700602" call ExileServer_system_database_query_s // Some custom maps don't have the proper safePos config entries. // If you are using one and you have an issue with mission spawns, please create an issue on GitHub or post a comment in the DMS thread. switch (toLower worldName) do -{ +{ case "altis": // [16000,16000] w/ radius of 16000 works well for Altis { DMS_MapCenterPos = [16000,16000]; @@ -52,7 +52,8 @@ switch (toLower worldName) do DMS_MapCenterPos = [6275,6350]; DMS_MapRadius = 5000; }; - case "tavi": // Thanks to JamieKG for this info + case "taviana"; // Thanks to JamieKG for this info + case "tavi": { DMS_MapCenterPos = [12800,12800]; DMS_MapRadius = 12800; @@ -125,7 +126,7 @@ DMS_CLIENT_fnc_spawnDynamicText = compileFinal "+str DMS_dynamicText_Duration+", "+str DMS_dynamicText_FadeTime+", 0, - 24358 + 24358+round(random 5) ] spawn BIS_fnc_dynamicText; "); publicVariable "DMS_CLIENT_fnc_spawnDynamicText"; @@ -148,6 +149,11 @@ DMS_CLIENT_fnc_spawnTextTiles = compileFinal "); publicVariable "DMS_CLIENT_fnc_spawnTextTiles"; +DMS_CLIENT_fnc_hintSilent = compileFinal "hintSilent parsetext format['%1',_this];"; +publicVariable "DMS_CLIENT_fnc_hintSilent"; + +publicVariable "DMS_Version"; + // Add the weighted predefined locations to the list of predefined locations @@ -224,6 +230,15 @@ else } forEach DMS_BasesToImportOnServerStart; +{ + [_x] call DMS_fnc_SpawnBanditMission; +} forEach DMS_BanditMissionsOnServerStart; + +{ + [_x] call DMS_fnc_SpawnStaticMission; +} forEach DMS_StaticMissionsOnServerStart; + + diff --git a/@ExileServer/addons/a3_dms/fn_DMS_preInit.sqf b/@ExileServer/addons/a3_dms/fn_DMS_preInit.sqf index 6e2ed2e..48348c6 100644 --- a/@ExileServer/addons/a3_dms/fn_DMS_preInit.sqf +++ b/@ExileServer/addons/a3_dms/fn_DMS_preInit.sqf @@ -20,6 +20,8 @@ if (DMS_Use_Map_Config) then call compileFinal preprocessFileLineNumbers (format ["\x\addons\dms\map_configs\%1_config.sqf",toLower worldName]); }; +DMS_MagRange = DMS_MaximumMagCount - DMS_MinimumMagCount; + /* Original Functions from http://maca134.co.uk/portfolio/m3editor-arma-3-map-editor/ @@ -44,15 +46,15 @@ M3E_fnc_getCenter = _xs = 0; _xc = {_xs = _xs + _x; true} count _ax; _xz = _xs / _xc; - + _ys = 0; _yc = {_ys = _ys + _x; true} count _ay; _yz = _ys / _yc; - + _zs = 0; _zc = {_zs = _zs + _x; true} count _az; _zz = _zs / _zc; - + [_xz, _yz, _zz] }; @@ -69,7 +71,7 @@ M3E_fnc_subArr = } foreach _a1; _a3 }; - + DMS_fnc_setRelPositions = { private ['_OK','_objects','_newCPos','_center']; @@ -101,4 +103,4 @@ DMS_fnc_setRelPositions = // Because I fucked up the name on first implementation and don't want to mess anybody up who didn't realize to change every occurence of "DMS_MaxSurfaceNormal" to "DMS_MinSurfaceNormal". DMS_MaxSurfaceNormal = DMS_MinSurfaceNormal; -DMS_AttemptsUntilThrottle = DMS_AttemptsUntilThrottle + 1; \ No newline at end of file +DMS_AttemptsUntilThrottle = DMS_AttemptsUntilThrottle + 1; diff --git a/@ExileServer/addons/a3_dms/missions/static/saltflats.sqf b/@ExileServer/addons/a3_dms/missions/static/saltflats.sqf index 245892e..1c7ef8c 100644 --- a/@ExileServer/addons/a3_dms/missions/static/saltflats.sqf +++ b/@ExileServer/addons/a3_dms/missions/static/saltflats.sqf @@ -164,7 +164,7 @@ _groupReinforcementsInfo = _group, // pass the group (again) [ [ - 0, // Let's limit number of units instead... + -1, // Let's limit number of units instead... 0 ], [ @@ -260,7 +260,7 @@ if !(_added) exitWith } forEach _missionAIUnits; _cleanup pushBack ((_missionObjs select 0)+(_missionObjs select 1)); - + { _cleanup pushBack (_x select 0); } foreach (_missionObjs select 2); @@ -285,4 +285,4 @@ if !(_added) exitWith if (DMS_DEBUG) then { (format ["MISSION: (%1) :: Mission #%2 started at %3 with %4 AI units and %5 difficulty at time %6",_missionName,_num,_pos,_AICount,_difficulty,_time]) call DMS_fnc_DebugLog; -}; \ No newline at end of file +}; diff --git a/@ExileServer/addons/a3_dms/missions/static/slums.sqf b/@ExileServer/addons/a3_dms/missions/static/slums.sqf index e074cfb..293703e 100644 --- a/@ExileServer/addons/a3_dms/missions/static/slums.sqf +++ b/@ExileServer/addons/a3_dms/missions/static/slums.sqf @@ -127,7 +127,7 @@ _groupReinforcementsInfo = _group, // pass the group [ [ - 0, // Let's limit number of units instead... + -1, // Let's limit number of units instead... 0 ], [ @@ -211,7 +211,7 @@ _added = _markers, _side, _difficulty, - [[],[]] + [] ] call DMS_fnc_AddMissionToMonitor_Static; // Check to see if it was added correctly, otherwise delete the stuff @@ -225,7 +225,7 @@ if !(_added) exitWith } forEach _missionAIUnits; _cleanup pushBack ((_missionObjs select 0)+(_missionObjs select 1)); - + { _cleanup pushBack (_x select 0); } foreach (_missionObjs select 2); @@ -250,4 +250,4 @@ if !(_added) exitWith if (DMS_DEBUG) then { (format ["MISSION: (%1) :: Mission #%2 started at %3 with %4 AI units and %5 difficulty at time %6",_missionName,_num,_pos,_AICount,_difficulty,_time]) call DMS_fnc_DebugLog; -}; \ No newline at end of file +}; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor.sqf b/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor.sqf index fcbbfec..ecfb6f8 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor.sqf @@ -46,9 +46,9 @@ _difficulty, _missionEvents, [ - _onSuccessScripts, // (OPTIONAL) Array of code or string to be executed on mission completion (in addition to regular code). - _onFailScripts, // (OPTIONAL) Array of code or stirng to be executed on mission failure (in addition to regular code). - _onMonitorStart, // (OPTIONAL) Code to run when the monitor starts to check the mission status, however it is checked AFTER "MissionSuccessState" is checked, so you can use/set the variable "_success" manually. The passed parameter (_this) is the mission data array itself. + _onSuccessScripts, // (OPTIONAL) Array of code or string to be executed on mission completion (in addition to regular code). Each element should be an array in the form [_params, _code]. + _onFailScripts, // (OPTIONAL) Array of code or stirng to be executed on mission failure (in addition to regular code). Each element should be an array in the form [_params, _code]. + _onMonitorStart, // (OPTIONAL) Code to run when the monitor starts to check the mission status. The passed parameter (_this) is the mission data array itself. _onMonitorEnd // (OPTIONAL) Code to run when the monitor is done with checking the mission status. The passed parameter (_this) is the mission data array itself. ] ] call DMS_fnc_AddMissionToMonitor; @@ -118,7 +118,7 @@ try }; _mines = []; - + if ((count _missionObjs)>3) then { _mines = _missionObjs param [3,[],[[]]]; @@ -156,7 +156,7 @@ try throw format["_onEndingScripts |%1|",_onEndingScripts]; }; - _arr = + _arr = [ _pos, _completionInfo, @@ -206,4 +206,4 @@ catch diag_log format ["DMS ERROR :: Calling DMS_AddMissionToMonitor with invalid parameter: %1",_exception]; }; -_added \ No newline at end of file +_added diff --git a/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor_Static.sqf b/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor_Static.sqf index 748fd34..3f838fc 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor_Static.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_AddMissionToMonitor_Static.sqf @@ -56,9 +56,9 @@ _difficulty, _missionEvents, [ - _onSuccessScripts, // (OPTIONAL) Array of code or string to be executed on mission completion (in addition to regular code). - _onFailScripts, // (OPTIONAL) Array of code or stirng to be executed on mission failure (in addition to regular code). - _onMonitorStart, // (OPTIONAL) Code to run when the monitor starts to check the mission status, however it is checked AFTER "MissionSuccessState" is checked, so you can use/set the variable "_success" manually. The passed parameter (_this) is the mission data array itself. + _onSuccessScripts, // (OPTIONAL) Array of code or string to be executed on mission completion (in addition to regular code). Each element should be an array in the form [_params, _code]. + _onFailScripts, // (OPTIONAL) Array of code or stirng to be executed on mission failure (in addition to regular code). Each element should be an array in the form [_params, _code]. + _onMonitorStart, // (OPTIONAL) Code to run when the monitor starts to check the mission status. The passed parameter (_this) is the mission data array itself. _onMonitorEnd // (OPTIONAL) Code to run when the monitor is done with checking the mission status. The passed parameter (_this) is the mission data array itself. ] ] call DMS_fnc_AddMissionToMonitor_Static; @@ -157,7 +157,7 @@ try throw format["_onEndingScripts |%1|",_onEndingScripts]; }; - _arr = + _arr = [ _pos, _completionInfo, @@ -208,4 +208,4 @@ catch diag_log format ["DMS ERROR :: Calling DMS_AddMissionToMonitor_Static with invalid parameter: %1",_exception]; }; -_added \ No newline at end of file +_added diff --git a/@ExileServer/addons/a3_dms/scripts/fn_BroadcastMissionStatus.sqf b/@ExileServer/addons/a3_dms/scripts/fn_BroadcastMissionStatus.sqf index 148c1bf..33e851c 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_BroadcastMissionStatus.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_BroadcastMissionStatus.sqf @@ -2,7 +2,7 @@ DMS_fnc_BroadcastMissionStatus Created by eraser1 - Usage: + Usage: [ _messageTitle, [ @@ -44,36 +44,32 @@ if !(_message isEqualType "") then _message = str _message; }; +if (_message isEqualTo "") exitWith {}; + { private "_args"; switch (toLower _x) do - { + { case "systemchatrequest": { - [_x, [format ["%1: %2",toUpper _missionName,_message]], "-1"] call ExileServer_system_network_send_broadcast; + format["%1: %2",toUpper _missionName,_message] remoteExecCall ["systemChat",-2]; }; case "standardhintrequest": { + format [ - _x, - [ - format - [ - "%4
%8", - _titleColor, - DMS_standardHint_Title_Size, - DMS_standardHint_Title_Font, - _missionName, - DMS_standardHint_Message_Color, - DMS_standardHint_Message_Size, - DMS_standardHint_Message_Font, - _message - ] - ], - "-1" - ] call ExileServer_system_network_send_broadcast; + "%4
%8", + _titleColor, + DMS_standardHint_Title_Size, + DMS_standardHint_Title_Font, + _missionName, + DMS_standardHint_Message_Color, + DMS_standardHint_Message_Size, + DMS_standardHint_Message_Font, + _message + ] remoteExecCall ["DMS_CLIENT_fnc_hintSilent",-2]; }; case "dynamictextrequest": @@ -110,4 +106,4 @@ if !(_message isEqualType "") then default { diag_log format ["DMS ERROR :: Unsupported Notification Type in DMS_PlayerNotificationTypes: %1 | Calling parameters: %2",_x,_this]; }; }; -} forEach DMS_PlayerNotificationTypes; \ No newline at end of file +} forEach DMS_PlayerNotificationTypes; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf b/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf index 2d74841..891d268 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf @@ -10,9 +10,9 @@ _lootValues, // ARRAY, STRING, or NUMBER: String or number refers to a crate case in config.cfg; array determines random crate weapons/items/backpacks _rareLootChance // (OPTIONAL) NUMBER: Manually define the percentage chance of spawning some rare items. ] call DMS_fnc_FillCrate; - + If the "_lootValues" parameter is a number or a string, the function will look for a value defined as "DMS_CrateCase_*", where the "*" is replaced by the "_lootValues" parameter. EG: DMS_CrateCase_Sniper. - + Otherwise, the "_lootValues" parameter must be defined as: [ _weapons, @@ -175,7 +175,10 @@ if ((_lootValues isEqualType []) && {!((_lootValues select 1) isEqualType {})}) _weapon = [_weapon,1]; }; _crate addWeaponCargoGlobal _weapon; - _crate addItemCargoGlobal [_ammo, (4 + floor(random 3))]; + if !(_ammo isEqualTo "Exile_Magazine_Swing") then + { + _crate addItemCargoGlobal [_ammo, (DMS_MinimumMagCount + floor(random DMS_MagRange))]; + }; }; }; @@ -307,4 +310,4 @@ if (_crate getVariable ["DMS_AllowSmoke", true]) then _marker setPosATL (getPosATL _crate); _marker attachTo [_crate, [0,0,0.5]]; }; -}; \ No newline at end of file +}; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_GroupReinforcementsManager.sqf b/@ExileServer/addons/a3_dms/scripts/fn_GroupReinforcementsManager.sqf index 0bd0af4..819357f 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_GroupReinforcementsManager.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_GroupReinforcementsManager.sqf @@ -28,7 +28,7 @@ ] call DMS_fnc_GroupReinforcementsManager; About "_monitorType" types: - + "playernear": _monitorParams = [ @@ -279,7 +279,7 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType]; }; - + if (_remainingUnits<_AICount) then { _maxAICount = if ((count _monitorParams)>2) then {_monitorParams param [2, 0, [0]]} else {_AICount}; @@ -487,7 +487,7 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the }; }; }; - + default { _reinforcementsDepleted = true; @@ -497,12 +497,7 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the if ((!isNil "_unitsToSpawn") && {_unitsToSpawn>0}) then { - private ["_spawnPos", "_units"]; - - if (_spawnLocations isEqualTo []) then - { - _spawnPos = getPosATL (leader _AIGroup); - }; + private ["_spawnPos", "_units", "_spawningLocations"]; if (_maxReinforcementUnits>0) then { @@ -520,17 +515,36 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the _units = []; - for "_i" from 1 to _unitsToSpawn do + if (_spawnLocations isEqualTo []) then { - if (isNil "_spawnPos") then + // No spawn locations were provided, so we just use the leader of the group as the spawn location. + _spawnPos = getPosATL (leader _AIGroup); + + for "_i" from 0 to (_unitsToSpawn-1) do { - _spawnPos = _spawnLocations call BIS_fnc_selectRandom; + _units pushBack ([_AIGroup,_spawnPos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier); + }; + } + else + { + // Shuffle the original list and make a copy. + _spawningLocations = (_spawnLocations call ExileClient_util_array_shuffle) + []; + _spawningLocations_count = count _spawningLocations; + + // Add extra spawning locations if there are not enough. + for "_i" from 0 to (_unitsToSpawn-_spawningLocations_count-1) do + { + _spawningLocations pushBack (_spawningLocations select floor(random(_spawningLocations_count+_i))); }; - _units pushBack ([_AIGroup,_spawnPos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier); + // Now to spawn the AI... + for "_i" from 0 to (_unitsToSpawn-1) do + { + _units pushBack ([_AIGroup,_spawningLocations select _i,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier); + }; }; - _units joinSilent _AIGroup; // Otherwise they don't like each other... + _units joinSilent _AIGroup; // Otherwise they don't like each other... // Update the given reinforcements count. _reinforcementWavesGiven = _reinforcementWavesGiven + 1; @@ -560,4 +574,4 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the -_reinforcementsDepleted \ No newline at end of file +_reinforcementsDepleted diff --git a/@ExileServer/addons/a3_dms/scripts/fn_IsValidPosition.sqf b/@ExileServer/addons/a3_dms/scripts/fn_IsValidPosition.sqf index f9ba4bf..d86a4f8 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_IsValidPosition.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_IsValidPosition.sqf @@ -66,7 +66,7 @@ else if (!_waterSpawn) then { // Check for nearby water - if ((_waterNearLimit>0) && {[_pos,_waterNearLimit] call DMS_fnc_isNearWater}) then + if ((_waterNearLimit>0) && {[_pos,_waterNearLimit] call DMS_fnc_isNearWater}) then { throw ("water"); }; @@ -114,16 +114,16 @@ else throw ("an A3XAI mission"); }; } forEach (missionNamespace getVariable ["A3XAI_mapMarkerArray",[]]); - + { // Check for nearby spawn points - if ((_spawnZoneNearLimit>0) && {((markertype _x) == "ExileSpawnZone") && {((getMarkerPos _x) distance2D _pos)<=_spawnZoneNearLimit}}) then + if ((_spawnZoneNearLimit>0) && {((markertype _x) in DMS_SpawnZoneMarkerTypes) && {((getMarkerPos _x) distance2D _pos)<=_spawnZoneNearLimit}}) then { throw ("a spawn zone"); }; // Check for nearby trader zones - if ((_traderZoneNearLimit>0) && {((markertype _x) == "ExileTraderZone") && {((getMarkerPos _x) distance2D _pos)<=_traderZoneNearLimit}}) then + if ((_traderZoneNearLimit>0) && {((markertype _x) in DMS_TraderZoneMarkerTypes) && {((getMarkerPos _x) distance2D _pos)<=_traderZoneNearLimit}}) then { throw ("a trader zone"); }; @@ -144,7 +144,7 @@ else }; } forEach allMapMarkers; - + // Check for nearby players // This is done last because it is likely to be the most resource intensive. if ((_playerNearLimit>0) && {[_pos,_playerNearLimit] call DMS_fnc_IsPlayerNearby}) then @@ -157,7 +157,7 @@ else throw ("a territory"); }; - + // No exceptions found _isValidPos = true; @@ -179,4 +179,4 @@ else }; -_isValidPos; \ No newline at end of file +_isValidPos; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_MissionSuccessState.sqf b/@ExileServer/addons/a3_dms/scripts/fn_MissionSuccessState.sqf index bba292e..abe446d 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_MissionSuccessState.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_MissionSuccessState.sqf @@ -1,7 +1,7 @@ /* DMS_fnc_MissionSuccessState Created by eraser1 - + Usage: [ [_completionType1,_completionArgs1,_isAbsoluteCondition], @@ -54,7 +54,7 @@ _exit = false; (format ["MissionSuccessState :: Checking completion type ""%1"" with argument |%2|. Absolute: %3",_completionType,_completionArgs,_absoluteWinCondition]) call DMS_fnc_DebugLog; }; - switch (toLower _completionType) do + switch (toLower _completionType) do { case "kill": { @@ -70,6 +70,10 @@ _exit = false; { _success = _completionArgs call DMS_fnc_IsPlayerNearby; }; + case "external": // This is a special completion type. It is intended to be a flag for people who want to control mission completion using _onMonitorStart and _onMonitorEnd through array manipulation. You probably don't want to use this unless you know what you're doing. + { + _success = _completionArgs; + }; default { diag_log format ["DMS ERROR :: Invalid completion type (%1) with args: %2",_completionType,_completionArgs]; @@ -93,4 +97,4 @@ _exit = false; }; } forEach _this; -_success; \ No newline at end of file +_success; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Dynamic.sqf b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Dynamic.sqf index a0a6de1..e4856aa 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Dynamic.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Dynamic.sqf @@ -8,7 +8,7 @@ [ _pos, _completionInfo, //<--- More info in "DMS_fnc_MissionSuccessState" - [_timeStarted,_timeUntilFail], + [_timeStarted,_failTime], [_AIUnit1,_AIUnit2,...,_AIUnitX], [ [_cleanupObj1,_cleanupObj2,...,_cleanupObjX], @@ -35,14 +35,14 @@ */ if (DMS_Mission_Arr isEqualTo []) exitWith {}; // Empty array, no missions running -private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_buildings", "_vehs", "_crate_info_array", "_mines", "_missionName", "_msgWIN", "_msgLose", "_markers", "_missionSide", "_arr", "_cleanupList"]; +private ["_pos", "_completionInfo", "_timeStarted", "_failTime", "_units", "_buildings", "_vehs", "_crate_info_array", "_mines", "_missionName", "_msgWIN", "_msgLose", "_markers", "_missionSide", "_arr", "_cleanupList"]; { _pos = _x select 0; - _success = (_x select 1) call DMS_fnc_MissionSuccessState; + _completionInfo = _x select 1; _timeStarted = _x select 2 select 0; - _timeUntilFail = _x select 2 select 1; + _failTime = _x select 2 select 1; _units = _x select 3; _buildings = _x select 4 select 0; _vehs = _x select 4 select 1; @@ -62,6 +62,13 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build try { + /* + if (DMS_DEBUG) then + { + (format ["MissionsMonitor_Dynamic :: Checking Mission Status (index %1): ""%2"" at %3",_forEachIndex,_missionName,_pos]) call DMS_fnc_DebugLog; + }; + */ + if !(_onMonitorStart isEqualTo {}) then { if (DMS_DEBUG) then @@ -71,15 +78,8 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build _x call _onMonitorStart; }; - /* - if (DMS_DEBUG) then - { - (format ["MissionsMonitor_Dynamic :: Checking Mission Status (index %1): ""%2"" at %3",_forEachIndex,_missionName,_pos]) call DMS_fnc_DebugLog; - }; - */ - - if (_success) then + if (_completionInfo call DMS_fnc_MissionSuccessState) then { DMS_CleanUpList pushBack [_buildings,diag_tickTime,DMS_CompletedMissionCleanupTime]; @@ -130,12 +130,13 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build }; { - _code = _x; + _params = _x select 0; + _code = _x select 1; if (_code isEqualType "") then { _code = compile _code; }; - call _code; + _params call _code; } forEach _onSuccessScripts; [_missionName,_msgWIN] call DMS_fnc_BroadcastMissionStatus; @@ -146,14 +147,14 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build throw format ["Mission (%1) Success at %2 with message %3.",_missionName,_pos,_msgWIN]; }; - if ((diag_tickTime-_timeStarted)>_timeUntilFail) then + if ((diag_tickTime-_timeStarted)>_failTime) then { // Check to see if the timeout should be extended before ending the mission. if ((DMS_MissionTimeoutResetRange>0) && {[_pos,DMS_MissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby}) then { - _x set [2,[diag_tickTime,_timeUntilFail]]; + _x set [2,[diag_tickTime,_failTime]]; - throw format ["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_timeUntilFail,_pos]; + throw format ["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_pos]; }; //Nobody is nearby so just cleanup objects from here @@ -182,22 +183,36 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build }; { - _code = _x; + _params = _x select 0; + _code = _x select 1; if (_code isEqualType "") then { _code = compile _code; }; - call _code; + _params call _code; } forEach _onFailScripts; [_missionName,_msgLose] call DMS_fnc_BroadcastMissionStatus; [_markers,"lose"] call DMS_fnc_RemoveMarkers; - + DMS_Mission_Arr deleteAt _forEachIndex; throw format ["Mission (%1) Fail at %2 with message %3.",_missionName,_pos,_msgLose]; }; + if ((diag_tickTime-_timeStarted)>DMS_MissionTimeoutResetFrequency) then + { + if ((DMS_MissionTimeoutResetRange>0) && {[_pos,DMS_MissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby}) then + { + _x set [2,[diag_tickTime,_failTime]]; + + if (DMS_DEBUG) then + { + format["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_pos] call DMS_fnc_DebugLog; + }; + }; + }; + if (DMS_MarkerText_ShowAICount) then { private ["_dot", "_text"]; @@ -250,4 +265,4 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build (format ["MissionsMonitor_Dynamic :: %1",_exception]) call DMS_fnc_DebugLog; }; }; -} forEach DMS_Mission_Arr; \ No newline at end of file +} forEach DMS_Mission_Arr; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Static.sqf b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Static.sqf index 0a13723..e3ce9d0 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Static.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor_Static.sqf @@ -11,7 +11,7 @@ _missionPos, _completionInfo, //<--- More info in "DMS_fnc_MissionSuccessState" _groupReinforcementsInfo, //<--- More info in "DMS_fnc_GroupReinforcementsManager" - [_timeStarted,_timeUntilFail], + [_timeStarted,_failTime], [_AIGroup1,_AIGroup2,...,_AIGroupX], [ [_cleanupObj1,_cleanupObj2,...,_cleanupObjX], @@ -43,7 +43,7 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati { - private ["_missionPos", "_completionInfo", "_groupReinforcementsInfo", "_timing", "_inputAIUnits", "_missionObjs", "_msgInfo", "_markers", "_missionSide", "_missionDifficulty", "_missionEvents", "_missionScripts", "_success", "_timeStarted", "_timeUntilFail", "_buildings", "_vehs", "_crate_info_array", "_mines", "_missionName", "_msgWIN", "_msgLose", "_onSuccessScripts", "_onFailScripts"]; + private ["_missionPos", "_completionInfo", "_groupReinforcementsInfo", "_timing", "_inputAIUnits", "_missionObjs", "_msgInfo", "_markers", "_missionSide", "_missionDifficulty", "_missionEvents", "_missionScripts", "_timeStarted", "_failTime", "_buildings", "_vehs", "_crate_info_array", "_mines", "_missionName", "_msgWIN", "_msgLose", "_onSuccessScripts", "_onFailScripts"]; if !(_x params [ @@ -66,9 +66,8 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati diag_log format ["DMS ERROR :: Invalid Index (%1) in DMS_StaticMission_Arr: %2",_forEachIndex,_x]; }; - _success = _completionInfo call DMS_fnc_MissionSuccessState; _timeStarted = _timing select 0; - _timeUntilFail = _timing select 1; + _failTime = _timing select 1; _buildings = _missionObjs select 0; _vehs = _missionObjs select 1; _crate_info_array = _missionObjs select 2; @@ -80,7 +79,7 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati _onFailScripts = _missionScripts select 1; _onMonitorStart = _missionScripts select 2; _onMonitorEnd = _missionScripts select 3; - + try { /* @@ -100,7 +99,7 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati }; - if (_success) then + if (_completionInfo call DMS_fnc_MissionSuccessState) then { DMS_CleanUpList pushBack [_buildings,diag_tickTime,DMS_CompletedMissionCleanupTime]; @@ -142,12 +141,13 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati }; { - _code = _x; + _params = _x select 0; + _code = _x select 1; if (_code isEqualType "") then { _code = compile _code; }; - call _code; + _params call _code; } forEach _onSuccessScripts; [_missionName,_msgWIN] call DMS_fnc_BroadcastMissionStatus; @@ -159,14 +159,14 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati throw format ["Mission (%1) Success at %2 with message %3.",_missionName,_missionPos,_msgWIN]; }; - if ((diag_tickTime-_timeStarted)>_timeUntilFail) then + if ((diag_tickTime-_timeStarted)>_failTime) then { // Check to see if the timeout should be extended before ending the mission. if ((DMS_StaticMissionTimeoutResetRange>0) && {[_missionPos,DMS_StaticMissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby}) then { - _x set [2,[diag_tickTime,_timeUntilFail]]; + _x set [2,[diag_tickTime,_failTime]]; - throw format ["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_timeUntilFail,_missionPos]; + throw format ["Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_missionPos]; }; //Nobody is nearby so just cleanup objects from here @@ -186,23 +186,37 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati { - _code = _x; + _params = _x select 0; + _code = _x select 1; if (_code isEqualType "") then { _code = compile _code; }; - call _code; + _params call _code; } forEach _onFailScripts; [_missionName,_msgLose] call DMS_fnc_BroadcastMissionStatus; [_markers,"lose"] call DMS_fnc_RemoveMarkers; - + DMS_StaticMission_Arr deleteAt _forEachIndex; DMS_RunningStaticMissions deleteAt _forEachIndex; throw format ["Mission (%1) Fail at %2 with message %3.",_missionName,_missionPos,_msgLose]; }; + if ((diag_tickTime-_timeStarted)>DMS_SMissionTimeoutResetFrequency) then + { + if ((DMS_StaticMissionTimeoutResetRange>0) && {[_missionPos,DMS_StaticMissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby}) then + { + _x set [2,[diag_tickTime,_failTime]]; + + if (DMS_DEBUG) then + { + format["Static Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_pos] call DMS_fnc_DebugLog; + }; + }; + }; + if (DMS_MarkerText_ShowAICount_Static) then { private ["_dot", "_text"]; @@ -261,10 +275,10 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati _x call _onMonitorEnd; }; - + if (DMS_DEBUG) then { (format ["MissionsMonitor_Static :: %1",_exception]) call DMS_fnc_DebugLog; }; }; -} forEach DMS_StaticMission_Arr; \ No newline at end of file +} forEach DMS_StaticMission_Arr; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf b/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf index d0b0186..dce38c0 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf @@ -22,11 +22,11 @@ if (DMS_DEBUG) then { (format ["OnKilled :: Logging AI death with parameters: %1",_this]) call DMS_fnc_DebugLog; }; - -_unit = _this select 0 select 0; -_killer = _this select 0 select 1; -_side = _this select 1; -_type = _this select 2; + +_unit = _this select 0; +_killer = _this select 1; +_side = _unit getVariable ["DMS_AI_Side", "bandit"]; +_type = _unit getVariable ["DMS_AI_Type", "soldier"]; _launcher = secondaryWeapon _unit; _launcherVar = _unit getVariable ["DMS_AI_Launcher",""]; _playerObj = objNull; @@ -67,7 +67,7 @@ if (DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then _unit spawn { sleep 0.5; - + { _holder = _x; { @@ -82,7 +82,7 @@ if (DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then }; _unit removeWeaponGlobal _launcher; - + { if (_x isKindOf ["CA_LauncherMagazine", configFile >> "CfgMagazines"]) then { @@ -123,7 +123,7 @@ if (!isNull _av) then if (DMS_DEBUG) then { - (format["OnKilled :: Destroying used AI vehicle %1, disabling simulation, and adding to cleanup.",typeOf _av]) call DMS_fnc_DebugLog; + (format["OnKilled :: Destroying used AI vehicle %1, and disabling simulation.",typeOf _av]) call DMS_fnc_DebugLog; }; }; } @@ -175,7 +175,7 @@ if (!isNull _av) then unassignVehicle _driver; moveOut _driver; - + _driver disableCollisionWith _av; _av setVehicleAmmoDef 1; @@ -195,7 +195,7 @@ if (!isNull _av) then if !(alive _driver) exitWith {}; _driver moveInGunner _av; - + _driver enableCollisionWith _av; if (DMS_DEBUG) then @@ -206,7 +206,7 @@ if (!isNull _av) then if (_owner!=2) then { _start = time; - + // Controlling AI... yes. I have to do this waitUntil { @@ -214,7 +214,7 @@ if (!isNull _av) then [_driver] orderGetIn true; _driver moveInGunner _av; - + (((gunner _av) isEqualTo _driver) || {(time-_start)>30}) }; @@ -228,7 +228,7 @@ if (!isNull _av) then [_driver] orderGetIn true; _driver moveInGunner _av; - + (((gunner _av) isEqualTo _driver) || {(time-_start)>30}) }; @@ -319,4 +319,4 @@ if (isPlayer _killer) then // Let Exile handle the AI Body cleanup. -_unit setVariable ["ExileDiedAt",time]; \ No newline at end of file +_unit setVariable ["ExileDiedAt",time]; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf b/@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf index 39d322f..b90d0aa 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf @@ -55,7 +55,7 @@ if ((!isNull _playerObj) && {(_playerUID != "") && {_playerObj isKindOf "Exile_U }; - if (_roadKilled && {DMS_Diff_RepOrTabs_on_roadkill}) then + if (_roadKilled && {_unit getVariable ["DMS_Diff_RepOrTabs_on_roadkill",DMS_Diff_RepOrTabs_on_roadkill]}) then { _moneyChange = missionNamespace getVariable [format ["DMS_%1_%2_RoadkillMoney",_AISide,_AIType],0]; _repChange = missionNamespace getVariable [format ["DMS_%1_%2_RoadkillRep",_AISide,_AIType],0]; @@ -67,11 +67,13 @@ if ((!isNull _playerObj) && {(_playerUID != "") && {_playerObj isKindOf "Exile_U _playerMoney = _playerObj getVariable ["ExileMoney", 0]; _playerRespect = _playerObj getVariable ["ExileScore", 0]; + /* if (DMS_DEBUG) then { format ["PlayerAwardOnAIKill :: Attempting to give %1 (%2) %3 poptabs and %4 respect. Player currently has %5 tabs and %6 respect.", name _playerObj, _playerUID, _moneyChange, _repChange, _playerMoney, _playerRespect] call DMS_fnc_DebugLog; }; - + */ + if (_moneyChange!=0) then { private ["_msgType", "_msgParams"]; @@ -153,6 +155,21 @@ if ((!isNull _playerObj) && {(_playerUID != "") && {_playerObj isKindOf "Exile_U // Update client database entry format["setAccountMoneyAndRespect:%1:%2:%3", _playerMoney, _playerRespect, _playerUID] call ExileServer_system_database_query_fireAndForget; + + if (DMS_Show_Party_Kill_Notification) then + { + private ["_group", "_members", "_msg"]; + + _group = group _playerObj; + _members = units _group; + if (!(_group isEqualTo ExileGraveyardGroup) && {(count _members)>1}) then + { + _msg = format["%1 killed %2 and received %3 poptabs and %4 respect.",name _playerObj,name _unit,_moneyChange,_repChange]; + { + _msg remoteExecCall ["systemChat", _x]; + } forEach _members; + }; + }; } else { @@ -168,4 +185,4 @@ else { format ["PlayerAwardOnAIKill :: No reward for non-player _playerObj: %1",_playerObj] call DMS_fnc_DebugLog; }; -}; \ No newline at end of file +}; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SetAILocality.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SetAILocality.sqf index c1564f0..4a9f6d6 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SetAILocality.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SetAILocality.sqf @@ -57,6 +57,14 @@ if (!isNull _client) then ExileServerOwnershipSwapQueue pushBack [_AI,_client]; }; + if (DMS_ai_offload_notifyClient) then + { + private "_msg"; + _msg = format ["DMS :: AI %1 |%2| has been offloaded to you.",_AIType,_AI]; + _msg remoteExecCall ["systemChat", _client]; + _msg remoteExecCall ["diag_log", _client]; + }; + if (DMS_DEBUG) then { (format ["SetAILocality :: Ownership swap of %1 (%4) to %2 (%3) is initialized. Initial swap attempt successful: %5",_AI, name _client, getPlayerUID _client, _AIType, _swapped]) call DMS_fnc_DebugLog; @@ -72,4 +80,4 @@ else }; false -}; \ No newline at end of file +}; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior.sqf index e7c8e56..203eaeb 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior.sqf @@ -4,7 +4,7 @@ Usage: [ - _group, // GROUP or OBJECT: Group or unit to change the behavior of + _group, // GROUP or OBJECT: Group or unit whose behavior is to be changed. _pos, // ARRAY (positionATL): Location for the AI to guard _difficulty, // STRING: Difficulty of the AI _behavior // (OPTIONAL) STRING: AI Behavior. Refer to: https://community.bistudio.com/wiki/setBehaviour @@ -36,7 +36,7 @@ try if (_group isEqualType objNull) then { if !(alive _group) throw "_group is a dead object!"; - + _group = group _group; }; } @@ -52,7 +52,6 @@ catch if (_exit) exitWith {false}; -// Mostly for DMS_fnc_SpawnAIVehicle, since setting behavior to COMBAT makes the driving suck... _behavior = if ((count _this)>3) then {_this select 3;} else {"COMBAT"}; @@ -60,10 +59,34 @@ _group setCombatMode "RED"; _group setBehaviour _behavior; -if (_difficulty == "random") then -{ - _difficulty = DMS_ai_skill_random call BIS_fnc_selectRandom; -}; +_difficulty = + switch (toLower _difficulty) do + { + case "random": + { + DMS_ai_skill_random call BIS_fnc_selectRandom; + }; + + case "randomdifficult": + { + DMS_ai_skill_randomDifficult call BIS_fnc_selectRandom; + }; + + case "randomeasy": + { + DMS_ai_skill_randomEasy call BIS_fnc_selectRandom; + }; + + case "randomintermediate": + { + DMS_ai_skill_randomIntermediate call BIS_fnc_selectRandom; + }; + + default + { + _difficulty; + }; + }; _radius = missionNamespace getVariable [format["DMS_AI_WP_Radius_%1",_difficulty],40]; @@ -87,4 +110,4 @@ _wp setWaypointType "CYCLE"; -true \ No newline at end of file +true diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior_Separate.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior_Separate.sqf new file mode 100644 index 0000000..ef3c64c --- /dev/null +++ b/@ExileServer/addons/a3_dms/scripts/fn_SetGroupBehavior_Separate.sqf @@ -0,0 +1,54 @@ +/* + DMS_fnc_SetGroupBehavior_Separate + created by eraser1 + + Takes in an array of unit(s), moves them to a temporary group, sets their behavior, then moves them back to the original group. + Use this function if you want to change the behavior of certain units in a group without adjusting the behavior of the whole group. + + Usage: + [ + [ // ARRAY of OBJECTs: Units whose behavior will be changed + _unit1, + _unit2, + ... + _unitN + ], + _finalGroup, // GROUP: The final group that the units will be moved to. + _pos, // ARRAY (positionATL): Location for the AI to guard + _difficulty, // STRING: Difficulty of the AI + _behavior // (OPTIONAL) STRING: AI Behavior. Refer to: https://community.bistudio.com/wiki/setBehaviour + ] call DMS_fnc_SetGroupBehavior_Separate; + + Returns true if behavior was successfully changed, false otherwise. +*/ + +if !(params +[ + ["_units",[],[[]]], + ["_finalGroup",grpNull,[grpNull]], + ["_pos",[0,0,0],[[]],[2,3]], + ["_difficulty","moderate",[""]] +]) +then +{ + diag_log format ["DMS ERROR :: Calling DMS_fnc_SetGroupBehavior_Separate with invalid params: %1",_this]; +}; + +_behavior = if ((count _this)>3) then {_this select 3;} else {"COMBAT"}; + +_tmpGroup = createGroup (side _finalGroup); + +_units joinSilent _tmpGroup; + +_return = [ + _tmpGroup, + _pos, + _difficulty, + _behavior +] call DMS_fnc_SetGroupBehavior; + +_units joinSilent _finalGroup; +deleteGroup _tmpGroup; + + +_return diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf index bb9addc..a5bc550 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf @@ -60,10 +60,35 @@ else }; }; -if(_difficulty == "random") then -{ - _difficulty = DMS_ai_skill_random call BIS_fnc_selectRandom; -}; +_difficulty = + switch (toLower _difficulty) do + { + case "random": + { + DMS_ai_skill_random call BIS_fnc_selectRandom; + }; + + case "randomdifficult": + { + DMS_ai_skill_randomDifficult call BIS_fnc_selectRandom; + }; + + case "randomeasy": + { + DMS_ai_skill_randomEasy call BIS_fnc_selectRandom; + }; + + case "randomintermediate": + { + DMS_ai_skill_randomIntermediate call BIS_fnc_selectRandom; + }; + + default + { + _difficulty; + }; + }; + //Create unit _unit = _group createUnit [DMS_AI_Classname, _pos, [], 0,"FORM"]; @@ -111,7 +136,7 @@ else }; // Unit name -_unit setName format["[DMS_%3Unit_%1%2]",_class,floor(random 1000),toUpper _side]; +_unit setName format["[DMS %1 %2 Unit %3]",toUpper _side,_class,floor(random 1000)]; if (!_useCustomGear) then { @@ -157,13 +182,13 @@ if (!_useCustomGear) then _weapon = (missionNamespace getVariable [format ["DMS_%1_weps",_class],DMS_assault_weps]) call BIS_fnc_selectRandom; [_unit, _weapon, 6 + floor(random 3)] call BIS_fnc_addWeapon; _unit selectWeapon _weapon; - - + + if((random 100) <= (missionNamespace getVariable [format["DMS_%1_optic_chance",_class],0])) then { _unit addPrimaryWeaponItem ((missionNamespace getVariable [format ["DMS_%1_optics",_class],DMS_assault_optics]) call BIS_fnc_selectRandom); }; - + if (_nighttime && {(random 100) <= DMS_ai_nighttime_accessory_chance}) then { _unit addPrimaryWeaponItem (["acc_pointer_IR","acc_flashlight"] call BIS_fnc_selectRandom); @@ -180,7 +205,7 @@ if (!_useCustomGear) then if(_suppressor != "") then { _unit addPrimaryWeaponItem _suppressor; - }; + }; }; // In case spawn position is water @@ -311,7 +336,7 @@ else // Soldier killed event handler -_unit addMPEventHandler ["MPKilled",'if (isServer) then {[_this, '+str _side+', '+str _type+'] call DMS_fnc_OnKilled;};']; +_unit addMPEventHandler ["MPKilled",'if (isServer) then {_this call DMS_fnc_OnKilled;};']; // Remove ramming damage from players. Also remove any damage within 5 seconds of spawning. // Will not work if unit is not local (offloaded) @@ -366,4 +391,4 @@ if (DMS_DEBUG) then -_unit \ No newline at end of file +_unit diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIVehicle.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIVehicle.sqf index 2721829..e9583aa 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIVehicle.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIVehicle.sqf @@ -14,11 +14,11 @@ _side, // "bandit","hero", etc. _vehClass // (OPTIONAL) String: classname of the Vehicle. Use "random" to select a random one from DMS_ArmedVehicles ] call DMS_fnc_SpawnAIVehicle; - + Returns the spawned vehicle. */ -private ["_OK", "_positions", "_veh", "_spawnPos", "_gotoPos", "_vehClass", "_driver", "_gunner", "_tmpGroup", "_group", "_class", "_difficulty", "_side"]; +private ["_OK", "_positions", "_veh", "_spawnPos", "_gotoPos", "_vehClass", "_driver", "_gunner", "_group", "_class", "_difficulty", "_side", "_crewCount"]; if !(params @@ -58,7 +58,6 @@ if (_vehClass == "random") then _vehClass = DMS_ArmedVehicles call BIS_fnc_selectRandom; }; -_tmpGroup = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]); _veh = createVehicle [_vehClass, _spawnPos, [], 0, "NONE"]; _veh setFuel 1; @@ -67,26 +66,23 @@ _veh setDir (random 360); _veh lock 2; _group addVehicle _veh; -_tmpGroup addVehicle _veh; - - -_driver = [_tmpGroup,_spawnPos,_class,_difficulty,_side,"Vehicle"] call DMS_fnc_SpawnAISoldier; -_gunner = [_tmpGroup,_spawnPos,_class,_difficulty,_side,"Vehicle"] call DMS_fnc_SpawnAISoldier; +_driver = [_group,_spawnPos,_class,_difficulty,_side,"Vehicle"] call DMS_fnc_SpawnAISoldier; _driver moveInDriver _veh; -_gunner moveInGunner _veh; - _driver setVariable ["DMS_AssignedVeh",_veh]; -_gunner setVariable ["DMS_AssignedVeh",_veh]; +_crewCount = +{ + _unit = [_group,_spawnPos,_class,_difficulty,_side,"Vehicle"] call DMS_fnc_SpawnAISoldier; + _unit moveInTurret [_veh, _x]; + _unit setVariable ["DMS_AssignedVeh",_veh]; + true +} count (allTurrets [_veh, true]); -[_tmpGroup,_gotoPos,_difficulty,"AWARE"] call DMS_fnc_SetGroupBehavior; - -[_driver,_gunner] joinSilent _group; if (DMS_DEBUG) then { - (format ["SpawnAIVehicle :: Created a %1 armed vehicle (%2) at %3 with %4 difficulty to group %5",_side,_vehClass,_spawnPos,_difficulty,_group]) call DMS_fnc_DebugLog; + (format ["SpawnAIVehicle :: Created a %1 armed vehicle (%2) with %7 crew members at %3 going to %4 with %5 difficulty to group %6.",_side,_vehClass,_spawnPos,_gotoPos,_difficulty,_group,_crewCount+1]) call DMS_fnc_DebugLog; }; -_veh \ No newline at end of file +_veh diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnPersistentVehicle.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnPersistentVehicle.sqf index 460943d..57dfe31 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnPersistentVehicle.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnPersistentVehicle.sqf @@ -84,7 +84,7 @@ try // Create and set the vehicle _vehObj = [_vehicleClass,_pos] call DMS_fnc_SpawnNonPersistentVehicle; - + if (_spawnATL) then { _vehObj setPosATL _pos; @@ -100,7 +100,7 @@ try // Set up vars _vehObj setVariable ["ExileIsPersistent", true]; _vehObj setVariable ["ExileAccessCode", _pinCode]; - _vehObj setVariable ["ExileOwnerUID", "76561198027700602"]; // That is my (eraser1's) PUID. Just so you don't think I'm trying to be sneaky... + _vehObj setVariable ["ExileOwnerUID", "DMS_PersistentVehicle"]; // Don't change this unless you know what you're doing. // Deny access until specified to do so. _vehObj setVariable ["ExileIsLocked",-1]; @@ -115,4 +115,4 @@ catch -_vehObj \ No newline at end of file +_vehObj diff --git a/@ExileServer/addons/a3_dms/scripts/fn_TargetsKilled.sqf b/@ExileServer/addons/a3_dms/scripts/fn_TargetsKilled.sqf index 6f6d739..957d036 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_TargetsKilled.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_TargetsKilled.sqf @@ -1,7 +1,7 @@ /* DMS_fnc_TargetsKilled Created by eraser1 - + Usage: [ _unit, @@ -12,11 +12,6 @@ Will accept non-array argument of group, unit, or object. */ -if !(_this isEqualType []) then -{ - _this = [_this]; -}; - if (_this isEqualTo []) exitWith { diag_log "DMS ERROR :: Calling DMS_TargetsKilled with empty array!"; @@ -29,55 +24,23 @@ _killed = false; try { { - if (_x isEqualType objNull) then + private ["_lastDistanceCheckTime", "_spawnPos"]; + + _lastDistanceCheckTime = _x getVariable ["DMS_LastAIDistanceCheck",time]; + _pos = getPosWorld _x; + _spawnPos = _x getVariable ["DMS_AISpawnPos",_pos]; + + if ((DMS_MaxAIDistance>0) && {((time - _lastDistanceCheckTime)>DMS_AIDistanceCheckFrequency) && {(_pos distance2D _spawnPos)>DMS_MaxAIDistance}}) then { - if (!isNull _x && {alive _x}) then - { - private ["_lastDistanceCheckTime", "_spawnPos"]; - - _lastDistanceCheckTime = _x getVariable ["DMS_LastAIDistanceCheck",time]; - _pos = getPosWorld _x; - _spawnPos = _x getVariable ["DMS_AISpawnPos",_pos]; - - if ((DMS_MaxAIDistance>0) && {((time - _lastDistanceCheckTime)>DMS_AIDistanceCheckFrequency) && {(_pos distance2D _spawnPos)>DMS_MaxAIDistance}}) then - { - _x setDamage 1; - diag_log format ["Killed a runaway unit! |%1| was more than %2m away from its spawn position %3!",_x,DMS_MaxAIDistance,_x getVariable "DMS_AISpawnPos"]; - } - else - { - throw _x; - }; - }; + _x setDamage 1; + diag_log format ["Killed a runaway unit! |%1| was more than %2m away from its spawn position %3!",_x,DMS_MaxAIDistance,_spawnPos]; } else { - if !(_x isEqualType grpNull) exitWith - { - diag_log format ["DMS ERROR :: %1 is neither OBJECT nor GROUP!",_x]; - }; - { - if (alive _x) then - { - private ["_lastDistanceCheckTime", "_spawnPos"]; - - _lastDistanceCheckTime = _x getVariable ["DMS_LastAIDistanceCheck",time]; - _pos = getPosWorld _x; - _spawnPos = _x getVariable ["DMS_AISpawnPos",_pos]; - - if ((DMS_MaxAIDistance>0) && {((time - _lastDistanceCheckTime)>DMS_AIDistanceCheckFrequency) && {(_pos distance2D _spawnPos)>DMS_MaxAIDistance}}) then - { - _x setDamage 1; - diag_log format ["Killed a runaway unit! |%1| was more than %2m away from its spawn position %3!",_x,DMS_MaxAIDistance,_x getVariable "DMS_AISpawnPos"]; - } - else - { - throw _x; - }; - }; - } forEach (units _x); + _x setVariable ["DMS_LastAIDistanceCheck",time]; + throw _x; }; - } forEach _this; + } forEach (_this call DMS_fnc_GetAllUnits); // DMS_fnc_GetAllUnits will return living AI unit objects only, so we only need to check for runaway units _killed = true; } @@ -89,4 +52,4 @@ catch }; }; -_killed; \ No newline at end of file +_killed; diff --git a/README.md b/README.md index 8133193..993b346 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # To the User: -####Read the instructions carefully. Before leaving any questions regarding DMS, please read through the [DMS "config.sqf"](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf); the majority of the questions we receive are answered (directly or indirectly) by the config. +####Read the instructions carefully. Before leaving any questions regarding DMS, please read through the [DMS "config.sqf"](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf?ts=4); the majority of the questions we receive are answered (directly or indirectly) by the config. ####Disclaimer: Defent's Mission System (DMS) is written from the ground up to be an efficient, easy to install, and vastly customizable mission system for the ArmA 3 [Exile Mod](http://www.exilemod.com/). You are welcome to port DMS or any of its functions for any other mod or (legal) purposes. Providing credit is appreciated. -However, creating such a mission system takes a lot of time and testing. We (the authors of DMS) are not perfect, and as a result, there may be bugs, glitches, and/or errors within DMS. We appreciate your co-operation in identifying and resolving such issues to improve DMS; however we are not liable for any issues resulting from the usage of DMS on/by your server. We are also not liable to help you in resolving any issues that may arise, although we will attempt to help you to some degree in most cases. +However, creating such a mission system takes a lot of time and testing. We (the authors of DMS) are not perfect, and as a result, there may be bugs, glitches, and/or errors within DMS. We appreciate your co-operation in identifying and resolving such issues to improve DMS; however we are not liable for any issues resulting from the usage of DMS on/by your server. We are also not liable to help you in resolving any issues that may arise, although we may attempt to help you to some degree in most cases. ___ @@ -12,7 +12,7 @@ ___ # Instructions [Please search the DMS thread before asking any questions](http://www.exilemod.com/topic/61-dms-defents-mission-system/?do=findComment&comment=242) -DMS will work "out-of-the-box" for almost any map. You have to keep in mind that if the map is too small (such as Stratis), then you will need to reduce the [Mission spawn location settings](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf#L63-L77). Also, for especially hilly maps (such as Panthera), you will need to reduce the [Minimum surfaceNormal](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf#L76) (the config value is automatically adjusted for some maps. You can check the [map configs](https://github.com/Defent/DMS_Exile/tree/master/%40ExileServer/addons/a3_dms/map_configs) to see the adjusted config value overwrites). +DMS will work "out-of-the-box" for almost any map. You have to keep in mind that if the map is too small (such as Stratis), then you will need to reduce the [Mission spawn location settings](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf?ts=4). Also, for especially hilly maps (such as Panthera), you will need to reduce the [Minimum surfaceNormal](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf?ts=4) (the config value is automatically adjusted for some maps. You can check the [map configs](https://github.com/Defent/DMS_Exile/tree/master/%40ExileServer/addons/a3_dms/map_configs) to see the adjusted config value overwrites). ## BattlEye Filters: It is highly recommended that you add @@ -35,7 +35,7 @@ after "7 createVehicle" 1. Download the [a3_dms](https://github.com/Defent/DMS_Exile/tree/master/%40ExileServer/addons/a3_dms) folder -2. Edit the [config.sqf](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf) to your preferences. +2. Edit the [config.sqf](https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/config.sqf?ts=4) to your preferences. 3. Pack the a3_dms folder with a PBO tool ([PBO Manager](http://www.armaholic.com/page.php?id=16369), [Eliteness](https://dev.withsix.com/projects/mikero-pbodll/files), or [the Arma 3 Tools suite](http://store.steampowered.com/app/233800/)) 4. Put the generated PBO in your ```@ExileServer\addons\``` directory. It should be alongside ```exile_server.pbo``` and ```exile_server_config.pbo```. @@ -79,10 +79,15 @@ ___ - [maca134](http://maca134.co.uk/portfolio/m3editor-arma-3-map-editor/) for M3Editor Stuff - [Darth Rogue from SOA](http://soldiersofanarchy.net/) for the awesome base for the first DMS static mission :D - [William from Refugees of the Fallen](http://refugeesofthefallen.enjin.com/) for the amazing slums static mission base and ideas :) -- [JamieKG from Eternal Gamer](http://eternal-gamer.com/) for testing and reporting issues. -- [Valthos from The Altis Project](https://www.thealtisproject.co.uk/) for testing and reporting issues. - Everbody's feedback on [the DMS thread on exile forums](http://www.exilemod.com/topic/61-dms-defents-mission-system/?do=findComment&comment=242) +#### Testers/Reporters: +- [William from Refugees of the Fallen](http://refugeesofthefallen.enjin.com/) +- [JamieKG from Eternal Gamer](http://eternal-gamer.com/) +- [Valthos from The Altis Project](https://www.thealtisproject.co.uk/) +- [Flowrider from Optimum Gaming](http://www.optimum-multigaming.com/) +- [CEN from ATD Gaming](http://atdgaming.com/) + ___ # Roadmap: @@ -116,8 +121,49 @@ ___ ___ # Changelog: +#### **BETA CHANGELOG** Last Updated January 6, 2015 (6:30 PM CST-America): +* **NEW CONFIG VALUES:** + + DMS_MissionTimeoutResetFrequency + DMS_SMissionTimeoutResetFrequency + DMS_SpawnZoneMarkerTypes + DMS_TraderZoneMarkerTypes + DMS_BanditMissionsOnServerStart + DMS_StaticMissionsOnServerStart + DMS_Show_Party_Kill_Notification + DMS_ai_offload_notifyClient + DMS_ai_skill_randomDifficult + DMS_ai_skill_randomEasy + DMS_ai_skill_randomIntermediate + DMS_MinimumMagCount + DMS_MaximumMagCount +* Created a couple new config examples. +* DMS will now use its own "PUID" for spawning persistent vehicles (instead of mine). +* Added "Taviana" to default map configs. +* You can now spawn missions on server start. Make sure to add them to the mission types beforehand. +* Fixed default values for reinforcements on saltflats and slums static Altis missions. +* ```_onSuccessScripts``` and ```_onFailScripts``` now use a new structure: it should be ```[[param,code],[param,code]]``` instead of ```[code,code]```. +* DMS now uses ```remoteExecCall``` instead of Exile client broadcast functions for "systemChatRequest" and "standardHintRequest". +* You can now customize the magazine range for guns in a crate. The "fillCrate" function is far from perfect, and I am working on improving it. Ideas are appreciated. +* Adjusted the logic to spawning AI reinforcements; the locations will be shuffled before the AI are spawned, and every location will be used at least once if there are more AI than reinforcement locations. +* You can now define custom markers for Trader/Spawn zones. Keep in mind that they are case-sensitive. +* ```_onMonitorStart``` will now run BEFORE success state is checked. As a result, I added a new "completion type" in "fn_MissionSuccessState" so that you can force mission completion via array manipulations. +* "fn_OnKilled" now gets AI side and type using "getVariable" instead of having to include them in the "addMPEventHandler". If you are using the function for custom purposes, you will need to edit your usage. +* You can now choose whether or not an AI produces different respect or tabs when roadkilled individually. +* You can now allow party members to be notified in chat when a party member kills an AI. +* You can now notify clients when AI have been offloaded to them. +* You now have greater control over AI difficulty; you can now manually define "random" presets to include/exclude special difficulty types. +* New function: "DMS_fnc_SetGroupBehavior_Separate" - You can pass an array of units and define their behavior without affecting the rest of the group. +* "DMS_fnc_SpawnAIVehicle" is overhauled: instead of only spawning a driver and a gunner, the function uses "allTurrets" to completely fill the crew of a vehicle. +* "DMS_fnc_SpawnAIVehicle" no longer sets the crew's behavior to "aware". +* Optimized "DMS_fnc_TargetsKilled". + + + + + #### December 24, 2015 (1:45 PM CST-America): -* Fixed an issue where you couldn't take stuff out of a crate if you had "DMS_EnableBoxMoving" set to "false". Thanks to [Flowrider](http://www.exilemod.com/profile/31-flowrider85/) for the report. +* Fixed an issue where you couldn't take stuff out of a crate if you had "DMS_EnableBoxMoving" set to "false". Thanks to [Flowrider from Optimum Gaming](http://www.optimum-multigaming.com/) for the report. * Fixed a couple script errors caused by a hasty adjustment in the last update. @@ -167,7 +213,7 @@ ___ * Increased marker circle diameter for saltflats mission to 750 meters. * Moved "DMS_Version" variable assignment to pre-init. * Moved Map Center and Map Radius assignments to post-init. -* Added support for 2 new optional parameters: _onMonitorStart and _onMonitorEnd, run before and after the Mission Monitor checks the mission, respectively, but AFTER "Mission Success State" is checked. +* Added support for 2 new optional parameters: ```_onMonitorStart``` and ```_onMonitorEnd```, run before and after the Mission Monitor checks the mission, respectively, but AFTER "Mission Success State" is checked. * Mines should now be deleted when a mission fails. * Script optimizations for almost all functions using new command(s) introduced in ArmA v1.54, as well as improved technique(s). * "ExileServer_system_garbageCollector_deleteObject" is now used to actually delete items by DMS_fnc_CleanUp. @@ -196,7 +242,7 @@ ___ #### November 14, 2015 (8:30 PM CST-America): * **NEW CONFIG VALUES:** - + DMS_AllowStaticReinforcements DMS_MarkerText_ShowAICount_Static DMS_PredefinedMissionLocations_WEIGHTED @@ -256,7 +302,7 @@ ___ * Fixed fn_CleanUp producing debug logs even with debug disabled. * Fixed the CleanUp list not Cleaning Up after itself (hah!). * Added diag_tickTime and DMS_Version to debug logs. -* You can now define a custom function for DMS_FillCrate. It will be passed params from _lootValues select 0. **I haven't tested this at all. Just keep that in mind ;)** +* You can now define a custom function for DMS_FillCrate. It will be passed params from ```_lootValues select 0```. **I haven't tested this at all. Just keep that in mind ;)** * You can now manually define mission spawning locations into an array, and that array will be used to find a location. Each location will still be checked for validity, and if no valid positions are found from the list, a random one is then generated using the normal method. **I didn't test this part at all either :P** * fn_FindSafePos should be even more efficient now, and even more controllable. * Quite a few new functions; most notably: fn_GroupReinforcementsManager