eraser1 2017-02-23 18:50:14 -06:00
parent 92d32436e0
commit c6c4db9e02
18 changed files with 401 additions and 235 deletions

View File

@ -4,8 +4,8 @@ class CfgPatches
{
units[] = {};
weapons[] = {};
a3_DMS_version = "September 5, 2016";
requiredVersion = 1.36;
a3_DMS_version = "February 23, 2017";
requiredVersion = 1.66;
requiredAddons[] = {"exile_client","exile_server_config"};
};
};

View File

@ -55,9 +55,10 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
DMS_MaxBanditMissions = 3; // Maximum number of Bandit Missions running at the same time
DMS_TimeToFirstMission = [180,420]; // [Minimum,Maximum] time between first mission spawn. | DEFAULT: 3-7 minutes.
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_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.
DMS_ResetMissionTimeoutOnKill = true; // Whether or not to reset the mission timeout when an AI is killed.
/*General settings for dynamic missions*/
/*General settings for static missions*/
@ -68,6 +69,7 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
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_ResetStaticMissionTimeoutOnKill = true; // Whether or not to reset the mission timeout when an AI is killed (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.
@ -267,12 +269,16 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
DMS_StaticMissionTypes = [ // List of STATIC missions with spawn chances.
//["saltflats",1] //<--Example (already imported by default on Altis in map configs)
//["slums",1] //<--Example (already imported by default on Altis in map configs)
//["saltflats",1] //<--Example (already imported by default on Altis in map configs)
//["slums",1] //<--Example (already imported by default on Altis in map configs)
//["occupation",1] //<--Example
//["sectorB",1] //<--Example for Taviana
];
DMS_SpecialMissions = [ // List of special missions with restrictions. Each element must be defined as [mission<STRING>, minPlayers<SCALAR>, maxPlayers<SCALAR>, timesPerRestart<SCALAR>, _timeBetween<SCALAR>].
//["specops",15,60,2,900] //<-- Example for a mission named "specops.sqf" that must be placed in the "special" folder. It will only spawn when there are at least 15 players, less than 60 players, it will only spawn up to twice per restart, and at least 900 seconds must pass before another instance of the mission can spawn.
];
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)
@ -301,7 +307,24 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
/* AI Settings */
DMS_AI_Classname = "O_recon_F"; // Since some of you wanted this...
DMS_AI_UseRealNames = true; // true if you want Arma assigned real names, false if you want random DMS assigned unit numbers
DMS_AI_NamingType = 0; // This specifies the "naming scheme" for the AI. 0 corresponds with the default ArmA names; 1 means you want a DMS name (eg: [DMS BANDIT SOLDIER 123]); 2 means you want to generate a name from a list of first and last names (DMS_AI_FirstNames, DMS_AI_LastNames).
DMS_AI_FirstNames = [ // List of "first names" that an AI can have. Only used when DMS_AI_NamingType = 2.
"Adam",
"Benjamin",
"Charles",
"David",
"Eric"
// etc.
];
DMS_AI_LastNames = [ // List of "last names" that an AI can have. Only used when DMS_AI_NamingType = 2.
"Smith",
"Johnson",
"Williams",
"Jones",
"Brown"
// etc.
];
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)
@ -411,7 +434,7 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
DMS_AIDistanceCheckFrequency = 60; // How often to check within DMS_fnc_TargetsKilled whether or not the AI is out of the maximum radius. Lower values increase frequency and increase server load, greater values decrease frequency and may cause longer delays for "runaway" AI.
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_Only_DMS_AI = true; // Don't set this to false unless you know what you're doing.
DMS_ai_offload_notifyClient = false; // Notify the client when AI has been offloaded to the client.
DMS_ai_allowFreezing = true; // Whether or not to "freeze" AI that are a certain distance away from players (and therefore inactive).
@ -1268,3 +1291,6 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
//"Exile_Car_Offroad_Armed_Guerilla01"
] + DMS_MilitaryVehicles + DMS_TransportTrucks;
/* Loot Settings */
DMS_ConfigLoaded = true;

View File

@ -14,7 +14,7 @@ if !(isServer) exitWith
if (isNil "DMS_DynamicMission") exitWith
if (isNil "DMS_ConfigLoaded") exitWith
{
for "_i" from 0 to 99 do
{

View File

@ -1,6 +1,6 @@
/*
DMS Pre-init
Written by eraser1 (trainwreckdayz.com)
Created by eraser1
*/
#define CALLFILE(FILE) call compile preprocessFileLineNumbers FILE;
@ -20,6 +20,16 @@ DMS_Version = getText (configFile >> "CfgPatches" >> "a3_dms" >> "a3_DMS_version
//Load main config
CALLFILE("\x\addons\dms\config.sqf");
// Let's be honest - you know it's gonna happen.
if (isNil "DMS_AI_NamingType") then
{
for "_i" from 0 to 99 do
{
diag_log format["!!!!!!!!MAKE SURE YOUR DMS CONFIG IS UPDATED!!!!!"];
};
DMS_ConfigLoaded = nil;
};
//Load map-specific configs. Should make it easier for people with multiple servers/maps. One PBO to rule them all...
if (DMS_Use_Map_Config) then
@ -120,3 +130,17 @@ DMS_CLIENT_fnc_hintSilent = compileFinal "hintSilent parsetext format['%1',_this
// Initialize mission variables...
CALLFILE("\x\addons\dms\missions\static_init.sqf");
CALLFILE("\x\addons\dms\missions\mission_init.sqf");
{
private _mission = _x select 0;
missionNamespace setVariable
[
format["DMS_SpecialMission_%1",_mission],
compileFinal preprocessFileLineNumbers (format ["\x\addons\DMS\missions\special\%1.sqf",_mission])
];
missionNamespace setVariable [format["DMS_SpecialMissionSpawnCount_%1",_mission], 0];
missionNamespace setVariable [format["DMS_SpecialMissionLastSpawn_%1",_mission], 0];
} forEach DMS_SpecialMissions;

View File

@ -173,8 +173,9 @@ _PossibleVehicleClass =
_VehicleClass = selectRandom _PossibleVehicleClass;
//DMS_fnc_SpawnPersistentVehicle will automatically turn the pincode into a string and format it.
_pinCode = round (random 9999);
// DMS_fnc_SpawnPersistentVehicle will automatically turn the pincode into a string and format it.
// Generate a pincode greater than 1000 because we shouldn't waste time having to format it in the mission messages.
_pinCode = 1000 + round (random 8999);
_vehicle = [_VehicleClass, _pos getPos [30, random 360], _pinCode] call DMS_fnc_SpawnPersistentVehicle;

View File

@ -173,7 +173,7 @@ _VehicleClass = selectRandom _PossibleVehicleClass;
//DMS_fnc_SpawnPersistentVehicle will automatically turn the pincode into a string and format it.
_pinCode = round (random 9999);
_pinCode = 1000 + round (random 8999);
_vehicle = [_VehicleClass,[(_pos select 0) -30, (_pos select 1) -30],_pinCode] call DMS_fnc_SpawnPersistentVehicle;

View File

@ -82,7 +82,7 @@ _class =
};
//DMS_fnc_SpawnPersistentVehicle will automatically turn the pincode into a string and format it.
_pinCode = round (random 9999);
_pinCode = 1000 + round (random 8999);
_vehicle = [_class,_pos,_pinCode] call DMS_fnc_SpawnPersistentVehicle;

View File

@ -23,9 +23,7 @@ if (DMS_DEBUG) then
// Set mission frequencies from config
DMS_BanditMissionTypesArray = [];
{
private "_missionName";
_missionName = _x select 0;
private _missionName = _x select 0;
for "_i" from 1 to (_x select 1) do
{

View File

@ -22,9 +22,7 @@ if (DMS_DEBUG) then
// Set mission frequencies from config
DMS_StaticMissionTypesArray = [];
{
private "_missionName";
_missionName = _x select 0;
private _missionName = _x select 0;
for "_i" from 1 to (_x select 1) do
{

View File

@ -156,6 +156,8 @@ try
throw format["_onEndingScripts |%1|",_onEndingScripts];
};
private _unitCount = count (_units call DMS_fnc_GetAllUnits);
private _arr =
[
_pos,
@ -185,7 +187,8 @@ try
_onFailScripts,
_onMonitorStart,
_onMonitorEnd
]
],
_unitCount
];
DMS_Mission_Arr pushBack _arr;
_added = true;
@ -193,7 +196,7 @@ try
if (DMS_MarkerText_ShowAICount) then
{
private _markerDot = _markers select 0;
_markerDot setMarkerText (format ["%1 (%2 %3 remaining)",markerText _markerDot,count _units,DMS_MarkerText_AIName]);
_markerDot setMarkerText (format ["%1 (%2 %3 remaining)",markerText _markerDot,_unitCount,DMS_MarkerText_AIName]);
};
if (DMS_DEBUG) then

View File

@ -158,6 +158,8 @@ try
throw format["_onEndingScripts |%1|",_onEndingScripts];
};
private _unitCount = count (_units call DMS_fnc_GetAllUnits);
private _arr =
[
_pos,
@ -188,7 +190,8 @@ try
_onFailScripts,
_onMonitorStart,
_onMonitorEnd
]
],
_unitCount
];
DMS_StaticMission_Arr pushBack _arr;
_added = true;
@ -196,7 +199,7 @@ try
if (DMS_MarkerText_ShowAICount_Static) then
{
private _markerDot = _markers select 0;
_markerDot setMarkerText (format ["%1 (%2 %3 remaining)",markerText _markerDot,count (_units call DMS_fnc_GetAllUnits),DMS_MarkerText_AIName]);
_markerDot setMarkerText (format ["%1 (%2 %3 remaining)",markerText _markerDot,_unitCount,DMS_MarkerText_AIName]);
};
if (DMS_DEBUG) then

View File

@ -54,6 +54,7 @@ private _objs = _export apply
_object setPosATL (_center vectorAdd (_x select 1));
_object enableSimulationGlobal ((_x select 3) select 0);
_object allowDamage ((_x select 3) select 1);
_object;
};

View File

@ -28,7 +28,8 @@
_onFailScripts,
_onMonitorStart,
_onMonitorEnd
]
],
_prevAICount
]
A semi-full breakdown can be found in fn_AddMissionToMonitor.sqf
@ -47,7 +48,9 @@
"_missionSide",
"_missionDifficulty",
"_missionEvents",
"_missionScripts"
"_missionScripts",
"_prevAICount",
"_isSpecial"
])
then
{
@ -134,10 +137,6 @@
if (_missionSide == "bandit") then
{
DMS_RunningBMissionCount = DMS_RunningBMissionCount - 1;
}
else
{
// Not yet implemented
};
{
@ -195,71 +194,91 @@
throw format ["Mission (%1) Success at %2 with message %3.",_missionName,_pos,_msgWIN];
};
if ((diag_tickTime-_timeStarted)>_failTime) then
private _timeElapsed = diag_tickTime - _timeStarted;
if (DMS_ResetMissionTimeoutOnKill) 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,_failTime]];
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
private _cleanupList = ((_units call DMS_fnc_GetAllUnits)+_buildings+_vehs+_mines);
{
_cleanupList pushBack (_x select 0);
} forEach _crate_info_array;
private _prev = DMS_CleanUp_PlayerNearLimit;
DMS_CleanUp_PlayerNearLimit = 0; // Temporarily set the limit to 0 since we want to delete all the stuff regardless of player presence.
_cleanupList call DMS_fnc_CleanUp;
DMS_CleanUp_PlayerNearLimit = _prev;
if (_missionSide == "bandit") then
{
DMS_RunningBMissionCount = DMS_RunningBMissionCount - 1;
}
else
{
// Not yet implemented
};
{
_params = _x select 0;
_code = _x select 1;
if (_code isEqualType "") then
{
_code = compile _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
private _AICount = count (_units call DMS_fnc_GetAllUnits);
if (_AICount != _prevAICount) then
{
_x set [2,[diag_tickTime,_failTime]];
_x set [11, _AICount];
_timeElapsed = 0;
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;
format["MissionsMonitor_Dynamic :: Mission Timeout Extended to %1 more seconds; AI count changed from %2 to %3. Position: %4, MissionIndex: %5",_failTime, _prevAICount, _AICount,_pos,_forEachIndex] call DMS_fnc_DebugLog;
};
};
};
switch (true) do
{
case (_timeElapsed > DMS_MissionTimeoutResetFrequency):
{
if ([_pos,DMS_MissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby) then
{
_x set [2,[diag_tickTime,_failTime]];
if (DMS_DEBUG) then
{
format["MissionsMonitor_Dynamic :: Mission Timeout Extended to %1 more seconds; player found within %2 meters. Position: %3, MissionIndex: %4",_failTime,DMS_MissionTimeoutResetRange,_pos,_forEachIndex] call DMS_fnc_DebugLog;
};
};
};
case (_timeElapsed > _failTime):
{
// Check to see if the timeout should be extended before ending the mission.
if ([_pos,DMS_MissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby) then
{
_x set [2,[diag_tickTime,_failTime]];
throw format["Mission Timeout Extended to %1 more seconds; player found within %2 meters. Position: %3, MissionIndex: %4",_failTime,DMS_MissionTimeoutResetRange,_pos,_forEachIndex] call DMS_fnc_DebugLog;
};
//Nobody is nearby so just cleanup objects from here
private _cleanupList = ((_units call DMS_fnc_GetAllUnits)+_buildings+_vehs+_mines);
{
_cleanupList pushBack (_x select 0);
} forEach _crate_info_array;
private _prev = DMS_CleanUp_PlayerNearLimit;
DMS_CleanUp_PlayerNearLimit = 0; // Temporarily set the limit to 0 since we want to delete all the stuff regardless of player presence.
_cleanupList call DMS_fnc_CleanUp;
DMS_CleanUp_PlayerNearLimit = _prev;
if (_missionSide == "bandit") then
{
DMS_RunningBMissionCount = DMS_RunningBMissionCount - 1;
};
{
_params = _x select 0;
_code = _x select 1;
if (_code isEqualType "") then
{
_code = compile _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 (DMS_MarkerText_ShowAICount) then
{
private _dot = _markers select 0;
@ -273,14 +292,6 @@
_dot setMarkerText (format ["%1 (%2 %3 remaining)",_text,count (_units call DMS_fnc_GetAllUnits),DMS_MarkerText_AIName]);
};
/*
Coming soon...
{
_x call DMS_fnc_HandleMissionEvents;
} forEach _missionEvents;
*/
if !(_onMonitorEnd isEqualTo {}) then
{

View File

@ -34,7 +34,8 @@
_onFailScripts,
_onMonitorStart,
_onMonitorEnd
]
],
_prevAICount
]
A semi-full breakdown can be found in fn_AddStaticMissionToMonitor.sqf
@ -54,7 +55,8 @@
"_missionSide",
"_missionDifficulty",
"_missionEvents",
"_missionScripts"
"_missionScripts",
"_prevAICount"
])
then
{
@ -194,63 +196,87 @@
throw format ["Mission (%1) Success at %2 with message %3.",_missionName,_missionPos,_msgWIN];
};
if ((diag_tickTime-_timeStarted)>_failTime) then
private _timeElapsed = diag_tickTime - _timeStarted;
if (DMS_ResetStaticMissionTimeoutOnKill) 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 [3,[diag_tickTime,_failTime]];
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
_cleanupList = ((_inputAIUnits call DMS_fnc_GetAllUnits)+_buildings+_vehs+_mines);
{
_cleanupList pushBack (_x select 0);
} forEach _crate_info_array;
private _prev = DMS_CleanUp_PlayerNearLimit;
DMS_CleanUp_PlayerNearLimit = 0; // Temporarily set the limit to 0 since we want to delete all the stuff regardless of player presence.
_cleanupList call DMS_fnc_CleanUp;
DMS_CleanUp_PlayerNearLimit = _prev;
{
_params = _x select 0;
_code = _x select 1;
if (_code isEqualType "") then
{
_code = compile _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
private _AICount = count (_inputAIUnits call DMS_fnc_GetAllUnits);
if (_AICount != _prevAICount) then
{
_x set [3,[diag_tickTime,_failTime]];
_x set [12, _AICount];
_timeElapsed = 0;
if (DMS_DEBUG) then
{
format["Static Mission Timeout Extended at %1 with timeout after %2 seconds. Position: %3",diag_tickTime,_failTime,_missionPos] call DMS_fnc_DebugLog;
format["MissionsMonitor_Static :: Static Mission Timeout Extended to %1 more seconds; AI count changed from %2 to %3. Position: %4, MissionIndex: %5",_failTime, _prevAICount, _AICount,_pos,_forEachIndex] call DMS_fnc_DebugLog;
};
};
};
switch (true) do
{
case (_timeElapsed > DMS_SMissionTimeoutResetFrequency):
{
if ([_missionPos,DMS_StaticMissionTimeoutResetRange] call DMS_fnc_IsPlayerNearby) then
{
_x set [3,[diag_tickTime,_failTime]];
if (DMS_DEBUG) then
{
format["MissionsMonitor_Static :: Static Mission Timeout Extended to %1 more seconds; player found within %2 meters. Position: %3, MissionIndex: %4",_failTime,DMS_StaticMissionTimeoutResetRange,_pos,_forEachIndex] call DMS_fnc_DebugLog;
};
};
};
case (_timeElapsed > _failTime):
{
// 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 [3,[diag_tickTime,_failTime]];
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
_cleanupList = ((_inputAIUnits call DMS_fnc_GetAllUnits)+_buildings+_vehs+_mines);
{
_cleanupList pushBack (_x select 0);
} forEach _crate_info_array;
private _prev = DMS_CleanUp_PlayerNearLimit;
DMS_CleanUp_PlayerNearLimit = 0; // Temporarily set the limit to 0 since we want to delete all the stuff regardless of player presence.
_cleanupList call DMS_fnc_CleanUp;
DMS_CleanUp_PlayerNearLimit = _prev;
{
_params = _x select 0;
_code = _x select 1;
if (_code isEqualType "") then
{
_code = compile _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 (DMS_MarkerText_ShowAICount_Static) then
{
private _dot = _markers select 0;
@ -264,14 +290,6 @@
_dot setMarkerText (format ["%1 (%2 %3 remaining)",_text,count (_inputAIUnits call DMS_fnc_GetAllUnits),DMS_MarkerText_AIName]);
};
/*
Coming soon...
{
_x call DMS_fnc_HandleMissionEvents;
} forEach _missionEvents;
*/
if (DMS_AllowStaticReinforcements) then
{

View File

@ -5,13 +5,10 @@
Usage:
[
[
_killedUnit,
_killer
],
_side, // "bandit" only for now
_type // Type of AI: "soldier","static","vehicle","heli", etc.
_killedUnit,
_killer
] call DMS_fnc_OnKilled;
***Designed for use with the ArmA "MPKilled" EH. This function should not be explicitly called otherwise.***
*/
if (DMS_DEBUG) then
{

View File

@ -68,4 +68,51 @@ if (diag_fps >= DMS_MinServerFPS && {_playerCount >= DMS_MinPlayerCount}) then
(format ["SelectMission :: Spawning of static mission ""%1"" complete!", _mission]) call DMS_fnc_DebugLog;
};
};
{
_x params
[
"_mission",
"_minPlayers",
"_maxPlayers",
"_maxTimesPerRestart",
"_timeBetween"
];
private _timesPerRestart = missionNamespace getVariable format["DMS_SpecialMissionSpawnCount_%1",_mission];
if
(
(_playerCount > _minPlayers) &&
{_playerCount < _maxPlayers} &&
{_maxTimesPerRestart < _timesPerRestart} &&
{(_time - (missionNamespace getVariable format["DMS_SpecialMissionLastSpawn_%1",_mission])) > _timeBetween}
) then
{
private _missionCode = missionNamespace getVariable format
[
"DMS_SpecialMission_%1",
"no"
];
if (_missionCode isEqualTo "no") then
{
diag_log format ["DMS ERROR :: Attempting to spawn a special mission that isn't precompiled! Parameters: %1", DMS_SpecialMissions deleteAt _forEachIndex];
}
else
{
missionNamespace setVariable [format["DMS_SpecialMissionSpawnCount_%1",_mission], _timesPerRestart+1];
call _missionCode;
missionNamespace setVariable [format["DMS_SpecialMissionLastSpawn_%1",_mission], _time];
if (DMS_DEBUG) then
{
(format ["SelectMission :: Spawned special mission %1. DMS_SpawnedSpecialMissions: %2", _mission, DMS_SpawnedSpecialMissions]) call DMS_fnc_DebugLog;
};
};
};
} forEach DMS_SpecialMissions;
};

View File

@ -8,7 +8,7 @@
_pos, // ARRAY (positionATL): Position of AI
_count, // SCALAR: Number of AI
_difficulty, // STRING: AI Difficulty: "random","hardcore","difficult","moderate", or "easy"
_class, // STRING: AI Class: "random","assault","MG","sniper" or "unarmed" OR [_class,_launcherType]
_class, // STRING: AI Class: "random","assault","MG", or "sniper" OR [_class,_launcherType]
_side, // STRING: Only "bandit" is supported by default
_customGearSet // (OPTIONAL) ARRAY: Manually defined AI gear. Refer to functional documentation of fn_SpawnAISoldier.sqf for more info: https://github.com/Defent/DMS_Exile/blob/master/%40ExileServer/addons/a3_dms/scripts/fn_SpawnAISoldier.sqf
] call DMS_fnc_SpawnAIGroup;
@ -30,13 +30,6 @@ exitWith
grpNull
};
if (_count < 1) exitWith
{
diag_log format ["DMS ERROR :: Calling DMS_SpawnAIGroup with less than 1 _count! _this: %1",_this];
grpNull
};
if (DMS_DEBUG) then
{
(format["SpawnAIGroup :: Spawning %1 %2 %3 AI at %4 with %5 difficulty.",_count,_class,_side,_pos,_difficulty]) call DMS_fnc_DebugLog;

View File

@ -7,7 +7,7 @@
[
_group, // GROUP: Group the AI will belong to
_pos, // ARRAY (positionATL): Position of AI
_class, // STRING: Classname: "random","assault","MG","sniper" or "unarmed". Use "custom" to use "_customGearSet"
_class, // STRING: Classname: "random","assault","MG", or "sniper". Use "custom" to use "_customGearSet"
_difficulty, // STRING: Difficulty: "random","static","hardcore","difficult","moderate", or "easy"
_side, // STRING: "bandit" only by default
_type, // STRING: Type of AI: "soldier","static","vehicle","heli", etc.
@ -29,11 +29,12 @@
_backpack // String | EG: "B_Carryall_oli"
]
Returns AI Unit
Returns AI Object
*/
// Enabling this ensures that any optic/bipod/accessory that isn't compatible with a weapon cannot be selected. (Doesn't apply to custom gear sets)
#define USE_EXTRA_CHECKING 1
private _customGearSet = [];
private _unarmed = false;
if !(params
[
@ -114,34 +115,36 @@ removeBackpackGlobal _unit;
} forEach DMS_ai_default_items;
if (_class == "unarmed") then
if (_class in DMS_ai_SupportedRandomClasses) then
{
_class = "assault";
_unarmed = true;
}
else
{
if (_class in DMS_ai_SupportedRandomClasses) then
{
_class = selectRandom (missionNamespace getVariable [format["DMS_%1_AI",_class], DMS_random_AI]);
};
_class = selectRandom (missionNamespace getVariable [format["DMS_%1_AI",_class], DMS_random_AI]);
};
// Set random DMS unit names if you don't want Arma assigned (real names)
if !(DMS_AI_UseRealNames) then
switch (DMS_AI_NamingType) do
{
_unit setName format["[DMS %1 %2 %3]",toUpper _side,_class,floor(random 1000)];
case 1:
{
_unit setName format["[DMS %1 %2 %3]",toUpper _side,_class,floor(random 1000)];
};
case 2:
{
_unit setName format["%1 %2", selectRandom DMS_AI_FirstNames, selectRandom DMS_AI_LastNames];
};
default {}; // Default ArmA names otherwise...
};
if !(_class in DMS_ai_SupportedClasses) exitWith
{
diag_log format ["DMS ERROR :: DMS_SpawnAISoldier called with unsupported _class: %1 | _this: %2",_class,_this];
deleteVehicle _unit;
};
if (_customGearSet isEqualTo []) then
{
if !(_class in DMS_ai_SupportedClasses) exitWith
{
diag_log format ["DMS ERROR :: DMS_SpawnAISoldier called with unsupported _class: %1 | _this: %2",_class,_this];
deleteVehicle _unit;
};
// Equipment (Stuff that goes in the toolbelt slots)
{
if (_x in ["Binocular","Rangefinder","Laserdesignator","Laserdesignator_02","Laserdesignator_03"]) then
@ -184,61 +187,104 @@ if (_customGearSet isEqualTo []) then
_unit linkItem "NVGoggles";
};
if (!_unarmed) then
private _weapon = selectRandom (missionNamespace getVariable [format ["DMS_%1_weps",_class],DMS_assault_weps]);
[_unit, _weapon, 6 + floor(random 3)] call DMS_fnc_AddWeapon;
_unit selectWeapon _weapon;
#ifdef USE_EXTRA_CHECKING
// "Guaranteed" method of finding/adding weapon attachments.
if ((random 100) <= (missionNamespace getVariable [format["DMS_%1_optic_chance",_class],0])) then
{
private _weapon = selectRandom (missionNamespace getVariable [format ["DMS_%1_weps",_class],DMS_assault_weps]);
[_unit, _weapon, 6 + floor(random 3)] call DMS_fnc_AddWeapon;
_unit selectWeapon _weapon;
private _optic = selectRandom
(
(missionNamespace getVariable [format ["DMS_%1_optics",_class],DMS_assault_optics]) arrayIntersect
(getArray (configfile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "CowsSlot"))
);
if((random 100) <= (missionNamespace getVariable [format["DMS_%1_optic_chance",_class],0])) then
if !(isNil "_optic") then
{
_unit addPrimaryWeaponItem (selectRandom (missionNamespace getVariable [format ["DMS_%1_optics",_class],DMS_assault_optics]));
_unit addPrimaryWeaponItem _optic;
};
if (_nighttime && {(random 100) <= DMS_ai_nighttime_accessory_chance}) then
{
_unit addPrimaryWeaponItem (selectRandom ["acc_pointer_IR","acc_flashlight"]);
};
if((random 100) <= (missionNamespace getVariable [format["DMS_%1_bipod_chance",_class],0])) then
{
_unit addPrimaryWeaponItem (selectRandom DMS_ai_BipodList);
};
if((random 100) <= (missionNamespace getVariable [format["DMS_%1_suppressor_chance",_class],0])) then
{
private _suppressor = _weapon call DMS_fnc_FindSuppressor;
if (_suppressor != "") then
{
_unit addPrimaryWeaponItem _suppressor;
};
};
/*
// In case spawn position is water
if (DMS_ai_enable_water_equipment && {surfaceIsWater _pos}) then
{
removeHeadgear _unit;
removeAllWeapons _unit;
_unit forceAddUniform "U_O_Wetsuit";
_unit addVest "V_RebreatherIA";
_unit addGoggles "G_Diving";
[_unit, "arifle_SDAR_F", 4 + floor(random 3), "20Rnd_556x45_UW_mag"] call DMS_fnc_AddWeapon;
};
*/
private _pistols = missionNamespace getVariable [format ["DMS_%1_pistols",_class],[]];
if !(_pistols isEqualTo []) then
{
private _pistol = selectRandom _pistols;
[_unit, _pistol, 2 + floor(random 2)] call DMS_fnc_AddWeapon;
};
// Infinite Ammo
// This will NOT work if AI unit is offloaded to client
_unit addeventhandler ["Fired", {(vehicle (_this select 0)) setvehicleammo 1;}];
};
if (_nighttime && {(random 100) <= DMS_ai_nighttime_accessory_chance}) then
{
private _accessory = selectRandom (getArray (configfile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "PointerSlot"));
if !(isNil "_accessory") then
{
_unit addPrimaryWeaponItem _accessory;
};
};
if ((random 100) <= (missionNamespace getVariable [format["DMS_%1_bipod_chance",_class],0])) then
{
private _bipod = selectRandom
(
DMS_AI_BipodList arrayIntersect
(getArray (configfile >> "CfgWeapons" >> _weapon >> "WeaponSlotsInfo" >> "UnderBarrelSlot"))
);
if !(isNil "_bipod") then
{
_unit addPrimaryWeaponItem _bipod;
};
};
#else
// "Regular" method of finding/adding weapon attachments.
if ((random 100) <= (missionNamespace getVariable [format["DMS_%1_optic_chance",_class],0])) then
{
_unit addPrimaryWeaponItem (selectRandom (missionNamespace getVariable [format ["DMS_%1_optics",_class],DMS_assault_optics]));
};
if (_nighttime && {(random 100) <= DMS_ai_nighttime_accessory_chance}) then
{
_unit addPrimaryWeaponItem (selectRandom ["acc_pointer_IR","acc_flashlight"]);
};
if ((random 100) <= (missionNamespace getVariable [format["DMS_%1_bipod_chance",_class],0])) then
{
_unit addPrimaryWeaponItem (selectRandom DMS_AI_BipodList);
};
#endif
if ((random 100) <= (missionNamespace getVariable [format["DMS_%1_suppressor_chance",_class],0])) then
{
private _suppressor = _weapon call DMS_fnc_FindSuppressor;
if (_suppressor != "") then
{
_unit addPrimaryWeaponItem _suppressor;
};
};
/*
// In case spawn position is water
if (DMS_ai_enable_water_equipment && {surfaceIsWater _pos}) then
{
removeHeadgear _unit;
removeAllWeapons _unit;
_unit forceAddUniform "U_O_Wetsuit";
_unit addVest "V_RebreatherIA";
_unit addGoggles "G_Diving";
[_unit, "arifle_SDAR_F", 4 + floor(random 3), "20Rnd_556x45_UW_mag"] call DMS_fnc_AddWeapon;
};
*/
private _pistols = missionNamespace getVariable [format ["DMS_%1_pistols",_class],[]];
if !(_pistols isEqualTo []) then
{
private _pistol = selectRandom _pistols;
[_unit, _pistol, 2 + floor(random 2)] call DMS_fnc_AddWeapon;
};
// Infinite Ammo. This will NOT work if AI unit is offloaded to client.
// Removed because there isn't much need for this.
// _unit addeventhandler ["Fired", {(vehicle (_this select 0)) setvehicleammo 1;}];
}
else
{