diff --git a/@ExileServer/addons/a3_dms/config.sqf b/@ExileServer/addons/a3_dms/config.sqf index dc6b83d..ca0e36b 100644 --- a/@ExileServer/addons/a3_dms/config.sqf +++ b/@ExileServer/addons/a3_dms/config.sqf @@ -47,6 +47,7 @@ DMS_DEBUG = false; DMS_MinWaterDepth = 20; // Minimum depth of water that an underwater mission can spawn at. + DMS_HideBox = false; // "Hide" the box from being visible by players until the mission is completed. DMS_SpawnBoxSmoke = true; // Spawn a smoke grenade on mission box upon misson completion during daytime DMS_SpawnBoxIRGrenade = true; // Spawn an IR grenade on mission box upon misson completion during nighttime @@ -581,7 +582,7 @@ DMS_DEBUG = false; // Debug Overwrites if(DMS_DEBUG) then { - DMS_TimeBetweenMissions = [30,40]; + DMS_TimeBetweenMissions = [10,15]; DMS_MissionTimeOut = [60,70]; DMS_MissionTypes = [["testmission",1]]; //DMS_MissionTypes = [["mercbase",1]]; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_AILocalityManager.sqf b/@ExileServer/addons/a3_dms/scripts/fn_AILocalityManager.sqf index 473bda5..e7cc826 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_AILocalityManager.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_AILocalityManager.sqf @@ -10,7 +10,7 @@ if !(DMS_ai_offload_to_client) exitWith {}; { // Exile already has a group cleanup system, so we'll leave empty groups for it - if ((count (units _x))>1) then + if (((count (units _x))>1) && {!(_x getVariable ["DMS_LockLocality",false])}) then { private ["_leader", "_group", "_owner"]; _leader = leader _x; @@ -39,11 +39,14 @@ if !(DMS_ai_offload_to_client) exitWith {}; } else { - if (DMS_DEBUG) then + if !((groupOwner _group) isEqualTo (owner DMS_HC_Object)) then { - diag_log format ["DMS_DEBUG AILocalityManager :: Setting ownership of group %1 to HC (%2)",_group,DMS_HC_Object]; + _transferSuccess = _group setGroupOwner (owner DMS_HC_Object); + if (DMS_DEBUG) then + { + diag_log format ["DMS_DEBUG AILocalityManager :: Setting ownership of group %1 to HC (%2). Success: %3",_group,DMS_HC_Object,_transferSuccess]; + }; }; - _group setGroupOwner (owner DMS_HC_Object); }; }; }; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf b/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf index 1b7a36c..b015763 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_FillCrate.sqf @@ -45,6 +45,8 @@ if !(DMS_GodmodeCrates) then _crate allowDamage true; }; +_crate hideObjectGlobal false; + if ((typeName _lootValues)=="ARRAY") then { diff --git a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor.sqf b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor.sqf index cc7293f..5ccfd7c 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_MissionsMonitor.sqf @@ -66,6 +66,9 @@ private ["_pos", "_success", "_timeStarted", "_timeUntilFail", "_units", "_build { _x lock 0; _x allowDamage true; + _x enableRopeAttach true; + _x enableSimulationGlobal true; + _x call ExileServer_system_simulationMonitor_addVehicle; } forEach _vehs; { diff --git a/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf b/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf index 95e6eb3..8afadc7 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_OnKilled.sqf @@ -15,7 +15,7 @@ */ -private ["_unit", "_player", "_side", "_type", "_launcher", "_playerObj", "_rockets", "_grpUnits", "_av", "_memCount", "_gunner", "_driver", "_veh", "_moneyGain", "_repGain", "_money", "_respect"]; +private ["_unit", "_killer", "_side", "_type", "_launcher", "_playerObj", "_rockets", "_grpUnits", "_av", "_memCount", "_gunner", "_driver", "_veh", "_moneyGain", "_repGain", "_money", "_respect"]; if (DMS_DEBUG) then @@ -23,12 +23,13 @@ if (DMS_DEBUG) then diag_log format ["DMS_DEBUG OnKilled :: Logging AI death with parameters: %1",_this]; }; -_unit = _this select 0 select 0; -_player = _this select 0 select 1; -_side = _this select 1; -_type = _this select 2; -_launcher = secondaryWeapon _unit; -_playerObj = objNull; +_unit = _this select 0 select 0; +_killer = _this select 0 select 1; +_side = _this select 1; +_type = _this select 2; +_launcher = secondaryWeapon _unit; +_launcherVar = _unit getVariable ["DMS_AI_Launcher",""]; +_playerObj = objNull; // Some of the previously used functions work with non-local argument. Some don't. BIS is annoying _removeAll = @@ -44,14 +45,32 @@ _removeAll = removeBackpackGlobal _unit; }; +moveOut _unit; + // Remove gear according to configs if (DMS_clear_AI_body && {(random 100) <= DMS_clear_AI_body_chance}) then { _unit call _removeAll; }; -if(DMS_ai_remove_launchers && {_launcher != ""}) then +if(DMS_ai_remove_launchers && {(_launcherVar != "") || {_launcher != ""}}) then { + // Because arma is stupid sometimes + if (_launcher=="") then + { + _launcher = _launcherVar; + + diag_log "sneaky launchers..."; + + { + if (_launcherVar in (weaponCargo _x)) exitWith + { + deleteVehicle _x; + diag_log "gotcha"; + }; + } forEach (nearestObjects [_unit, ["GroundWeaponHolder","WeaponHolderSimulated"], 5]); + }; + _rockets = _launcher call DMS_fnc_selectMagazine; _unit removeWeaponGlobal _launcher; @@ -82,14 +101,12 @@ _av = _unit getVariable ["DMS_AssignedVeh",objNull]; if (!isNull _av) then { // Determine whether or not the vehicle has any active crew remaining. - _memCount = {alive _x} count (crew _av); + _memCount = {[(alive _x),false] select (_unit isEqualTo _x);} count (crew _av); // Destroy the vehicle and add it to cleanup if there are no active crew members of the vehicle. if (_memCount<1) then { - moveOut _unit; - _av setDamage 1; DMS_CleanUpList pushBack [_av,diag_tickTime,DMS_AIVehCleanUpTime]; _av spawn {sleep 1;_this enableSimulationGlobal false;}; @@ -108,36 +125,112 @@ if (!isNull _av) then _gunner = gunner _av; _driver = driver _av; + + // The fact that I have to do this in the FUCKING ONKILLED EVENTHANDLER is a testament to why ArmA will make me die prematurely + _gunnerIsAlive = alive _gunner; + _driverIsAlive = alive _driver; + + if (_unit isEqualTo _gunner) then + { + _gunnerIsAlive = false; + }; + if (_unit isEqualTo _driver) then + { + _driverIsAlive = false; + }; + // If the gunner is dead but the driver is alive, then the driver becomes the gunner. // Helps with troll AI vehicles driving around aimlessly after the gunner is shot off. More realistic imo - if (((isNull _gunner) || {!(alive _gunner)}) && {!(isNull _driver) && {alive _driver}}) then + if (!_gunnerIsAlive && {_driverIsAlive}) then { - [_driver,_av] spawn + [_driver,_av,_killer] spawn { - _driver = _this select 0; - _av = _this select 1; - _av setVehicleAmmoDef 1; - sleep 5+(random 3); // 3 to 6 seconds delay after gunner death, to simulate reaction/switching time. + _driver = _this select 0; + _av = _this select 1; + _killer = _this select 2; + _grp = group _driver; + _owner = groupOwner _grp; - // The unit has to be local or else some of the commands won't work. Might as well eject the driver from the vehicle and make him useful. + _grp setVariable ["DMS_LockLocality",true]; + + // The AI has to be local in order for these commands to work, so I reset locality, just because it's really difficult to deal with otherwise + if (_owner!=2) then + { + diag_log format ["Temporarily setting owner of %1 to server from %2. Success: %3",_grp,_owner,_grp setGroupOwner 2]; + }; + + sleep 5+(random 3); // 5 to 8 seconds delay after gunner death + + if !(alive _driver) exitWith {}; + + unassignVehicle _driver; moveOut _driver; - if (!local _driver) exitWith {}; + + _driver disableCollisionWith _av; - //doGetOut _driver; - //unassignVehicle _driver; - waitUntil {(vehicle _driver)==_driver}; + _av setVehicleAmmoDef 1; + + waitUntil + { + unassignVehicle _driver; + doGetOut _driver; + moveOut _driver; + (vehicle _driver)==_driver + }; _driver assignAsGunner _av; [_driver] orderGetIn true; sleep 1.5; + if !(alive _driver) exitWith {}; _driver moveInGunner _av; + + _driver enableCollisionWith _av; if (DMS_DEBUG) then { - diag_log format["DMS_DEBUG OnKilled :: Switching driver of AI Vehicle (%1) to gunner.",typeOf _av]; + diag_log format["DMS_DEBUG OnKilled :: Switched driver of AI Vehicle (%1) to gunner.",typeOf _av]; }; + + if (_owner!=2) then + { + _start = time; + + // Controlling AI... yes. I have to do this + waitUntil + { + _driver assignAsGunner _av; + [_driver] orderGetIn true; + + _driver moveInGunner _av; + + (((gunner _av) isEqualTo _driver) || {(time-_start)>30}) + }; + + sleep 3; + + _start = time; + + waitUntil + { + _driver assignAsGunner _av; + [_driver] orderGetIn true; + + _driver moveInGunner _av; + + (((gunner _av) isEqualTo _driver) || {(time-_start)>30}) + }; + + _driver doTarget _killer; + _driver doFire _killer; + + sleep 15; + + diag_log format ["Resetting ownership of %1 to %2. Success: %3",_grp,_owner,_grp setGroupOwner _owner]; + }; + + _grp setVariable ["DMS_LockLocality",false]; }; }; }; @@ -145,11 +238,11 @@ if (!isNull _av) then }; -if (isPlayer _player) then +if (isPlayer _killer) then { - _veh = vehicle _player; + _veh = vehicle _killer; - _playerObj = _player; + _playerObj = _killer; // Reveal the killer to the AI units if (DMS_ai_share_info) then @@ -157,19 +250,19 @@ if (isPlayer _player) then { if (((position _x) distance2D (position _unit)) <= DMS_ai_share_info_distance ) then { - _x reveal [_player, 4.0]; + _x reveal [_killer, 4.0]; }; } forEach allUnits; }; // Fix for players killing AI from mounted vehicle guns - if (!(_player isKindOf "Exile_Unit_Player") && {!isNull (gunner _player)}) then + if (!(_killer isKindOf "Exile_Unit_Player") && {!isNull (gunner _killer)}) then { - _playerObj = gunner _player; + _playerObj = gunner _killer; }; - if (!(_veh isEqualTo _player) && {(driver _veh) isEqualTo _player}) then + if (!(_veh isEqualTo _killer) && {(driver _veh) isEqualTo _killer}) then { _playerObj = driver _veh; diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup.sqf index 317aec9..a9cc607 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnAIGroup.sqf @@ -73,6 +73,8 @@ if(_pos_z == 0) then _group = createGroup (missionNamespace getVariable [format ["DMS_%1Side",_side],EAST]); +_group setVariable ["DMS_LockLocality",nil]; + for "_i" from 1 to _count do { _unit = [_group,[_pos_x,_pos_y,_pos_z],_class,_difficulty,_side,"Soldier"] call DMS_fnc_SpawnAISoldier; @@ -93,6 +95,8 @@ if ((!isNil "_launcher") || {DMS_ai_use_launchers && {(random 100) <= DMS_ai_use _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 { diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnCrate.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnCrate.sqf index 62f336f..7b8db7f 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnCrate.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnCrate.sqf @@ -33,4 +33,9 @@ clearItemCargoGlobal _crate; clearMagazineCargoGlobal _crate; clearBackpackCargoGlobal _crate; +if (DMS_HideBox) then +{ + _crate hideObjectGlobal true; +}; + _crate; \ No newline at end of file diff --git a/@ExileServer/addons/a3_dms/scripts/fn_SpawnNonPersistentVehicle.sqf b/@ExileServer/addons/a3_dms/scripts/fn_SpawnNonPersistentVehicle.sqf index f74dc97..00390aa 100644 --- a/@ExileServer/addons/a3_dms/scripts/fn_SpawnNonPersistentVehicle.sqf +++ b/@ExileServer/addons/a3_dms/scripts/fn_SpawnNonPersistentVehicle.sqf @@ -38,19 +38,34 @@ _maxDistance = 10; while{count _vehpos < 1} do { _vehpos = _position findEmptyPosition [20,_maxDistance,_vehicleClass]; - _maxDistance = (_maxDistance + 15); + _maxDistance = (_maxDistance + 5); }; -_vehObj = [_vehicleClass, _vehpos, (random 360), true] call ExileServer_object_vehicle_createNonPersistentVehicle; -_vehObj allowDamage false; -_vehObj setFuel 1; -_vehObj lock 2; +_vehpos set [2, 0.1]; + +_vehObj = createVehicle [_vehicleClass, _vehpos, [], 0, "CAN_COLLIDE"]; + +clearBackpackCargoGlobal _vehObj; +clearItemCargoGlobal _vehObj; +clearMagazineCargoGlobal _vehObj; +clearWeaponCargoGlobal _vehObj; + +_vehObj setVariable ["ExileIsPersistent", false]; + +_vehObj setFuel (0.75+(random 0.25)); +_vehObj setDir (random 360); +_vehObj setPosATL _vehpos; _vehObj setVectorUp (surfaceNormal _vehpos); +_vehObj lock 2; +_vehObj allowDamage false; +_vehObj enableRopeAttach false; +_vehObj enableSimulationGlobal false; + if (DMS_DEBUG) then { diag_log format ["DMS_DEBUG SpawnNonPersistentVehicle :: Created %1 at %2 with calling parameters: %3",_vehObj,_vehpos,_this]; }; -_vehObj +_vehObj \ No newline at end of file diff --git a/Pre-Packed PBO/a3_dms.pbo b/Pre-Packed PBO/a3_dms.pbo index 2884e85..331b0a0 100644 Binary files a/Pre-Packed PBO/a3_dms.pbo and b/Pre-Packed PBO/a3_dms.pbo differ diff --git a/README.md b/README.md index 59f9f5e..7b9bba7 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,15 @@ if (!hasInterface && !isServer) then ## Changelog: +#### September 18, 2015 (6:30 PM CST-America): +* NEW CONFIG VALUE: "DMS_HideBox". +* Loot vehicles cannot be lifted, pushed, or damaged until the mission is completed successfully. Then the vehicle will be added to the Exile simulation monitor. +* AI in vehicles will be automatically ejected on death. +* Another potential fix for launchers not despawning off of AI sometimes. +* When an AI gunner from an armed ground vehicle is killed, the driver will be switched to the gunner seat after 5-10 seconds. This prevents the driver from driving around aimlessly and trolling. +* The above feature should now also work on AI that have been offloaded now (doing so was a major, major pain in the ass, and is the reason why there was no update yesterday). + + #### September 16, 2015 (10:30 PM CST-America): * NEW CONFIG VALUES: DMS_MaxAIDistance and DMS_AIDistanceCheckFrequency * You can now use the above config values to kill AI that flee from their spawn position. Only "Soldier" AI will be killed.