mirror of
https://github.com/Defent/DMS_Exile.git
synced 2024-08-30 16:52:12 +00:00
Say bye-bye to the pre-packed PBO ;)
#### November 14, 2015 (8:30 PM CST-America): * **NEW CONFIG VALUES:** DMS_AllowStaticReinforcements DMS_MarkerText_ShowAICount_Static DMS_PredefinedMissionLocations_WEIGHTED DMS_AIKill_DistanceBonusMinDistance DMS_AIKill_DistanceBonusCoefficient * You can now manually disable Static Mission AI reinforcements using "DMS_AllowStaticReinforcements" * You can now choose whether or not to show AI count for map markers for both Static and Dynamic missions separately. * DMS will now check to see if the config.sqf didn't load properly, and for the presence of RyanZombies. * You can now make predefined locations weighted. * Some optimization + code clarity. * Added ```taviana_config.sqf``` (identical to ```tavi_config.sqf```) for the latest version of Taviana. * **saltflats mission**: * The AI will now initially spawn randomly across the compound. This should help with the issue of some AI spawning outside of the compound. * Added more static guns: 4 around the flagpole (5 meters north, south, east, and west). One on top of the tower in each corner, and another on the top of the concrete water tower. * When an AI group is offloaded to a client and he gets out of range AND no other viable client is found, the AI locality should now revert to the server (it used to just stay with the original client). * Added extra measures to prevent the creation of 2 markers with the same name. * fn_FillCrate.sqf: * Fixed the issue where DMS would complain about incorrect parameters when using custom code to generate loot. * DMS now has debug logging to tell you exactly what it spawns in the crate when using a crate case or custom code. * "DMS_PredefinedMissionLocations" itself will now be shuffled when finding a position. This should make the generated positions even more random. * Added new Group Reinforcement Types: "armed_vehicle_replace" and "static_gunner" * Potentially resolved the issue with launchers not being deleted from AI bodies when they're killed sometimes. * **fn_PlayerAwardOnAIKill.sqf**: Created a separate function to handle poptabs/respect of a player when he/she kills an AI. * Added a "distance bonus" for respect when killing AI. * Added logging for player rewards on AI kills. * DMS now lets Exile's body cleanup handle dead AIs. * Fixed the issue where DMS would spawn static missions even when "DMS_StaticMission" is set to false. * fn_SetAILocality.sqf now returns true/false if it does/doesn't find an owner. * New function "fn_SpawnAIGroup_MultiPos.sqf". Almost identical to SpawnAIGroup, except it spawns each AI along a list of locations. * **Removed the pre-packed PBO. Too many people were having issues with their PBO tool removing the prefix and repacking it would result in DMS not working.**
This commit is contained in:
parent
72f0469297
commit
78aa0f8667
@ -57,6 +57,7 @@ class CfgFunctions
|
||||
class MissionsMonitor_Static {};
|
||||
class MissionSuccessState {};
|
||||
class OnKilled {};
|
||||
class PlayerAwardOnAIKill {};
|
||||
class RemoveMarkers {};
|
||||
class SelectRandomVal {};
|
||||
class SelectMagazine {};
|
||||
@ -65,6 +66,7 @@ class CfgFunctions
|
||||
class SetAILocality {};
|
||||
class SetGroupBehavior {};
|
||||
class SpawnAIGroup {};
|
||||
class SpawnAIGroup_MultiPos {};
|
||||
class SpawnAIVehicle {};
|
||||
class SpawnAISoldier {};
|
||||
class SpawnAIStaticMG {};
|
||||
|
@ -6,8 +6,9 @@
|
||||
*/
|
||||
|
||||
|
||||
// Enables debug logging in DMS functions. This will also make missions spawn and timeout more quickly (for testing purposes).
|
||||
// Disable this on live servers, unless you know what you're doing.
|
||||
// Enables debug logging in DMS functions.
|
||||
// Logs will be written in the RPT, and if you have infiSTAR's "ARMA_LOG" DLL loaded, it will also produce logs in the server directory.
|
||||
// This will produce A LOT of logs, so make sure you leave it to false unless you know what you're doing.
|
||||
DMS_DEBUG = false;
|
||||
|
||||
|
||||
@ -38,6 +39,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
|
||||
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_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;
|
||||
/*General settings for static missions*/
|
||||
|
||||
DMS_playerNearRadius = 100; // How close a player has to be to a mission in order to satisfy the "playerNear" mission requirement (can be customized per mission).
|
||||
@ -49,6 +51,7 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
|
||||
DMS_MarkerText_ShowMissionPrefix = true; // Whether or not to place a prefix before the mission marker text. Enable this if your players get confused by the marker names :P
|
||||
DMS_MarkerText_MissionPrefix = "Mission:"; // The text displayed before the mission name in the mission marker.
|
||||
DMS_MarkerText_ShowAICount = true; // Whether or not to display the number of remaining AI in the marker name.
|
||||
DMS_MarkerText_ShowAICount_Static = true; // Whether or not to display the number of remaining AI in the marker name for STATIC missions.
|
||||
DMS_MarkerText_AIName = "Units"; // What the AI will be called in the map marker. For example, the marker text can show: "Car Dealer (3 Units remaining)"
|
||||
DMS_MarkerPosRandomization = false; // Randomize the position of the circle marker of a mission
|
||||
DMS_MarkerPosRandomRadius = [25,100]; // Minimum/Maximum distance that the circle marker position will be randomized | DEFAULT: 0 meters to 200 meters
|
||||
@ -65,12 +68,28 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
|
||||
DMS_CompletedMissionCleanup = true; // Cleanup mission-spawned buildings and AI bodies after some time
|
||||
DMS_CompletedMissionCleanupTime = 3600; // Minimum time until mission-spawned buildings and AI are cleaned up
|
||||
DMS_CleanUp_PlayerNearLimit = 20; // Cleanup of an object is aborted if a player is this many meters close to the object
|
||||
DMS_AIVehCleanUpTime = 900; // Time until a destroyed AI vehicle is cleaned up.
|
||||
DMS_AIVehCleanUpTime = 300; // Time until a destroyed AI vehicle is cleaned up.
|
||||
/*Mission Cleanup settings*/
|
||||
|
||||
/*Mission spawn location settings*/
|
||||
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],
|
||||
...
|
||||
positionN: [x_N,y_N,z_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_N,y_N,z_N], chance_N]
|
||||
*/
|
||||
|
||||
];
|
||||
DMS_ThrottleBlacklists = true; // Whether or not to "throttle" the blacklist distance parameters in DMS_fnc_FindSafePos. This will reduce the values of the minimum
|
||||
@ -197,6 +216,9 @@ DMS_Use_Map_Config = true; // Whether or not to use config overwrites specific t
|
||||
DMS_Bandit_Static_RepGain = 15; // The amount of Respect gained for killing a bandit static gunner
|
||||
DMS_Bandit_Vehicle_MoneyGain = 100; // The amount of Poptabs gained for killing a bandit vehicle crew member
|
||||
DMS_Bandit_Vehicle_RepGain = 25; // The amount of Respect gained for killing a bandit vehicle crew member
|
||||
|
||||
DMS_AIKill_DistanceBonusMinDistance = 100; // Minimum distance from the player to the AI to apply the distance bonus.
|
||||
DMS_AIKill_DistanceBonusCoefficient = 0.25; // If the distance from the player to the killed unit is more than "DMS_AIKill_DistanceBonusMinDistance" meters then the player gets a respect bonus equivalent to the distance multiplied by this coefficient. For example, killing an AI from 400 meters will give 100 extra respect (when the coefficient is 0.25). Set to 0 to disable the bonus. This bonus will not be applied if there isn't a regular AI kill bonus.
|
||||
|
||||
DMS_Diff_RepOrTabs_on_roadkill = true; // Whether or not you want to use different values for giving respect/poptabs when you run an AI over. Default values are NEGATIVE. This means player will LOSE respect or poptabs.
|
||||
DMS_Bandit_Soldier_RoadkillMoney = -10; // The amount of Poptabs gained/lost for running over a bandit soldier
|
||||
|
@ -13,6 +13,17 @@ if !(isServer) exitWith
|
||||
};
|
||||
|
||||
|
||||
|
||||
if (isNil "DMS_DynamicMission") exitWith
|
||||
{
|
||||
for "_i" from 0 to 99 do
|
||||
{
|
||||
diag_log "DMS ERROR :: You have made an error in your DMS config.sqf! Cancelling DMS Launch.";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
RESISTANCE setFriend[WEST,0];
|
||||
WEST setFriend[RESISTANCE,0];
|
||||
RESISTANCE setFriend[EAST,0];
|
||||
@ -20,12 +31,22 @@ EAST setFriend[RESISTANCE,0];
|
||||
EAST setFriend[WEST,0];
|
||||
WEST setFriend[EAST,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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
DMS_A3_AllMarkerColors = [];
|
||||
for "_i" from 0 to ((count(configfile >> "CfgMarkerColors"))-1) do
|
||||
{
|
||||
@ -33,6 +54,21 @@ for "_i" from 0 to ((count(configfile >> "CfgMarkerColors"))-1) do
|
||||
};
|
||||
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Create and send Client Functions using compileFinal for security.
|
||||
DMS_CLIENT_fnc_spawnDynamicText = compileFinal
|
||||
("
|
||||
[
|
||||
@ -65,11 +101,24 @@ DMS_CLIENT_fnc_spawnTextTiles = compileFinal
|
||||
");
|
||||
publicVariable "DMS_CLIENT_fnc_spawnTextTiles";
|
||||
|
||||
|
||||
|
||||
// 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];
|
||||
|
||||
|
||||
|
||||
if (DMS_DynamicMission || {DMS_StaticMission}) then
|
||||
{
|
||||
call compileFinal preprocessFileLineNumbers "\x\addons\dms\missions\static_init.sqf";
|
||||
@ -123,6 +172,6 @@ else
|
||||
};
|
||||
|
||||
|
||||
DMS_Version = "October 30 2015";
|
||||
DMS_Version = "November 14 2015";
|
||||
|
||||
"DMS post-init complete." call DMS_fnc_DebugLog;
|
||||
|
@ -126,7 +126,7 @@ DMS_fnc_setRelPositions =
|
||||
{
|
||||
private ['_relpos','_objPos'];
|
||||
|
||||
_relpos = [getPosATL _x, _center] call M3E_fnc_subArr;
|
||||
_relpos = (getPosATL _x) vectorDiff _center;
|
||||
_objPos = [_newCPos,_relpos] call DMS_fnc_CalcPos;
|
||||
|
||||
_x setPosATL _objPos;
|
||||
|
27
@ExileServer/addons/a3_dms/map_configs/taviana_config.sqf
Normal file
27
@ExileServer/addons/a3_dms/map_configs/taviana_config.sqf
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Custom configs for Taviana.
|
||||
Sample by eraser1
|
||||
|
||||
All of these configs exist in the main config. The configs below will simply override any config from the main config (although the majority of them are the same).
|
||||
Explanations to all of these configs also exist in the main config.
|
||||
*/
|
||||
|
||||
DMS_findSafePosBlacklist =
|
||||
[
|
||||
//Insert position blacklists here.
|
||||
];
|
||||
|
||||
// These configs are the default values from the main config. Just included here as an example.
|
||||
DMS_PlayerNearBlacklist = 2000;
|
||||
DMS_SpawnZoneNearBlacklist = 2500;
|
||||
DMS_TraderZoneNearBlacklist = 2500;
|
||||
DMS_MissionNearBlacklist = 2500;
|
||||
DMS_WaterNearBlacklist = 500;
|
||||
|
||||
|
||||
// Making these configs below as strict as possible will help in reducing the number of attempts taken to find a valid position, and as a result, improve performance.
|
||||
|
||||
DMS_MinDistFromWestBorder = 500; // The western island is pretty close to the western border.
|
||||
DMS_MinDistFromEastBorder = 4500; // About 4.5km of ocean from the eastern border to the edge of the main east island. Set to 6000 if you want to "cut off" most of the Taviana Zoo area.
|
||||
DMS_MinDistFromSouthBorder = 100; // The western island almost touches the southern border so this one is tiny...
|
||||
DMS_MinDistFromNorthBorder = 3000; // About 3km from the northern tip of the east island to the edge.
|
@ -20,17 +20,54 @@ if ([_pos,DMS_StaticMinPlayerDistance] call DMS_fnc_IsPlayerNearby) exitWith {"d
|
||||
_difficulty = "hardcore";
|
||||
|
||||
|
||||
// Define spawn locations for AI Soldiers. These will be used for the initial spawning of AI as well as reinforcements.
|
||||
// The center spawn location is added 3 times so at least 3 AI will spawn initially at the center location, and so that future reinforcements are more likely to spawn at the center.
|
||||
_AISoldierSpawnLocations =
|
||||
[
|
||||
_pos,
|
||||
_pos,
|
||||
_pos,
|
||||
[23500,18750,0.5],
|
||||
[23498,18715,0.5],
|
||||
[23461,18478.2,0],
|
||||
[23443,18495.3,0],
|
||||
[23424,18479.4,0],
|
||||
[23405.9,18497,0],
|
||||
[23387.1,18479.7,0],
|
||||
[23378.3,18497.6,0],
|
||||
[23359.2,18480,0],
|
||||
[23334.9,18479.2,0],
|
||||
[23295.1,18515.4,3.12796],
|
||||
[23242.7,18793.5,0.5],
|
||||
[23387.2,18638.5,0.5],
|
||||
[23294.6,18640.8,0.2],
|
||||
[23309.1,18683.1,0.6],
|
||||
[23308.5,18683,4],
|
||||
[23360.5,18686.3,4],
|
||||
[23362.9,18679,0.6],
|
||||
[23403.1,18685.1,0.6],
|
||||
[23420.9,18839.6,4.35],
|
||||
[23420.8,18843.4,12.35],
|
||||
[23421,18838.6,0.36],
|
||||
[23422.2,18823.8,0.4],
|
||||
[23502.1,18862.3,15.37],
|
||||
[23494.2,18478.6,15.37],
|
||||
[23206.6,18493.8,15.37],
|
||||
[23239.4,18561.1,0]
|
||||
];
|
||||
|
||||
// Create AI
|
||||
_AICount = 20 + (round (random 5));
|
||||
|
||||
// I add
|
||||
_group =
|
||||
[
|
||||
_pos,
|
||||
_AISoldierSpawnLocations,
|
||||
_AICount,
|
||||
_difficulty,
|
||||
"random",
|
||||
_side
|
||||
] call DMS_fnc_SpawnAIGroup;
|
||||
] call DMS_fnc_SpawnAIGroup_MultiPos;
|
||||
|
||||
_veh =
|
||||
[
|
||||
@ -48,7 +85,16 @@ _veh =
|
||||
_staticGuns =
|
||||
[
|
||||
[
|
||||
[_pos,[-6.29138,3.9917,0]] call DMS_fnc_CalcPos
|
||||
//[23424.4,18844.1,15.33], // Top of the construction building. I added this and I thought it may be too much. Your choice if you want to uncomment ;)
|
||||
_pos vectorAdd [5,0,0], // 5 meters East of center pos
|
||||
_pos vectorAdd [-5,0,0], // 5 meters West of center pos
|
||||
_pos vectorAdd [0,5,0], // 5 meters North of center pos
|
||||
_pos vectorAdd [0,-5,0], // 5 meters South of center pos
|
||||
[23216.3,18863.6,20.5], // Top of NorthWest Tower
|
||||
[23506.6,18867.6,20.5], // Top of NorthEast Tower
|
||||
[23497.9,18483.8,20.5], // Top of SouthEast Tower
|
||||
[23211.1,18489.3,20.5], // Top of SouthWest Tower
|
||||
[23509.7,18788.1,22.52] // Top of the concrete water tower thing.
|
||||
],
|
||||
_group,
|
||||
"assault",
|
||||
@ -133,35 +179,7 @@ _groupReinforcementsInfo =
|
||||
240, // About a 4 minute delay between reinforcements.
|
||||
diag_tickTime
|
||||
],
|
||||
[
|
||||
[23500,18750,0.5],
|
||||
[23498,18715,0.5],
|
||||
[23461,18478.2,0],
|
||||
[23443,18495.3,0],
|
||||
[23424,18479.4,0],
|
||||
[23405.9,18497,0],
|
||||
[23387.1,18479.7,0],
|
||||
[23378.3,18497.6,0],
|
||||
[23359.2,18480,0],
|
||||
[23334.9,18479.2,0],
|
||||
[23295.1,18515.4,3.12796],
|
||||
[23242.7,18793.5,0.5],
|
||||
[23387.2,18638.5,0.5],
|
||||
[23294.6,18640.8,0.2],
|
||||
[23309.1,18683.1,0.6],
|
||||
[23308.5,18683,4],
|
||||
[23360.5,18686.3,4],
|
||||
[23362.9,18679,0.6],
|
||||
[23403.1,18685.1,0.6],
|
||||
[23420.9,18839.6,4.35],
|
||||
[23420.8,18843.4,12.35],
|
||||
[23421,18838.6,0.36],
|
||||
[23422.2,18823.8,0.4],
|
||||
[23502.1,18862.3,15.37],
|
||||
[23494.2,18478.6,15.37],
|
||||
[23206.6,18493.8,15.37],
|
||||
[23239.4,18561.1,0]
|
||||
],
|
||||
_AISoldierSpawnLocations,
|
||||
"random",
|
||||
_difficulty,
|
||||
_side,
|
||||
|
@ -14,6 +14,7 @@ if (!DMS_ai_offload_to_client && {isNull DMS_HC_Object}) exitWith {};
|
||||
private ["_leader", "_group", "_owner"];
|
||||
_leader = leader _x;
|
||||
_group = _x;
|
||||
_groupOwner = groupOwner _group;
|
||||
if ((!isNull _leader) && {(alive _leader) && {!isPlayer _leader}}) then
|
||||
{
|
||||
if (isNull DMS_HC_Object) then
|
||||
@ -22,23 +23,39 @@ if (!DMS_ai_offload_to_client && {isNull DMS_HC_Object}) exitWith {};
|
||||
{
|
||||
(format ["AILocalityManager :: DMS_HC_Object is null! Finding owner for group: %1",_group]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
|
||||
|
||||
_owner = objNull;
|
||||
|
||||
if !(local _group) then // Only check for the group owner in players if it doesn't belong to the server.
|
||||
{
|
||||
if ((groupOwner _group) isEqualTo (owner _x)) exitWith
|
||||
{
|
||||
_owner = _x;
|
||||
};
|
||||
} forEach allPlayers;
|
||||
if (_groupOwner isEqualTo (owner _x)) exitWith
|
||||
{
|
||||
_owner = _x;
|
||||
};
|
||||
} forEach allPlayers;
|
||||
};
|
||||
|
||||
if ((isNull _owner) || {(_owner distance2D _leader)>3500}) then
|
||||
{
|
||||
[_group,_leader] call DMS_fnc_SetAILocality;
|
||||
if !([_group,_leader] call DMS_fnc_SetAILocality) then
|
||||
{
|
||||
if !(local _group) then
|
||||
{
|
||||
_group setGroupOwner 2;
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format ["AILocalityManager :: Current owner of group %1 is too far away and no other viable owner found; resetting ownership to the server.",_group]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if !((groupOwner _group) isEqualTo (owner DMS_HC_Object)) then
|
||||
if !(_groupOwner isEqualTo (owner DMS_HC_Object)) then
|
||||
{
|
||||
_transferSuccess = _group setGroupOwner (owner DMS_HC_Object);
|
||||
if (DMS_DEBUG) then
|
||||
|
@ -17,7 +17,7 @@ private ["_pos", "_relPos", "_npos"];
|
||||
|
||||
_OK = params
|
||||
[
|
||||
["_pos","",[[],objNull]],
|
||||
["_pos","",[[],objNull],[2,3]],
|
||||
["_relPos","",[[]],[2,3]]
|
||||
];
|
||||
|
||||
@ -30,7 +30,7 @@ if (!_OK) exitWith
|
||||
// Get the position if an object was supplied instead of position
|
||||
if ((typeName _pos)=="OBJECT") then
|
||||
{
|
||||
_pos = getPos _pos;
|
||||
_pos = getPosATL _pos;
|
||||
};
|
||||
|
||||
// Set the center pos to 0 if it isn't defined
|
||||
@ -46,13 +46,5 @@ if ((count _relPos)<3) then
|
||||
_relPos set [2,0];
|
||||
};
|
||||
|
||||
|
||||
_npos =
|
||||
[
|
||||
(_pos select 0)+(_relPos select 0),
|
||||
(_pos select 1)+(_relPos select 1),
|
||||
(_pos select 2)+(_relPos select 2)
|
||||
];
|
||||
|
||||
|
||||
_npos
|
||||
// Script command "vectorAdd" is much faster than adding each element manually.
|
||||
_pos vectorAdd _relPos
|
@ -50,54 +50,65 @@ _clean =
|
||||
};
|
||||
|
||||
|
||||
{
|
||||
if ((typeName _x) == "OBJECT") then
|
||||
{
|
||||
if (isNull _x) exitWith {};
|
||||
|
||||
if !([_x,DMS_CleanUp_PlayerNearLimit] call DMS_fnc_IsPlayerNearby) then
|
||||
{
|
||||
private ["_parameter"];
|
||||
_parameter = _x;
|
||||
|
||||
switch (typeName _parameter) do
|
||||
{
|
||||
case "ARRAY":
|
||||
{
|
||||
_x call _clean;
|
||||
}
|
||||
else
|
||||
{
|
||||
_skippedObjects pushBack _x;
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format ["CleanUp :: Skipping cleanup for |%1|, player within %2 meters!",_x,DMS_CleanUp_PlayerNearLimit]) call DMS_fnc_DebugLog;
|
||||
(format ["CleanUp :: Doing recursive call for ARRAY: %1",_parameter]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
_parameter call DMS_fnc_CleanUp;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((typeName _x) == "GROUP") exitWith
|
||||
{
|
||||
if (!isNull _x) then
|
||||
{
|
||||
// Group cleanup should only be called when it has to be deleted regardless, so no need to check for nearby players
|
||||
{
|
||||
_x call _clean;
|
||||
} forEach (units _x);
|
||||
|
||||
if(local _x)then
|
||||
case "OBJECT":
|
||||
{
|
||||
if (isNull _parameter) exitWith {};
|
||||
|
||||
if !([_parameter,DMS_CleanUp_PlayerNearLimit] call DMS_fnc_IsPlayerNearby) then
|
||||
{
|
||||
_parameter call _clean;
|
||||
}
|
||||
else
|
||||
{
|
||||
_skippedObjects pushBack _parameter;
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
deleteGroup _x;
|
||||
}
|
||||
else
|
||||
{
|
||||
[groupOwner _x,"DeleteGroupPlz",[_x]] call ExileServer_system_network_send_to;
|
||||
(format ["CleanUp :: Skipping cleanup for |%1|, player within %2 meters!",_parameter,DMS_CleanUp_PlayerNearLimit]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
};
|
||||
if ((typeName _x) == "ARRAY") exitWith
|
||||
|
||||
case "GROUP":
|
||||
{
|
||||
if (DMS_DEBUG) then
|
||||
if (isNull _parameter) exitWith {};
|
||||
|
||||
// Group cleanup should only be called when it has to be deleted regardless of player presence, so no need to check for nearby players
|
||||
// If you want to check player presence before deleting a group, then do {(units _group) call DMS_fnc_CleanUp} instead of {_group call DMS_fnc_CleanUp}
|
||||
{
|
||||
(format ["CleanUp :: Doing recursive call for ARRAY: %1",_x]) call DMS_fnc_DebugLog;
|
||||
_x call _clean;
|
||||
} forEach (units _parameter);
|
||||
|
||||
if (local _parameter) then
|
||||
{
|
||||
deleteGroup _parameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
[groupOwner _parameter, "DeleteGroupPlz", [_parameter]] call ExileServer_system_network_send_to;
|
||||
};
|
||||
_x call DMS_fnc_CleanUp;
|
||||
};
|
||||
diag_log format ["DMS ERROR :: Attempted to call DMS_fnc_CleanUp on non- group or object %1 from array %2",_x,_this];
|
||||
|
||||
default
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_CleanUp with an invalid parameter: %1 | Type: %2", _parameter, typeName _parameter];
|
||||
[]
|
||||
};
|
||||
};
|
||||
} forEach _this;
|
||||
|
||||
|
@ -60,13 +60,13 @@ if !((toLower _color) in DMS_A3_AllMarkerColors) then
|
||||
_color = "ColorRed";
|
||||
};
|
||||
|
||||
_circle = createMarker [format ["DMS_MissionMarkerCircle%1",_num], _pos];
|
||||
_circle = createMarker [format ["DMS_MissionMarkerCircle%1_%2",_num,round(time)], _pos];
|
||||
_circle setMarkerColor _color;
|
||||
_circle setMarkerShape "ELLIPSE";
|
||||
_circle setMarkerBrush "Solid";
|
||||
_circle setMarkerSize [150,150];
|
||||
|
||||
_dot = createMarker [format ["DMS_MissionMarkerDot%1",_num], _pos];
|
||||
_dot = createMarker [format ["DMS_MissionMarkerDot%1_%2",_num,round(time)], _pos];
|
||||
_dot setMarkerColor "ColorBlack";
|
||||
_dot setMarkerType "mil_dot";
|
||||
_dot setMarkerText _text;
|
||||
|
@ -31,29 +31,29 @@
|
||||
_customLootFunction
|
||||
]
|
||||
In this case, "_customLootFunctionParams" is passed to "_customLootFunction", and the custom loot function must return the loot in the form:
|
||||
[
|
||||
[
|
||||
[
|
||||
weapon1,
|
||||
weapon2,
|
||||
[weapon_that_appears_twice,2],
|
||||
...
|
||||
weaponN
|
||||
],
|
||||
[
|
||||
item1,
|
||||
item2,
|
||||
[item_that_appears_5_times,5],
|
||||
...
|
||||
itemN
|
||||
],
|
||||
[
|
||||
backpack1,
|
||||
backpack2,
|
||||
[backpack_that_appears_3_times,3],
|
||||
...
|
||||
backpackN
|
||||
]
|
||||
weapon1,
|
||||
weapon2,
|
||||
[weapon_that_appears_twice,2],
|
||||
...
|
||||
weaponN
|
||||
],
|
||||
[
|
||||
item1,
|
||||
item2,
|
||||
[item_that_appears_5_times,5],
|
||||
...
|
||||
itemN
|
||||
],
|
||||
[
|
||||
backpack1,
|
||||
backpack2,
|
||||
[backpack_that_appears_3_times,3],
|
||||
...
|
||||
backpackN
|
||||
]
|
||||
]
|
||||
*/
|
||||
|
||||
private ["_crate","_lootValues","_wepCount","_weps","_itemCount","_items","_backpackCount","_backpacks","_weapon","_ammo","_item","_backpack","_crateValues","_rareLootChance","_marker"];
|
||||
@ -63,7 +63,7 @@ private ["_crate","_lootValues","_wepCount","_weps","_itemCount","_items","_back
|
||||
_OK = params
|
||||
[
|
||||
["_crate",objNull,[objNull]],
|
||||
["_lootValues","",[0,"",[]],[3]]
|
||||
["_lootValues","",[0,"",[]],[2,3]]
|
||||
];
|
||||
|
||||
if (!_OK || {isNull _crate}) exitWith
|
||||
@ -221,6 +221,12 @@ else
|
||||
};
|
||||
_crate addBackpackCargoGlobal _x;
|
||||
} forEach _backpacks;
|
||||
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format["FillCrate :: Filled crate %1 (at %5) with weapons |%2|, items |%3|, and backpacks |%4|",_crate, _weps, _items, _backpacks, getPosATL _crate]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ _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;
|
||||
_presetLocs = DMS_PredefinedMissionLocations call ExileClient_util_array_shuffle;
|
||||
_presetLocsLength = count _presetLocs;
|
||||
};
|
||||
|
||||
|
@ -25,27 +25,33 @@ if ((typeName _this)!="ARRAY") then
|
||||
_units = [];
|
||||
|
||||
{
|
||||
private ["_parameter", "_tN"];
|
||||
private ["_parameter"];
|
||||
_parameter = _x;
|
||||
_tN = typeName _parameter;
|
||||
if (_tN == "ARRAY") then
|
||||
{
|
||||
_units append (_parameter call DMS_fnc_GetAllUnits);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_tN in ["OBJECT", "GROUP"]) then
|
||||
|
||||
_units append
|
||||
(
|
||||
switch (typeName _parameter) do
|
||||
{
|
||||
if (!isNull _parameter) then
|
||||
case "ARRAY":
|
||||
{
|
||||
if (_tN == "OBJECT") then
|
||||
_parameter call DMS_fnc_GetAllUnits
|
||||
};
|
||||
|
||||
case "OBJECT":
|
||||
{
|
||||
if (!(isNull _parameter) && {alive _parameter}) then
|
||||
{
|
||||
if (alive _parameter) then
|
||||
{
|
||||
_units pushBack _parameter;
|
||||
};
|
||||
[_parameter]
|
||||
}
|
||||
else
|
||||
{
|
||||
[]
|
||||
}
|
||||
};
|
||||
|
||||
case "GROUP":
|
||||
{
|
||||
if (!isNull _parameter) then
|
||||
{
|
||||
{
|
||||
if (alive _x) then
|
||||
@ -54,13 +60,16 @@ _units = [];
|
||||
};
|
||||
} forEach (units _parameter);
|
||||
};
|
||||
[]
|
||||
};
|
||||
|
||||
default
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_GetAllUnits with an invalid parameter: %1 | Type: %2", _parameter, typeName _parameter];
|
||||
[]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_GetAllUnits with an invalid parameter: %1 | Type: %2", _x, _tN];
|
||||
};
|
||||
};
|
||||
);
|
||||
} forEach _this;
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
|
@ -61,13 +61,28 @@
|
||||
_maxAICount // (OPTIONAL) SCALAR: Maximum number of AI Units after reinforcements. Default value is equivalent to _AICount. Set to 0 for no limit.
|
||||
]
|
||||
|
||||
"static_gunner":
|
||||
_monitorParams =
|
||||
[
|
||||
_staticGun, // OBJECT: If this object (static gun) loses its gunner and/or is deleted, then a new static gun and/or gunner will spawn to replace the previous one.
|
||||
_gunPos, // ARRAY (positionATL): The position of the static gun.
|
||||
_staticGunClass // (OPTIONAL) STRING: The classname of the static gun to spawn as reinforcement.
|
||||
]
|
||||
|
||||
"armed_vehicle":
|
||||
_monitorParams =
|
||||
[
|
||||
_AICount, // SCALAR: If the AI Group has fewer than "_AICount" living units, then the group will receive reinforcements.
|
||||
_vehClass // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
|
||||
]
|
||||
NOTE: Every reinforcement vehicle as one unit given for monitor type "armed_vehicle"
|
||||
|
||||
"armed_vehicle_replace":
|
||||
_monitorParams =
|
||||
[
|
||||
_vehicle, // OBJECT: When this vehicle is null or dead, then this group will receive reinforcements. The spawned vehicle will then be the new _vehicle.
|
||||
_vehClass // (OPTIONAL) STRING: The classname of the vehicle to spawn. Use "random" to select a random vehicle from "DMS_ArmedVehicles". Default: "random"
|
||||
]
|
||||
NOTE: Every reinforcement vehicle counts as one unit given for monitor type "armed_vehicle" and "armed_vehicle_replace"
|
||||
|
||||
Returns whether or not reinforcement waves or units given exceeds/matches maximum wave or unit reinforcements. If true, then no more reinforcements will be spawned (so the passed info should be deleted from the available reinforcements list).
|
||||
*/
|
||||
@ -335,6 +350,102 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
case "armed_vehicle_replace":
|
||||
{
|
||||
private ["_vehicle", "_vehClass", "_leaderPos"];
|
||||
|
||||
if !(_monitorParams params
|
||||
[
|
||||
["_vehicle", objNull, [objNull]]
|
||||
])
|
||||
exitWith
|
||||
{
|
||||
_reinforcementsDepleted = true;
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
|
||||
};
|
||||
|
||||
if ((isNull _vehicle) || {!alive _vehicle} || {(count (crew _vehicle)) isEqualTo 0}) then
|
||||
{
|
||||
deleteVehicle _vehicle;
|
||||
|
||||
_vehClass = if ((count _monitorParams)>1) then {_monitorParams param [1, "", [""]]} else {"random"};
|
||||
|
||||
_leaderPos = getPosATL (leader _AIGroup);
|
||||
|
||||
_vehicle =
|
||||
[
|
||||
[
|
||||
if (_spawnLocations isEqualTo []) then {[_leaderPos,100+(random 200),random 360] call DMS_fnc_SelectOffsetPos} else {_spawnLocations call BIS_fnc_selectRandom},
|
||||
_leaderPos
|
||||
],
|
||||
_AIGroup,
|
||||
_class,
|
||||
_difficulty,
|
||||
_side,
|
||||
_vehClass
|
||||
] call DMS_fnc_SpawnAIVehicle;
|
||||
|
||||
// Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
|
||||
_reinforcementWavesGiven = _reinforcementWavesGiven + 1;
|
||||
_reinforcementUnitsGiven = _reinforcementWavesGiven;
|
||||
|
||||
_monitorParams set [0, _vehicle];
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format["GroupReinforcementsManager :: Group %1 received a ""%2"" vehicle (%3) as reinforcements.",_AIGroup, _vehClass, _vehicle]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
case "static_gunner":
|
||||
{
|
||||
private ["_staticGun", "_gunPos", "_staticGunClass"];
|
||||
|
||||
if !(_monitorParams params
|
||||
[
|
||||
["_staticGun", objNull, [objNull]],
|
||||
["_gunPos", [], [[]], [2,3]]
|
||||
])
|
||||
exitWith
|
||||
{
|
||||
_reinforcementsDepleted = true;
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_GroupReinforcementsManager with invalid _monitorParams: %1 | _monitorType: %2 | Setting _reinforcementsDepleted to true.",_monitorParams,_monitorType];
|
||||
};
|
||||
|
||||
if ((isNull _staticGun) || {!alive _staticGun} || {(count (crew _staticGun)) isEqualTo 0}) then
|
||||
{
|
||||
deleteVehicle _staticGun;
|
||||
|
||||
_staticGunClass = if ((count _monitorParams)>1) then {_monitorParams param [1, "", [""]]} else {"random"};
|
||||
|
||||
_leaderPos = getPosATL (leader _AIGroup);
|
||||
|
||||
_staticGun =
|
||||
[
|
||||
[
|
||||
_gunPos
|
||||
],
|
||||
_AIGroup,
|
||||
_class,
|
||||
_difficulty,
|
||||
_side,
|
||||
_staticGunClass
|
||||
] call DMS_fnc_SpawnAIStaticMG;
|
||||
|
||||
// Every vehicle counts as one unit given, so the number of units given is equivalent to number of waves given.
|
||||
_reinforcementWavesGiven = _reinforcementWavesGiven + 1;
|
||||
_reinforcementUnitsGiven = _reinforcementWavesGiven;
|
||||
|
||||
_monitorParams set [0, _staticGun];
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format["GroupReinforcementsManager :: Group %1 received a ""%2"" static gun (%3) as reinforcement at %4.",_AIGroup, _staticGunClass, _staticGun, _gunPos]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
default
|
||||
{
|
||||
@ -375,7 +486,7 @@ if (!_reinforcementsDepleted && {(diag_tickTime-_lastUpdated)>_updateDelay}) the
|
||||
_spawnPos = _spawnLocations call BIS_fnc_selectRandom;
|
||||
};
|
||||
|
||||
_units pushBack ([_AIGroup,[_spawnPos,1+(random 3),random 360] call DMS_fnc_SelectOffsetPos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier);
|
||||
_units pushBack ([_AIGroup,_spawnPos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier);
|
||||
};
|
||||
|
||||
_units joinSilent _AIGroup; // Otherwise they don't like each other...
|
||||
|
@ -190,7 +190,7 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati
|
||||
throw format ["Mission (%1) Fail at %2 with message %3.",_missionName,_missionPos,_msgLose];
|
||||
};
|
||||
|
||||
if (DMS_MarkerText_ShowAICount) then
|
||||
if (DMS_MarkerText_ShowAICount_Static) then
|
||||
{
|
||||
private ["_dot", "_text"];
|
||||
|
||||
@ -219,12 +219,15 @@ if (DMS_StaticMission_Arr isEqualTo []) exitWith {}; // Empty array, no stati
|
||||
};
|
||||
|
||||
|
||||
if (DMS_AllowStaticReinforcements) then
|
||||
{
|
||||
if (_x call DMS_fnc_GroupReinforcementsManager) then
|
||||
{
|
||||
_groupReinforcementsInfo deleteAt _forEachIndex;
|
||||
};
|
||||
} forEach _groupReinforcementsInfo;
|
||||
if (_x call DMS_fnc_GroupReinforcementsManager) then
|
||||
{
|
||||
_groupReinforcementsInfo deleteAt _forEachIndex;
|
||||
};
|
||||
} forEach _groupReinforcementsInfo;
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
|
||||
private ["_unit", "_killer", "_side", "_type", "_launcher", "_launcherVar", "_playerObj", "_removeAll", "_rockets", "_grpUnits", "_av", "_memCount", "_gunner", "_driver", "_gunnerIsAlive", "_driverIsAlive", "_grp", "_owner", "_start", "_roadKilled", "_veh", "_boom", "_revealAmount", "_silencer", "_moneyChange", "_repChange", "_money", "_respect", "_msgType", "_msgParams"];
|
||||
private ["_unit", "_killer", "_side", "_type", "_launcher", "_launcherVar", "_playerObj", "_removeAll", "_rockets", "_grpUnits", "_av", "_memCount", "_gunner", "_driver", "_gunnerIsAlive", "_driverIsAlive", "_grp", "_owner", "_start", "_roadKilled", "_veh", "_boom", "_revealAmount", "_muzzle", "_silencer"];
|
||||
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
@ -53,7 +53,7 @@ if (DMS_clear_AI_body && {(random 100) <= DMS_clear_AI_body_chance}) then
|
||||
_unit call _removeAll;
|
||||
};
|
||||
|
||||
if(DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then
|
||||
if (DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then
|
||||
{
|
||||
// Because arma is stupid sometimes
|
||||
if (_launcher=="") then
|
||||
@ -62,24 +62,31 @@ if(DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then
|
||||
|
||||
diag_log "sneaky launchers...";
|
||||
|
||||
_unit spawn
|
||||
{
|
||||
if (_launcherVar in (weaponCargo _x)) exitWith
|
||||
sleep 0.5;
|
||||
|
||||
{
|
||||
deleteVehicle _x;
|
||||
diag_log "gotcha";
|
||||
};
|
||||
} forEach (nearestObjects [_unit, ["GroundWeaponHolder","WeaponHolderSimulated"], 5]);
|
||||
_holder = _x;
|
||||
{
|
||||
if (_x isKindOf ["LauncherCore", configFile >> "CfgWeapons"]) exitWith
|
||||
{
|
||||
deleteVehicle _holder;
|
||||
diag_log "gotcha";
|
||||
};
|
||||
} forEach (weaponCargo _holder);
|
||||
} forEach (nearestObjects [_this, ["GroundWeaponHolder","WeaponHolderSimulated"], 5]);
|
||||
};
|
||||
};
|
||||
|
||||
_rockets = _launcher call DMS_fnc_selectMagazine;
|
||||
_unit removeWeaponGlobal _launcher;
|
||||
|
||||
{
|
||||
if(_x == _rockets) then
|
||||
if (_x isKindOf ["CA_LauncherMagazine", configFile >> "CfgMagazines"]) then
|
||||
{
|
||||
_unit removeMagazineGlobal _x;
|
||||
};
|
||||
} forEach magazines _unit;
|
||||
} forEach (magazines _unit);
|
||||
};
|
||||
|
||||
if(DMS_RemoveNVG) then
|
||||
@ -109,6 +116,7 @@ if (!isNull _av) then
|
||||
{
|
||||
_av setDamage 1;
|
||||
DMS_CleanUpList pushBack [_av,diag_tickTime,DMS_AIVehCleanUpTime];
|
||||
_av setVariable ["ExileDiedAt",time];
|
||||
_av spawn {sleep 1;_this enableSimulationGlobal false;};
|
||||
|
||||
|
||||
@ -305,85 +313,8 @@ if (isPlayer _killer) then
|
||||
};
|
||||
|
||||
|
||||
if ((!isNull _playerObj) && {((getPlayerUID _playerObj) != "") && {_playerObj isKindOf "Exile_Unit_Player"}}) then
|
||||
{
|
||||
_moneyChange = missionNamespace getVariable [format ["DMS_%1_%2_MoneyGain",_side,_type],0];
|
||||
_repChange = missionNamespace getVariable [format ["DMS_%1_%2_RepGain",_side,_type],0];
|
||||
|
||||
if (_roadKilled && {DMS_Diff_RepOrTabs_on_roadkill}) then
|
||||
{
|
||||
_moneyChange = missionNamespace getVariable [format ["DMS_%1_%2_RoadkillMoney",_side,_type],0];
|
||||
_repChange = missionNamespace getVariable [format ["DMS_%1_%2_RoadkillRep",_side,_type],0];
|
||||
};
|
||||
|
||||
if ((_moneyChange!=0) || (_repChange!=0)) then
|
||||
{
|
||||
_money = _playerObj getVariable ["ExileMoney", 0];
|
||||
_respect = _playerObj getVariable ["ExileScore", 0];
|
||||
|
||||
if (_moneyChange!=0) then
|
||||
{
|
||||
private ["_msgType", "_msgParams"];
|
||||
|
||||
// Set client's money
|
||||
// I also make sure that they don't get negative poptabs
|
||||
_money = (_money + _moneyChange) max 0;
|
||||
_playerObj setVariable ["ExileMoney",_money];
|
||||
|
||||
_msgType = "moneyReceivedRequest";
|
||||
_msgParams = [str _money, format ["killing a %1 AI",_type]];
|
||||
|
||||
if (_moneyChange<0) then
|
||||
{
|
||||
// Change message for players when they're actually LOSING poptabs
|
||||
_msgType = "notificationRequest";
|
||||
_msgParams = ["Whoops",[format ["Lost %1 poptabs from running over a %2 AI!",abs _moneyChange,_type]]];
|
||||
|
||||
// With the error message the money value won't be updated on the client, so I just directly PVC the value.
|
||||
ExileClientPlayerMoney = _money;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerMoney";
|
||||
ExileClientPlayerMoney = nil;
|
||||
};
|
||||
|
||||
if (DMS_Show_Kill_Poptabs_Notification) then
|
||||
{
|
||||
// Send notification and update client's money stats
|
||||
[_playerObj, _msgType, _msgParams] call ExileServer_system_network_send_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Player's money will already be updated for negative values, so let's not create unnecessary network traffic by sending another PVC
|
||||
if (_moneyChange>0) then
|
||||
{
|
||||
ExileClientPlayerMoney = _money;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerMoney";
|
||||
ExileClientPlayerMoney = nil;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (_repChange!=0) then
|
||||
{
|
||||
// Set client's respect
|
||||
_respect = _respect + _repChange;
|
||||
_playerObj setVariable ["ExileScore",_respect];
|
||||
|
||||
if (DMS_Show_Kill_Respect_Notification) then
|
||||
{
|
||||
// Send frag message
|
||||
[_playerObj, "showFragRequest", [ [[format ["%1 AI KILL",toUpper _type],_repChange]] ] ] call ExileServer_system_network_send_to;
|
||||
};
|
||||
|
||||
// Send updated respect value to client
|
||||
ExileClientPlayerScore = _respect;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerScore";
|
||||
ExileClientPlayerScore = nil;
|
||||
};
|
||||
|
||||
// Update client database entry
|
||||
format["setAccountMoneyAndRespect:%1:%2:%3", _money, _respect, (getPlayerUID _playerObj)] call ExileServer_system_database_query_fireAndForget;
|
||||
};
|
||||
};
|
||||
[_playerObj, _unit, _side, _type, _roadKilled] call DMS_fnc_PlayerAwardOnAIKill;
|
||||
|
||||
|
||||
DMS_CleanUpList pushBack [_unit,diag_tickTime,DMS_CompletedMissionCleanupTime];
|
||||
// Let Exile handle the AI Body cleanup.
|
||||
_unit setVariable ["ExileDiedAt",time];
|
169
@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf
Normal file
169
@ExileServer/addons/a3_dms/scripts/fn_PlayerAwardOnAIKill.sqf
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
DMS_fnc_PlayerAwardOnAIKill
|
||||
Created by eraser1
|
||||
|
||||
Gives (or removes) a player's respect/poptabs for killing an AI.
|
||||
|
||||
Usage:
|
||||
[
|
||||
_playerObj,
|
||||
_unit,
|
||||
_AISide,
|
||||
_AIType,
|
||||
_roadKilled
|
||||
] call DMS_fnc_PlayerAwardOnAIKill;
|
||||
|
||||
Returns nothing
|
||||
*/
|
||||
|
||||
private ["_playerUID", "_playerObj", "_moneyChange", "_AISide", "_AIType", "_repChange", "_roadKilled", "_unitMoney", "_unit", "_unitRespect", "_playerMoney", "_playerRespect", "_msgType", "_msgParams"];
|
||||
|
||||
if !(params
|
||||
[
|
||||
["_playerObj", objNull, [objNull] ],
|
||||
["_unit", objNull, [objNull] ],
|
||||
["_AISide", "", [""] ],
|
||||
["_AIType", "", [""] ],
|
||||
["_roadKilled", false, [false] ]
|
||||
])
|
||||
exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_fnc_PlayerAwardOnAIKill with invalid parameters: %1",_this];
|
||||
};
|
||||
|
||||
|
||||
_playerUID = getPlayerUID _playerObj;
|
||||
|
||||
if ((!isNull _playerObj) && {(_playerUID != "") && {_playerObj isKindOf "Exile_Unit_Player"}}) then
|
||||
{
|
||||
_moneyChange = missionNamespace getVariable [format ["DMS_%1_%2_MoneyGain",_AISide,_AIType],0];
|
||||
_repChange = missionNamespace getVariable [format ["DMS_%1_%2_RepGain",_AISide,_AIType],0];
|
||||
|
||||
if (_roadKilled && {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];
|
||||
};
|
||||
|
||||
// Check for individually defined AI money/respect.
|
||||
_unitMoney = _unit getVariable ["DMS_AI_Money",""];
|
||||
_unitRespect = _unit getVariable ["DMS_AI_Respect",""];
|
||||
|
||||
if !(_unitMoney isEqualTo "") then
|
||||
{
|
||||
_moneyChange = _unitMoney;
|
||||
};
|
||||
|
||||
if !(_unitRespect isEqualTo "") then
|
||||
{
|
||||
_repChange = _unitRespect;
|
||||
};
|
||||
|
||||
|
||||
if ((_moneyChange!=0) || (_repChange!=0)) then
|
||||
{
|
||||
_playerMoney = _playerObj getVariable ["ExileMoney", 0];
|
||||
_playerRespect = _playerObj getVariable ["ExileScore", 0];
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
format ["PlayerAwardOnAIKill :: Attempting to give %1 (%2) %3 poptabs and %4 respect. Player currently has %5 tabs and %6 respect.", name _playerObj, _playerUID, _moneyChange, _repChange, _playerMoney, _playerRespect] call DMS_fnc_DebugLog;
|
||||
};
|
||||
|
||||
if (_moneyChange!=0) then
|
||||
{
|
||||
private ["_msgType", "_msgParams"];
|
||||
|
||||
// Set client's money
|
||||
// I also make sure that they don't get negative poptabs
|
||||
_playerMoney = (_playerMoney + _moneyChange) max 0;
|
||||
_playerObj setVariable ["ExileMoney",_playerMoney];
|
||||
|
||||
_msgType = "moneyReceivedRequest";
|
||||
_msgParams = [str _playerMoney, format ["killing a %1 AI",_AIType]];
|
||||
|
||||
if (_moneyChange<0) then
|
||||
{
|
||||
// Change message for players when they're actually LOSING poptabs
|
||||
_msgType = "notificationRequest";
|
||||
_msgParams = ["Whoops",[format ["Lost %1 poptabs from running over a %2 AI!",abs _moneyChange,_AIType]]];
|
||||
|
||||
// With the error message the money value won't be updated on the client, so I just directly PVC the value.
|
||||
ExileClientPlayerMoney = _playerMoney;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerMoney";
|
||||
ExileClientPlayerMoney = nil;
|
||||
};
|
||||
|
||||
if (DMS_Show_Kill_Poptabs_Notification) then
|
||||
{
|
||||
// Send notification and update client's money stats
|
||||
[_playerObj, _msgType, _msgParams] call ExileServer_system_network_send_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Player's money will already be updated for negative values, so let's not create unnecessary network traffic by sending another PVC
|
||||
if (_moneyChange>0) then
|
||||
{
|
||||
ExileClientPlayerMoney = _playerMoney;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerMoney";
|
||||
ExileClientPlayerMoney = nil;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (_repChange!=0) then
|
||||
{
|
||||
_attributes = [[format ["%1 AI KILL",toUpper _AIType],_repChange]];
|
||||
|
||||
if (DMS_AIKill_DistanceBonusCoefficient>0) then
|
||||
{
|
||||
_distance = floor (_unit distance _playerObj);
|
||||
|
||||
if (_distance>DMS_AIKill_DistanceBonusMinDistance) then
|
||||
{
|
||||
_distanceBonus = floor (_distance * DMS_AIKill_DistanceBonusCoefficient);
|
||||
_attributes pushBack [format ["%1m RANGE BONUS",_distance], _distanceBonus];
|
||||
|
||||
_repChange = _repChange + _distanceBonus;
|
||||
};
|
||||
};
|
||||
|
||||
// Set client's respect
|
||||
_playerRespect = _playerRespect + _repChange;
|
||||
_playerObj setVariable ["ExileScore",_playerRespect];
|
||||
|
||||
if (DMS_Show_Kill_Respect_Notification) then
|
||||
{
|
||||
// Send frag message
|
||||
[_playerObj, "showFragRequest", [_attributes]] call ExileServer_system_network_send_to;
|
||||
};
|
||||
|
||||
// Send updated respect value to client
|
||||
ExileClientPlayerScore = _playerRespect;
|
||||
(owner _playerObj) publicVariableClient "ExileClientPlayerScore";
|
||||
ExileClientPlayerScore = nil;
|
||||
};
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
format ["PlayerAwardOnAIKill :: %1 (%2) awarded %3 poptabs and %4 respect for killing %5. Player's money is now %6, and respect is now %7. Roadkill: %8", name _playerObj, _playerUID, _moneyChange, _repChange, _unit, _playerMoney, _playerRespect, _roadKilled] call DMS_fnc_DebugLog;
|
||||
};
|
||||
|
||||
// Update client database entry
|
||||
format["setAccountMoneyAndRespect:%1:%2:%3", _playerMoney, _playerRespect, _playerUID] call ExileServer_system_database_query_fireAndForget;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
format ["PlayerAwardOnAIKill :: %1 (%2) was not awarded any poptabs or respect.", name _playerObj, _playerUID] call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
format ["PlayerAwardOnAIKill :: No reward for non-player _playerObj: %1",_playerObj] call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
@ -41,7 +41,7 @@ if (diag_fps >= DMS_MinServerFPS && {(count allPlayers) >= DMS_MinPlayerCount})
|
||||
};
|
||||
|
||||
|
||||
if (_time - DMS_StaticMissionLastStart > DMS_StaticMissionDelay) then
|
||||
if ((DMS_StaticMission) && {_time - DMS_StaticMissionLastStart > DMS_StaticMissionDelay}) then
|
||||
{
|
||||
private ["_mission", "_availableMissions"];
|
||||
|
||||
|
@ -28,7 +28,9 @@ if (!_OK) exitWith
|
||||
[0,0,0]
|
||||
};
|
||||
|
||||
_npos = [(_pos select 0)+(sin(_dir)*_dis),(_pos select 1)+(cos(_dir)*_dis),_pos select 2];
|
||||
if ((count _pos) isEqualTo 2) then
|
||||
{
|
||||
_pos set [2,0];
|
||||
};
|
||||
|
||||
|
||||
_npos
|
||||
_pos vectorAdd [sin(_dir)*_dis,cos(_dir)*_dis,0]
|
@ -9,11 +9,14 @@
|
||||
] call DMS_fnc_SetAILocality;
|
||||
|
||||
Makes a random player within 3 KM of the AI unit or group the owner.
|
||||
Offloading AI can increase server performance.
|
||||
Offloading AI will improve server performance, but the unit will no longer be local, which will limit the server's control over it.
|
||||
Could however have negative effects if target player has a potato PC.
|
||||
|
||||
Returns true if a viable owner was found, false otherwise.
|
||||
*/
|
||||
private ["_AI", "_pos", "_exit", "_client"];
|
||||
|
||||
private ["_AI", "_AIType", "_pos", "_exit", "_client", "_swapped"];
|
||||
|
||||
|
||||
_AI = param [0,objNull,[objNull,grpNull]];
|
||||
|
||||
@ -22,20 +25,19 @@ if (isNull _AI) exitWith
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SetAILocality with null parameter; _this: %1",_this];
|
||||
};
|
||||
|
||||
if ((typeName _AI)=="OBJECT") then
|
||||
{
|
||||
_pos = _AI;
|
||||
}
|
||||
else
|
||||
{
|
||||
_pos = param [1,"",[objNull,[]],[2,3]];
|
||||
};
|
||||
|
||||
_AIType = typeName _AI;
|
||||
|
||||
|
||||
_pos = if (_AIType=="OBJECT") then {_AI} else {param [1,"",[objNull,[]],[2,3]]};
|
||||
|
||||
if (_pos isEqualTo "") exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SetAILocality with invalid position; this: %1",_this];
|
||||
};
|
||||
|
||||
|
||||
|
||||
_client = objNull;
|
||||
|
||||
{
|
||||
@ -45,18 +47,29 @@ _client = objNull;
|
||||
};
|
||||
} forEach allPlayers;
|
||||
|
||||
|
||||
if (!isNull _client) then
|
||||
{
|
||||
ExileServerOwnershipSwapQueue pushBack [_AI,_client];
|
||||
_swapped = if (_AIType=="OBJECT") then {_AI setOwner (owner _client)} else {_AI setGroupOwner (owner _client)};
|
||||
|
||||
if (!_swapped) then
|
||||
{
|
||||
ExileServerOwnershipSwapQueue pushBack [_AI,_client];
|
||||
};
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format ["SetAILocality :: Ownership swap of %1 (%4) to %2 (%3) is added to ExileServerOwnershipSwapQueue.",_AI,name _client,getPlayerUID _client,typeName _AI]) call DMS_fnc_DebugLog;
|
||||
(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;
|
||||
};
|
||||
|
||||
true
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format ["SetAILocality :: No viable client found for the ownership of %1! _pos: %2",_AI,_pos]) call DMS_fnc_DebugLog;
|
||||
(format ["SetAILocality :: No viable client found for the ownership of %1! _pos: %2.",_AI,_pos]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
|
||||
false
|
||||
};
|
@ -31,6 +31,12 @@ if (!_OK) 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
|
||||
{
|
||||
@ -40,7 +46,7 @@ if (DMS_DEBUG) then
|
||||
// if soldier have AT/AA weapons
|
||||
if (typeName _class == "ARRAY") then
|
||||
{
|
||||
_launcherType = _class select 1;
|
||||
_launcherType = _class select 1;
|
||||
_class = _class select 0;
|
||||
};
|
||||
|
||||
@ -51,15 +57,9 @@ _group setVariable ["DMS_LockLocality",nil];
|
||||
_group setVariable ["DMS_SpawnedGroup",true];
|
||||
_group setVariable ["DMS_Group_Side", _side];
|
||||
|
||||
if (_count < 1) exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SpawnAIGroup with less than 1 _count! _this: %1",_this];
|
||||
_group
|
||||
};
|
||||
|
||||
for "_i" from 1 to _count do
|
||||
{
|
||||
_unit = [_group,[_pos,random 5,random 360] call DMS_fnc_SelectOffsetPos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier;
|
||||
_unit = [_group,_pos,_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier;
|
||||
};
|
||||
|
||||
// An AI will definitely spawn with a launcher if you define type
|
||||
|
127
@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup_MultiPos.sqf
Normal file
127
@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup_MultiPos.sqf
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
DMS_fnc_SpawnAIGroup_MultiPos
|
||||
Created by eraser1
|
||||
|
||||
|
||||
Spawns a group of AI with a given AI count at the provided list of location(s), with a given difficulty, class, and side.
|
||||
|
||||
Usage:
|
||||
[
|
||||
[
|
||||
_position1, // Potential location for AI to spawn #1
|
||||
_position2, // Potential location for AI to spawn #2
|
||||
...
|
||||
_positionN // Potential location for AI to spawn #N
|
||||
],
|
||||
_count, // Number of AI
|
||||
_difficulty, // AI Difficulty: "random","hardcore","difficult","moderate", or "easy"
|
||||
_class, // AI Class: "random","assault","MG","sniper" or "unarmed" OR [_class,_launcherType]
|
||||
_side // Only "bandit" is supported atm
|
||||
] call DMS_fnc_SpawnAIGroup_MultiPos;
|
||||
|
||||
Returns AI Group
|
||||
*/
|
||||
|
||||
private ["_OK", "_positions", "_count", "_difficulty", "_class", "_side", "_positionsCount", "_launcherType", "_group", "_unit", "_units", "_i", "_launcher", "_rocket"];
|
||||
|
||||
|
||||
_OK = params
|
||||
[
|
||||
["_positions","_positions ERROR",[[]]],
|
||||
["_count","_count ERROR",[0]],
|
||||
["_difficulty","_difficulty ERROR",[""]],
|
||||
["_class","_class ERROR",[""]],
|
||||
["_side","_side ERROR",[""]]
|
||||
];
|
||||
|
||||
if (!_OK) exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SpawnAIGroup_MultiPos with invalid parameters: %1",_this];
|
||||
grpNull
|
||||
};
|
||||
|
||||
_positionsCount = count _positions;
|
||||
|
||||
if (_positionsCount<1) exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SpawnAIGroup_MultiPos with an empty list of positions! _this: %1",_this];
|
||||
grpNull
|
||||
};
|
||||
|
||||
if (_count < 1) exitWith
|
||||
{
|
||||
diag_log format ["DMS ERROR :: Calling DMS_SpawnAIGroup_MultiPos with less than 1 _count! _this: %1",_this];
|
||||
grpNull
|
||||
};
|
||||
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format["SpawnAIGroup_MultiPos :: Spawning %1 %2 %3 AI at positions %4 with %5 difficulty.",_count,_class,_side,_positions,_difficulty]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
|
||||
// if soldier have AT/AA weapons
|
||||
if (typeName _class == "ARRAY") then
|
||||
{
|
||||
_launcherType = _class select 1;
|
||||
_class = _class select 0;
|
||||
};
|
||||
|
||||
|
||||
_group = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]);
|
||||
|
||||
_group setVariable ["DMS_LockLocality",nil];
|
||||
_group setVariable ["DMS_SpawnedGroup",true];
|
||||
_group setVariable ["DMS_Group_Side", _side];
|
||||
|
||||
for "_i" from 1 to _count do
|
||||
{
|
||||
_unit = [_group,_positions select (_i % _positionsCount),_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier;
|
||||
};
|
||||
|
||||
// An AI will definitely spawn with a launcher if you define type
|
||||
if ((!isNil "_launcherType") || {DMS_ai_use_launchers && {DMS_ai_launchers_per_group>0}}) then
|
||||
{
|
||||
if (isNil "_launcherType") then
|
||||
{
|
||||
_launcherType = "AT";
|
||||
};
|
||||
|
||||
_units = units _group;
|
||||
|
||||
for "_i" from 0 to (((DMS_ai_launchers_per_group min _count)-1) max 0) do
|
||||
{
|
||||
if ((random 100)<DMS_ai_use_launchers_chance) then
|
||||
{
|
||||
_unit = _units select _i;
|
||||
|
||||
_launcher = ((missionNamespace getVariable [format ["DMS_AI_wep_launchers_%1",_launcherType],["launch_NLAW_F"]]) call BIS_fnc_selectRandom);
|
||||
|
||||
removeBackpackGlobal _unit;
|
||||
_unit addBackpack "B_Carryall_mcamo";
|
||||
_rocket = _launcher call DMS_fnc_selectMagazine;
|
||||
|
||||
[_unit, _launcher, DMS_AI_launcher_ammo_count,_rocket] call BIS_fnc_addWeapon;
|
||||
|
||||
_unit setVariable ["DMS_AI_Launcher",_launcher];
|
||||
|
||||
if (DMS_DEBUG) then
|
||||
{
|
||||
(format["SpawnAIGroup_MultiPos :: Giving %1 a %2 launcher with %3 %4 rockets",_unit,_launcher,DMS_AI_launcher_ammo_count,_rocket]) call DMS_fnc_DebugLog;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
_group selectLeader ((units _group) select 0);
|
||||
_group setFormation "WEDGE";
|
||||
|
||||
|
||||
|
||||
[_group,_positions select 0,_difficulty,"COMBAT"] call DMS_fnc_SetGroupBehavior;
|
||||
|
||||
|
||||
diag_log format ["DMS_SpawnAIGroup_MultiPos :: Spawned %1 AI using positions parameter: %2.",_count,_positions];
|
||||
|
||||
_group
|
@ -11,11 +11,11 @@
|
||||
...
|
||||
_pos3
|
||||
],
|
||||
_group, // Group to which the AI unit(s) belongs to
|
||||
_class, // Class: "random","assault","MG","sniper" or "unarmed"
|
||||
_difficulty, // Difficulty: "random","static","hardcore","difficult","moderate", or "easy"
|
||||
_side, // "bandit","hero", etc.
|
||||
_MGClass // !OPTIONAL) String: classname of the MG. Use "random" to select a random one from DMS_static_weapons
|
||||
_group, // GROUP: Group to which the AI unit(s) belongs to
|
||||
_class, // STRING: "random","assault","MG","sniper" or "unarmed"
|
||||
_difficulty, // STRING: "random","static","hardcore","difficult","moderate", or "easy"
|
||||
_side, // STRING: "bandit","hero", etc.
|
||||
_MGClass // (OPTIONAL) STRING: classname of the MG. Use "random" to select a random one from DMS_static_weapons
|
||||
] call DMS_fnc_SpawnAIStaticMG;
|
||||
|
||||
Returns an array of static gun objects.
|
||||
|
@ -61,6 +61,8 @@ if (_vehClass == "random") then
|
||||
_tmpGroup = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]);
|
||||
|
||||
_veh = createVehicle [_vehClass, _spawnPos, [], 0, "NONE"];
|
||||
_veh setFuel 1;
|
||||
_veh engineOn true;
|
||||
_veh setDir (random 360);
|
||||
_veh lock 2;
|
||||
|
||||
|
Binary file not shown.
71
README.md
71
README.md
@ -11,30 +11,44 @@ ___
|
||||
|
||||
|
||||
# Instructions
|
||||
See also: http://www.exilemod.com/topic/61-dms-defents-mission-system/?do=findComment&comment=242
|
||||
[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).
|
||||
|
||||
## Installation:
|
||||
Put the pre-packed PBO in your ```@ExileServer\addons\``` directory. It should be alongside ```exile_server``` and ```exile_server_config```.
|
||||
## BattlEye Filters:
|
||||
It is highly recommended that you add
|
||||
|
||||
```
|
||||
!="(_this select 0) execVM \"\A3\Structures_F\Wrecks\Scripts\Wreck_Heli_Attack_01.sqf\""
|
||||
```
|
||||
|
||||
at ***the END of the line that starts with "7 execVM" in scripts.txt*** . [Here is the pastebin](http://pastebin.com/W8bH252U).
|
||||
|
||||
## Installation:
|
||||
|
||||
|
||||
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.
|
||||
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```.
|
||||
|
||||
If you are using Vilayer or some other GameServer hosting service, and/or the above step did not work, then create a new folder called @a3_dms in the root ArmA 3 folder, create a subfolder called "addons", and place the "a3_dms.pbo" in the "addons" subfolder. Then, edit your startup parameters/modline to include "@a3_dms". For example: ```-serverMod=@ExileServer;@a3_dms;```
|
||||
|
||||
## infiSTAR:
|
||||
If you are using infiSTAR and want to keep ```_CGM = true;```, then set ```_UMW = true;``` (the latest version of infiSTAR already has DMS markers whitelisted in ```_aLocalM```).
|
||||
|
||||
## Optional:
|
||||
|
||||
### Vilayer or other Game Server Providers Instructions:
|
||||
|
||||
### To modify the config:
|
||||
1. Download the a3_dms folder
|
||||
2. Edit the config.sqf to your preferences.
|
||||
3. Pack the a3_dms folder with a PBO tool (**PBO Manager**, Eliteness, or Arma 3 Tools suite)
|
||||
4. Follow the ["Installation:" steps](https://github.com/Defent/DMS_Exile#to-install) using the PBO you just created instead of the pre-packed one.
|
||||
If you are using Vilayer or some other GameServer hosting service, and/or the above steps did not work, then follow these instructions:
|
||||
|
||||
1. Create a new folder called @a3_dms in the root ArmA 3 folder.
|
||||
2. Create a subfolder called "addons".
|
||||
3. Place the "a3_dms.pbo" in the "addons" subfolder.
|
||||
4. Edit your startup parameters/modline to include "@a3_dms". For example: ```-serverMod=@ExileServer;@a3_dms;```
|
||||
|
||||
|
||||
### HEADLESS CLIENT:
|
||||
|
||||
**We are dropping Headless Client support for DMS until it is completed, then we will create proper HC support.**
|
||||
**DMS does not currently support headless client. Do not attempt to use HC with DMS unless you know what you are doing.**
|
||||
|
||||
___
|
||||
|
||||
@ -80,6 +94,41 @@ ___
|
||||
___
|
||||
|
||||
# Changelog:
|
||||
#### November 14, 2015 (8:30 PM CST-America):
|
||||
* **NEW CONFIG VALUES:**
|
||||
|
||||
DMS_AllowStaticReinforcements
|
||||
DMS_MarkerText_ShowAICount_Static
|
||||
DMS_PredefinedMissionLocations_WEIGHTED
|
||||
DMS_AIKill_DistanceBonusMinDistance
|
||||
DMS_AIKill_DistanceBonusCoefficient
|
||||
* You can now manually disable Static Mission AI reinforcements using "DMS_AllowStaticReinforcements"
|
||||
* You can now choose whether or not to show AI count for map markers for both Static and Dynamic missions separately.
|
||||
* DMS will now check to see if the config.sqf didn't load properly, and for the presence of RyanZombies.
|
||||
* You can now make predefined locations weighted.
|
||||
* Some optimization + code clarity.
|
||||
* Added ```taviana_config.sqf``` (identical to ```tavi_config.sqf```) for the latest version of Taviana.
|
||||
* **saltflats mission**:
|
||||
* The AI will now initially spawn randomly across the compound. This should help with the issue of some AI spawning outside of the compound.
|
||||
* Added more static guns: 4 around the flagpole (5 meters north, south, east, and west). One on top of the tower in each corner, and another on the top of the concrete water tower.
|
||||
* When an AI group is offloaded to a client and he gets out of range AND no other viable client is found, the AI locality should now revert to the server (it used to just stay with the original client).
|
||||
* Added extra measures to prevent the creation of 2 markers with the same name.
|
||||
* fn_FillCrate.sqf:
|
||||
* Fixed the issue where DMS would complain about incorrect parameters when using custom code to generate loot.
|
||||
* DMS now has debug logging to tell you exactly what it spawns in the crate when using a crate case or custom code.
|
||||
* "DMS_PredefinedMissionLocations" itself will now be shuffled when finding a position. This should make the generated positions even more random.
|
||||
* Added new Group Reinforcement Types: "armed_vehicle_replace" and "static_gunner"
|
||||
* Potentially resolved the issue with launchers not being deleted from AI bodies when they're killed sometimes.
|
||||
* **fn_PlayerAwardOnAIKill.sqf**: Created a separate function to handle poptabs/respect of a player when he/she kills an AI.
|
||||
* Added a "distance bonus" for respect when killing AI.
|
||||
* Added logging for player rewards on AI kills.
|
||||
* DMS now lets Exile's body cleanup handle dead AIs.
|
||||
* Fixed the issue where DMS would spawn static missions even when "DMS_StaticMission" is set to false.
|
||||
* fn_SetAILocality.sqf now returns true/false if it does/doesn't find an owner.
|
||||
* New function "fn_SpawnAIGroup_MultiPos.sqf". Almost identical to SpawnAIGroup, except it spawns each AI along a list of locations.
|
||||
* **Removed the pre-packed PBO. Too many people were having issues with their PBO tool removing the prefix and repacking it would result in DMS not working.**
|
||||
|
||||
|
||||
#### October 30, 2015 (9:30 PM CST-America):
|
||||
* **NEW CONFIG VALUES:**
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user