More things!

New function "DMS_fnc_ShuffleNewArray" for shuffling an array without modifying the original.

New method of using predefined mission locations. The old method will NO LONGER WORK and must be changed.

Moving a bunch of code to DMS preinit because it doesn't need to be postinit.

You can now specify buildings to enable/disable simulation (allowing you to open/close doors) for the old M3E exports. Existing buildings have been updated.

Clients will log to their RPT if an AI has been offloaded to them, regardless of the setting for notifying clients. The setting will now only dictate whether or not they get a message in chat upon offloading.

A couple fixes from PrimusNZ:
Fixed the special mission spawning logic so that the player count limits set are actually accurate.

Fixed the "runaway AI killer" logic so that it actually kills AI that are far away.
This commit is contained in:
eraser1 2018-03-18 17:09:25 -05:00
parent 6d45755efc
commit 0c087e6403
17 changed files with 169 additions and 139 deletions

View File

@ -76,6 +76,7 @@ class CfgFunctions
class SetGroupBehavior {};
class SetGroupBehavior_Separate {};
class SetRelPositions {};
class ShuffleNewArray {};
class SpawnAIGroup {};
class SpawnAIGroup_MultiPos {};
class SpawnAIVehicle {};

View File

@ -112,20 +112,21 @@ DMS_SpawnMissions_Scheduled = false; // Whether or not to spawn missions in a sc
DMS_UsePredefinedMissionLocations = false; // Whether or not to use a list of pre-defined mission locations instead before attempting to find a random (valid) position. The positions will still be checked for validity. If none of the provided positions are valid, a random one will be generated.
DMS_PredefinedMissionLocations = [ // List of Preset/Predefined mission locations.
/* List of positions:
position1: [x_1,y_1,z_1],
position2: [x_2,y_2,z_2],
"x" and "y" are the center to a position on the map, and "r" is a radius about the center.
position1: [[x_1,y_1],r_1],
position2: [[x_2,y_2],r_2],
...
positionN: [x_N,y_N,z_N]
positionN: [[x_N,y_N],r_N]
*/
];
DMS_PredefinedMissionLocations_WEIGHTED = [ // List of Preset/Predefined mission locations WITH WEIGHTED CHANCES. This will NOT override "DMS_PredefinedMissionLocations", and everything from "DMS_PredefinedMissionLocations" will behave as though it has 1 weight per position.
/* List of arrays with position and weighted chance:
[[x_1,y_1,z_1], chance_1],
[[x_2,y_2,z_2], chance_2],
[[[x_1,y_1],r_1], weight_1],
[[[x_2,y_2],r_2], weight_2],
...
[[x_N,y_N,z_N], chance_N]
[[[x_N,y_N],r_N], weight_N]
*/
];

View File

@ -81,51 +81,6 @@ WEST setFriend[RESISTANCE,0];
if ((!isNil "A3XAI_isActive") && {!DMS_ai_offload_Only_DMS_AI}) then
{
diag_log 'DMS DETECTED A3XAI. Enabling "DMS_ai_offload_Only_DMS_AI"!';
DMS_ai_offload_Only_DMS_AI = true;
};
if ((isClass (configFile >> "CfgPatches" >> "Ryanzombies")) && {!DMS_ai_offload_Only_DMS_AI}) then
{
diag_log 'DMS DETECTED RyanZombies. Enabling "DMS_ai_offload_Only_DMS_AI"!';
DMS_ai_offload_Only_DMS_AI = true;
};
if !(DMS_ai_offload_to_client) then
{
DMS_ai_offloadOnUnfreeze = false;
};
if !(DMS_ai_allowFreezing) then
{
DMS_ai_freezeOnSpawn = false;
};
DMS_A3_AllMarkerColors = [];
for "_i" from 0 to ((count(configfile >> "CfgMarkerColors"))-1) do
{
DMS_A3_AllMarkerColors pushBack (toLower (configName ((configfile >> "CfgMarkerColors") select _i)));
};
if !((toLower DMS_MissionMarkerWinDotColor) in DMS_A3_AllMarkerColors) then
{
diag_log format ["DMS ERROR :: Unsupported color for DMS_MissionMarkerWinDotColor (""%1""). Switching color to ""ColorBlue"".",DMS_MissionMarkerWinDotColor];
DMS_MissionMarkerWinDotColor = "ColorBlue";
};
if !((toLower DMS_MissionMarkerLoseDotColor) in DMS_A3_AllMarkerColors) then
{
diag_log format ["DMS ERROR :: Unsupported color for DMS_MissionMarkerLoseDotColor (""%1""). Switching color to ""ColorRed"".",DMS_MissionMarkerLoseDotColor];
DMS_MissionMarkerLoseDotColor = "ColorRed";
};
// Send Client Functions using compileFinal for security.
publicVariable "DMS_CLIENT_fnc_spawnDynamicText";
publicVariable "DMS_CLIENT_fnc_spawnTextTiles";
@ -138,16 +93,6 @@ format["DMS_Version: %1",DMS_Version] remoteExecCall ["diag_log", -2, "DMS_LogVe
// Add the weighted predefined locations to the list of predefined locations
{
for "_i" from 1 to (_x select 1) do
{
DMS_PredefinedMissionLocations pushBack (_x select 0);
};
} forEach DMS_PredefinedMissionLocations_WEIGHTED;
// Set up the minimum/maximum co-ordinate values for x and y...
DMS_MinMax_X_Coords = [DMS_MinDistFromWestBorder, worldSize - DMS_MinDistFromEastBorder];
DMS_MinMax_Y_Coords = [DMS_MinDistFromSouthBorder, worldSize - DMS_MinDistFromNorthBorder];

View File

@ -144,3 +144,62 @@ CALLFILE("\x\addons\dms\missions\mission_init.sqf");
missionNamespace setVariable [format["DMS_SpecialMissionSpawnCount_%1",_mission], 0];
missionNamespace setVariable [format["DMS_SpecialMissionLastSpawn_%1",_mission], 0];
} forEach DMS_SpecialMissions;
if ((!isNil "A3XAI_isActive") && {!DMS_ai_offload_Only_DMS_AI}) then
{
diag_log 'DMS DETECTED A3XAI. Enabling "DMS_ai_offload_Only_DMS_AI"!';
DMS_ai_offload_Only_DMS_AI = true;
};
if ((isClass (configFile >> "CfgPatches" >> "Ryanzombies")) && {!DMS_ai_offload_Only_DMS_AI}) then
{
diag_log 'DMS DETECTED RyanZombies. Enabling "DMS_ai_offload_Only_DMS_AI"!';
DMS_ai_offload_Only_DMS_AI = true;
};
if !(DMS_ai_offload_to_client) then
{
DMS_ai_offloadOnUnfreeze = false;
};
if !(DMS_ai_allowFreezing) then
{
DMS_ai_freezeOnSpawn = false;
};
DMS_A3_AllMarkerColors = [];
for "_i" from 0 to ((count(configfile >> "CfgMarkerColors"))-1) do
{
DMS_A3_AllMarkerColors pushBack (toLower (configName ((configfile >> "CfgMarkerColors") select _i)));
};
if !((toLower DMS_MissionMarkerWinDotColor) in DMS_A3_AllMarkerColors) then
{
diag_log format ["DMS ERROR :: Unsupported color for DMS_MissionMarkerWinDotColor (""%1""). Switching color to ""ColorBlue"".",DMS_MissionMarkerWinDotColor];
DMS_MissionMarkerWinDotColor = "ColorBlue";
};
if !((toLower DMS_MissionMarkerLoseDotColor) in DMS_A3_AllMarkerColors) then
{
diag_log format ["DMS ERROR :: Unsupported color for DMS_MissionMarkerLoseDotColor (""%1""). Switching color to ""ColorRed"".",DMS_MissionMarkerLoseDotColor];
DMS_MissionMarkerLoseDotColor = "ColorRed";
};
// Add the weighted predefined locations to the list of predefined locations
{
for "_i" from 1 to (_x select 1) do
{
DMS_PredefinedMissionLocations pushBack (_x select 0);
};
} forEach DMS_PredefinedMissionLocations_WEIGHTED;
DMS_PredefinedMissionLocations = DMS_PredefinedMissionLocations call DMS_fnc_ShuffleNewArray;

View File

@ -1,14 +1,14 @@
[
["Land_Cargo_House_V2_F",[0,15,0],0],
["Land_Cargo_House_V2_F",[6.2,15,0],0],
["Land_Cargo_House_V2_F",[-6.2,15,0],0],
["Land_Cargo_House_V2_F",[15,0,0],90],
["Land_Cargo_House_V2_F",[15,6.2,0],90],
["Land_Cargo_House_V2_F",[15,-6.2,0],90],
["Land_Cargo_House_V2_F",[0,-15,0],180],
["Land_Cargo_House_V2_F",[-6.2,-15,0],180],
["Land_Cargo_House_V2_F",[6.2,-15,0],180],
["Land_Cargo_House_V2_F",[-15,0,0],270],
["Land_Cargo_House_V2_F",[-15,-6.2,0],270],
["Land_Cargo_House_V2_F",[-15,6.2,0],270]
]
["Land_Cargo_House_V2_F",[0,15,0],0,[],false,true],
["Land_Cargo_House_V2_F",[6.2,15,0],0,[],false,true],
["Land_Cargo_House_V2_F",[-6.2,15,0],0,[],false,true],
["Land_Cargo_House_V2_F",[15,0,0],90,[],false,true],
["Land_Cargo_House_V2_F",[15,6.2,0],90,[],false,true],
["Land_Cargo_House_V2_F",[15,-6.2,0],90,[],false,true],
["Land_Cargo_House_V2_F",[0,-15,0],180,[],false,true],
["Land_Cargo_House_V2_F",[-6.2,-15,0],180,[],false,true],
["Land_Cargo_House_V2_F",[6.2,-15,0],180,[],false,true],
["Land_Cargo_House_V2_F",[-15,0,0],270,[],false,true],
["Land_Cargo_House_V2_F",[-15,-6.2,0],270,[],false,true],
["Land_Cargo_House_V2_F",[-15,6.2,0],270,[],false,true]
]

View File

@ -1,14 +1,14 @@
[
["Land_Cargo_House_V3_F",[0,15,0],0],
["Land_Cargo_House_V3_F",[6.2,15,0],0],
["Land_Cargo_House_V3_F",[-6.2,15,0],0],
["Land_Cargo_House_V3_F",[15,0,0],90],
["Land_Cargo_House_V3_F",[15,6.2,0],90],
["Land_Cargo_House_V3_F",[15,-6.2,0],90],
["Land_Cargo_House_V3_F",[0,-15,0],180],
["Land_Cargo_House_V3_F",[-6.2,-15,0],180],
["Land_Cargo_House_V3_F",[6.2,-15,0],180],
["Land_Cargo_House_V3_F",[-15,0,0],270],
["Land_Cargo_House_V3_F",[-15,-6.2,0],270],
["Land_Cargo_House_V3_F",[-15,6.2,0],270]
]
["Land_Cargo_House_V3_F",[0,15,0],0,[],false,true],
["Land_Cargo_House_V3_F",[6.2,15,0],0,[],false,true],
["Land_Cargo_House_V3_F",[-6.2,15,0],0,[],false,true],
["Land_Cargo_House_V3_F",[15,0,0],90,[],false,true],
["Land_Cargo_House_V3_F",[15,6.2,0],90,[],false,true],
["Land_Cargo_House_V3_F",[15,-6.2,0],90,[],false,true],
["Land_Cargo_House_V3_F",[0,-15,0],180,[],false,true],
["Land_Cargo_House_V3_F",[-6.2,-15,0],180,[],false,true],
["Land_Cargo_House_V3_F",[6.2,-15,0],180,[],false,true],
["Land_Cargo_House_V3_F",[-15,0,0],270,[],false,true],
["Land_Cargo_House_V3_F",[-15,-6.2,0],270,[],false,true],
["Land_Cargo_House_V3_F",[-15,6.2,0],270,[],false,true]
]

View File

@ -1,14 +1,14 @@
[
["Land_Medevac_house_V1_F",[0,15,0],0],
["Land_Medevac_house_V1_F",[6.2,15,0],0],
["Land_Medevac_house_V1_F",[-6.2,15,0],0],
["Land_Medevac_house_V1_F",[15,0,0],90],
["Land_Medevac_house_V1_F",[15,6.2,0],90],
["Land_Medevac_house_V1_F",[15,-6.2,0],90],
["Land_Medevac_house_V1_F",[0,-15,0],180],
["Land_Medevac_house_V1_F",[-6.2,-15,0],180],
["Land_Medevac_house_V1_F",[6.2,-15,0],180],
["Land_Medevac_house_V1_F",[-15,0,0],270],
["Land_Medevac_house_V1_F",[-15,-6.2,0],270],
["Land_Medevac_house_V1_F",[-15,6.2,0],270]
]
["Land_Medevac_house_V1_F",[0,15,0],0,[],false,true],
["Land_Medevac_house_V1_F",[6.2,15,0],0,[],false,true],
["Land_Medevac_house_V1_F",[-6.2,15,0],0,[],false,true],
["Land_Medevac_house_V1_F",[15,0,0],90,[],false,true],
["Land_Medevac_house_V1_F",[15,6.2,0],90,[],false,true],
["Land_Medevac_house_V1_F",[15,-6.2,0],90,[],false,true],
["Land_Medevac_house_V1_F",[0,-15,0],180,[],false,true],
["Land_Medevac_house_V1_F",[-6.2,-15,0],180,[],false,true],
["Land_Medevac_house_V1_F",[6.2,-15,0],180,[],false,true],
["Land_Medevac_house_V1_F",[-15,0,0],270,[],false,true],
["Land_Medevac_house_V1_F",[-15,-6.2,0],270,[],false,true],
["Land_Medevac_house_V1_F",[-15,6.2,0],270,[],false,true]
]

View File

@ -1,7 +1,7 @@
[
["Land_Research_HQ_F",[10,0,0],0],
["Land_Research_HQ_F",[10,0,0],0,[],false,true],
["Land_CncBarrierMedium4_F",[1,7,0],0],
["Land_CncBarrierMedium4_F",[1,-7,0],0],
["Land_CncBarrierMedium4_F",[-3,-4,0],90],
["Land_CncBarrierMedium4_F",[-3,3.5,0],90]
]
]

View File

@ -43,26 +43,15 @@ DMS_DebugMarkers = [];
*/
private _isValidSpot = false;
private _presetLocs = [];
private _presetLocsLength = 0;
if (DMS_UsePredefinedMissionLocations) then
{
// Shuffle the array so that the positions are selected in random order
_presetLocs = DMS_PredefinedMissionLocations call ExileClient_util_array_shuffle;
_presetLocsLength = count _presetLocs;
};
private _pos = [];
for "_attempts" from 1 to MAX_ATTEMPTS do
{
_pos =
if (DMS_UsePredefinedMissionLocations && {_attempts<=_presetLocsLength}) then
if (DMS_UsePredefinedMissionLocations) then
{
_presetLocs select (_attempts - 1)
_posInfo = selectRandom DMS_UsePredefinedMissionLocations;
[_posInfo select 0, random (_posInfo select 1), random 360] call DMS_fnc_SelectOffsetPos
}
else
{

View File

@ -51,12 +51,12 @@ private _objs = _export apply
{
// Create the object
private _obj = createVehicle [_x select 0, [0,0,0], [], 0, "CAN_COLLIDE"];
_obj enableSimulationGlobal false;
_obj enableSimulationGlobal (_x param [5,false,[false]]);
// Calculate the object's position using provided relative position
private _objPos = [_pos,_x select 1] call DMS_fnc_CalcPos;
if (((count _x)>4) && {!(_x select 4)}) then
if (_x param [4,false,[false]]) then
{
// Supports bank/pitch
_obj setPosATL _objPos;

View File

@ -52,7 +52,7 @@ if ((isNil "_export") || {!(_export isEqualType [])}) exitWith
private _objs = _export apply
{
private _obj = createVehicle [_x select 0, [0,0,0], [], 0, "CAN_COLLIDE"];
_obj enableSimulationGlobal false;
_obj enableSimulationGlobal (_x param [5,false,[false]]);
private _pos = (_x select 1) vectorAdd [0,0,5000];

View File

@ -46,8 +46,8 @@ if ((isNil "_export") || {!(_export isEqualType [])}) exitWith
private _objs = _export apply
{
private _obj = createVehicle [_x select 0, [0,0,0], [], 0, "CAN_COLLIDE"];
_obj enableSimulationGlobal false;
_obj enableSimulationGlobal (_x param [5,false,[false]]);
private _pos = _x select 1;
if (_x select 4) then

View File

@ -84,8 +84,8 @@ if (diag_fps >= DMS_MinServerFPS && {_playerCount >= DMS_MinPlayerCount}) then
if
(
(_playerCount > _minPlayers) &&
{_playerCount < _maxPlayers} &&
(_playerCount >= _minPlayers) &&
{_playerCount <= _maxPlayers} &&
{_maxTimesPerRestart > _timesSpawned} &&
{(_time - (missionNamespace getVariable format["DMS_SpecialMissionLastSpawn_%1",_mission])) > _timeBetween}
) then

View File

@ -51,11 +51,11 @@ if (!isNull _client) then
ExileServerOwnershipSwapQueue pushBack [_AI,_client];
};
private _msg = format ["DMS :: AI %1 |%2| has been offloaded to you.",_AIType,_AI];
_msg remoteExecCall ["diag_log", _client];
if (DMS_ai_offload_notifyClient) then
{
private _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

View File

@ -0,0 +1,20 @@
/*
DMS_fnc_ShuffleNewArray
created by eraser1
Usage:
_array call DMS_fnc_ShuffleNewArray
Shuffles an array without modifying the original (input) array.
*/
_this = + _this;
_shuffled = [];
for "_i" from (count _this) to 1 step -1 do
{
_shuffled pushBack (_this deleteAt floor(random _i));
};
_shuffled;

View File

@ -22,18 +22,32 @@ private _killed = false;
try
{
{
private _lastDistanceCheckTime = _x getVariable ["DMS_LastAIDistanceCheck",time];
private _pos = getPosWorld _x;
private _spawnPos = _x getVariable ["DMS_AISpawnPos",0];
if ((DMS_MaxAIDistance>0) && {!(_spawnPos isEqualTo 0)} && {((time - _lastDistanceCheckTime)>DMS_AIDistanceCheckFrequency) && {(_pos distance2D _spawnPos)>DMS_MaxAIDistance}}) then
if (DMS_MaxAIDistance>0) 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,_spawnPos];
private _lastDistanceCheckTime = _x getVariable ["DMS_LastAIDistanceCheck",time];
private _pos = getPosWorld _x;
private _spawnPos = _x getVariable ["DMS_AISpawnPos",0];
if (!(_spawnPos isEqualTo 0) && {(time - _lastDistanceCheckTime)>DMS_AIDistanceCheckFrequency}) then
{
if ((_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,_spawnPos];
}
else
{
_x setVariable ["DMS_LastAIDistanceCheck",time];
throw _x;
};
}
else
{
throw _x;
};
}
else
{
_x setVariable ["DMS_LastAIDistanceCheck",time];
throw _x;
};
} 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

View File

@ -1,4 +1,4 @@
![ArmA 1.80](https://img.shields.io/badge/Arma-1.80-blue.svg) ![Exile 1.0.3 "Lemon"](https://img.shields.io/badge/Exile-1.0.3%20Lemon-C72651.svg) ![DMS Version](https://img.shields.io/badge/DMS%20Version-2018--02--12-blue.svg)
![ArmA 1.80](https://img.shields.io/badge/Arma-1.80-blue.svg) ![Exile 1.0.4 "Pineapple"](https://img.shields.io/badge/Exile-1.0.4%20Pineapple-C72651.svg) ![DMS Version](https://img.shields.io/badge/DMS%20Version-2018--03--18RC-blue.svg)
# To the User:
@ -100,16 +100,16 @@ If you can't figure it out, leave a post on [the DMS thread on exile forums](htt
<br><br>
### HEADLESS CLIENT:
**DMS does not currently support headless client. Do not attempt to use HC with DMS unless you know what you are doing.**
**DMS does not run on a headless client. Do not attempt to use HC with DMS unless you know what you are doing.**
___
<br><br>
# Credits:
### Authors:
- [Defent](https://github.com/Defent) from [NumenaDayZ](http://numenadayz.com/).
- [eraser1](https://github.com/eraser1) from [TrainwreckDayZ](http://www.trainwreckdayz.com/home).
- [secondcoming](https://github.com/secondcoming) from [ExileYorkshire](http://exileyorkshire.co.uk/).
- [Defent](https://github.com/Defent)
- [eraser1](https://github.com/eraser1)
- [secondcoming](https://github.com/secondcoming)
### Thanks:
@ -121,6 +121,7 @@ ___
- [William from Refugees of the Fallen](http://rtfgaming.com/) for the amazing slums static mission base and ideas :)
- [DONKEYPUNCH](https://github.com/donkeypunchepoch) for everything on the [February 17th 2016 commit](https://github.com/Defent/DMS_Exile/wiki/Changelog#february-17-2016-600-pm-cst-america) ;)
- [MGTDB](https://github.com/MGTDB) for the plethora of fixes, testing, and all-around doing our work for us :P
- [PrimusNZ](https://github.com/PrimusNZ) for some fixes.
- Everybody'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:
@ -150,7 +151,7 @@ ___
* Spawning in a trader on mission completion ([Trillseeker82](http://www.exilemod.com/topic/61-dms-defents-mission-system/?do=findComment&comment=43932)).
#### Full Headless Client Support.
* AI will still be offloaded to clients (ideally); strictly DMS functions will be handled by the HC.
* Handling DMS functions/code as well as AI on the HC.
___