/* Author: Freddo, Edited by Genesis Description: Function for improving AI driving. AI drivers will avoid obstacles and units BETTER with this, at the cost of FPS. Parameter(s): 0: ARRAY - Array containing drivers to affect Returns: NOTHING Example1: driverArray spawn VCM_fnc_VehicleDetection; */ //This script aims to improve AI driving skills...It's basic. But it works. { private _PredictPos = [_x,3] call VCM_fnc_MovePrediction; _PredictPos set [2,0.1]; if (VCM_Debug) then { _PredictPos spawn { private _arrow = "Sign_Arrow_Cyan_F" createVehicleLocal [0,0,0];_arrow setPos _this;sleep 2;deleteVehicle _arrow; }; }; //Lets check for obstacles and make sure the vehicle does not hit them //Create an array of objects near predicted path //private _obstacles = _predictPos nearObjects ["ALL", VCM_DrivingDist]; // VCM_DrivingDist is search distance //Snap to the nearest road. private _NR = [_PredictPos, VCM_DrivingDist] call BIS_fnc_nearestRoad; if !(isNull _NR) then {_PredictPos = getpos _NR;}; private _obstacles = nearestObjects [_predictPos, ["Strategic"], VCM_DrivingDist,true]; //Remove gates, bridges and units vehicle from obstacles private _RemoveArray = []; private _veh = objectParent _x; { if (_veh isEqualTo _x || (_x isKindOf "AllVehicles") || {["gate",(str _x)] call BIS_fnc_inString} || {["bridge",(str _x)] call BIS_fnc_inString}) then { _RemoveArray pushback _x; //We do this method to avoid indexing errors. }; } forEach _obstacles; //We do this method to avoid indexing errors. { private _Obj = _x; private _Index = _obstacles findIf {_x isEqualTo _Obj}; _obstacles deleteAt _Index; } foreach _RemoveArray; private _hlprArray = []; if (count _obstacles > 0) then { _x forcespeed 10; { if !(_x getVariable ["VCM_AVOID", false] || {_x isKindOf "man"} || {_x isKindOf "Helper_Base_F"} || {_x isKindOf "Logic"}) then { // Vcom ignore this object until loop complete _x setVariable ["VCM_AVOID", true]; // Positions to spawn helper objects private _hlpPosArray = []; private _boundBox = boundingBoxReal _x; private _p2 = _boundBox select 1; _p2 params ["_p2MaxX","_p2MaxY","_p2MaxZ"]; // Find corners of building bounding box _hlpPosArray pushBack (_x modelToWorld [_p2MaxX,_p2MaxY,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [-_p2MaxX,_p2MaxY,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [-_p2MaxX,-_p2MaxY,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [_p2MaxX,-_p2MaxY,-_p2MaxZ + 0.1]); // Get mid points of a building. _hlpPosArray pushBack (_x modelToWorld [0,-_p2MaxY,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [0,_p2MaxY,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [-_p2MaxX,0,-_p2MaxZ + 0.1]); _hlpPosArray pushBack (_x modelToWorld [_p2MaxX,0,-_p2MaxZ + 0.1]); // Spawn helper objects (These act as additional points of contact that the AI will attempt to avoid) { if ([_hlprArray, _x, true,"Driving"] call VCM_fnc_ClstObj distance2D _x > 1) then { private _hlpObj = "Land_Wrench_F" createVehicleLocal _x; _hlpObj setVariable ["VCM_AVOID", true]; _hlpObj setPos _x; //_hlpObj setObjectTextureGlobal [0, ""]; _hlprArray pushBack _hlpObj; _hlpObj setVelocity [0,0,0]; }; } forEach _hlpPosArray; //Spawn debug objects if (VCM_Debug) then { { private _ObjPos = getpos _x; [_ObjPos select 0, _ObjPos select 1, 0.2] spawn { private _arrow = "Sign_Arrow_Large_F" createVehicle [0,0,0]; _arrow setPos _this; sleep 9; deleteVehicle _arrow; }; } forEach _hlprArray; }; // Delete helper objects after some time [_hlprArray, _obstacles,_x] spawn { sleep 9; { deleteVehicle _x; } forEach (_this select 0); { // Allow object to be considered again _x setVariable ["VCM_AVOID", false]; } forEach (_this select 1); (_this#2) forcespeed -1; }; }; } forEach _obstacles; }; //Avoid units. private _Livingobstacles = _predictPos nearObjects ["MAN",(VCM_DrivingDist*2)]; private _Unit = _x; _LivingObstacles deleteAt (_Livingobstacles findIf {_x isEqualTo _Unit}); private _Remove = []; { if !(_x isEqualTo (vehicle _x)) then {_Remove pushback _x;}; if !([(side _Unit),(side _x)] call BIS_fnc_sideIsFriendly) then {_Remove pushback _x;}; } foreach _Livingobstacles; //We do this method to avoid indexing errors. { private _Obj = _x; private _Index = _Livingobstacles findIf {_x isEqualTo _Obj}; _Livingobstacles deleteAt _Index; } foreach _Remove; private _NearestUnit = [_Livingobstacles, _x, true,"Driving"] call VCM_fnc_ClstObj; if (_NearestUnit distance2D _x < 20) then { if (_NearestUnit distance2D _x < 5) then { _Unit forcespeed 0; _Unit spawn { sleep 5; _this forcespeed -1; }; } else { _Unit forcespeed 5; _Unit spawn { sleep 2; _this forcespeed -1; }; }; }; } foreach _this;