Release Candidate

This commit is contained in:
eraser1 2016-01-06 18:38:55 -06:00
parent 3a812885d8
commit c13d751047
26 changed files with 477 additions and 246 deletions

4
.gitignore vendored
View File

@ -41,3 +41,7 @@ $RECYCLE.BIN/
Network Trash Folder
Temporary Items
.apdisk
# Private files/missions
@ExileServer/addons/a3_dms/missions/static/sectorB.sqf

View File

@ -65,6 +65,7 @@ class CfgFunctions
class SelectOffsetPos {};
class SetAILocality {};
class SetGroupBehavior {};
class SetGroupBehavior_Separate {};
class SpawnAIGroup {};
class SpawnAIGroup_MultiPos {};
class SpawnAIVehicle {};

View File

@ -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.
@ -141,10 +145,10 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
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.
@ -200,17 +204,37 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
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
// 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
@ -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
@ -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],

View File

@ -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;
};
@ -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;

View File

@ -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/

View File

@ -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
],
[

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -44,6 +44,8 @@ if !(_message isEqualType "") then
_message = str _message;
};
if (_message isEqualTo "") exitWith {};
{
private "_args";
@ -51,14 +53,11 @@ if !(_message isEqualType "") then
{
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":
{
[
_x,
[
format
[
"<t color='%1' size='%2' font='%3'>%4</t><br/><t color='%5' size='%6' font='%7'>%8</t>",
@ -70,10 +69,7 @@ if !(_message isEqualType "") then
DMS_standardHint_Message_Size,
DMS_standardHint_Message_Font,
_message
]
],
"-1"
] call ExileServer_system_network_send_broadcast;
] remoteExecCall ["DMS_CLIENT_fnc_hintSilent",-2];
};
case "dynamictextrequest":

View File

@ -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))];
};
};
};

View File

@ -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,14 +515,33 @@ 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...

View File

@ -117,13 +117,13 @@ else
{
// 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");
};

View File

@ -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];

View File

@ -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,12 +183,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 _onFailScripts;
[_missionName,_msgLose] call DMS_fnc_BroadcastMissionStatus;
@ -198,6 +200,19 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build
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"];

View File

@ -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;
@ -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,12 +186,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 _onFailScripts;
[_missionName,_msgLose] call DMS_fnc_BroadcastMissionStatus;
@ -203,6 +204,19 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati
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"];

View File

@ -23,10 +23,10 @@ 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;
@ -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;
};
};
}

View File

@ -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,10 +67,12 @@ 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
{
@ -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
{

View File

@ -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;

View File

@ -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
@ -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,9 +59,33 @@ _group setCombatMode "RED";
_group setBehaviour _behavior;
if (_difficulty == "random") then
_difficulty =
switch (toLower _difficulty) do
{
_difficulty = DMS_ai_skill_random call BIS_fnc_selectRandom;
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];

View File

@ -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

View File

@ -60,11 +60,36 @@ else
};
};
if(_difficulty == "random") then
_difficulty =
switch (toLower _difficulty) do
{
_difficulty = DMS_ai_skill_random call BIS_fnc_selectRandom;
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"];
_unit allowFleeing 0;
@ -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
{
@ -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)

View File

@ -18,7 +18,7 @@
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

View File

@ -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];

View File

@ -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!";
@ -28,10 +23,6 @@ _killed = false;
try
{
{
if (_x isEqualType objNull) then
{
if (!isNull _x && {alive _x}) then
{
private ["_lastDistanceCheckTime", "_spawnPos"];
@ -42,42 +33,14 @@ try
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"];
diag_log format ["Killed a runaway unit! |%1| was more than %2m away from its spawn position %3!",_x,DMS_MaxAIDistance,_spawnPos];
}
else
{
_x setVariable ["DMS_LastAIDistanceCheck",time];
throw _x;
};
};
}
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);
};
} 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;
}

View File

@ -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.
@ -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