SEM/sem/scripts/ai/fn_AIconvoy.sqf
2017-03-27 15:32:07 +02:00

323 lines
8.5 KiB
Plaintext

/* KiloSwiss */
private["_group","_endPos","_missionID","_mainVehicle","_convoyVehicles","_enterableVehicles","_convoyGrps","_ranks","_side","_vehiclePos","_vehFrontPos","_veh1","_veh2","_veh3","_start"];
_group = _this select 0;
_endPos = _this select 1;
_missionID = _this select 2;
_mainVehicle = _this select 3;
_convoyVehicles = _this select 4;
_enterableVehicles = _this select 5;
/* Marker position update */
_this spawn { private["_endPos","_missionID","_mainVehicle","_oldPos","_newPos"];
_endPos = _this select 1;
_missionID = _this select 2;
_mainVehicle = _this select 3;
_oldPos = position _mainVehicle;
while{alive _mainVehicle && _mainVehicle distance _endPos > 50}do{
UIsleep 10;
_newPos = position _mainVehicle;
if(_oldPos distance _newPos > 10)then{
_oldPos = _newPos;
SEM_updateMissionMarkerPos = [_missionID, _newPos];
SEM_updateMissionMarkerPos call SEM_client_updateMissionMarkerPos;
};
};
};
_units = (units _group);
_side = side (_units select 0);
_startPos = getPos _mainVehicle;
_vehFront = (if(count _convoyVehicles == 1)then[{_mainVehicle},{{if(_x != _mainVehicle)exitWith{_x}; (_convoyVehicles select 0)}count _convoyVehicles}]);
{
_x setVariable ["AIskill",(skill _x)]
} count _units;
_ranks = ["COLONEL","MAJOR","CAPTAIN","LIEUTENANT","SERGEANT","CORPORAL","PRIVATE"];
{
_x setFuel 1;
_x setDamage 0;
_group addVehicle _x;
if (_x in _enterableVehicles) then {
_x lock 0
}
else {
_x lock 3
};
_x setVariable ["AIrank", (_ranks select (_forEachIndex min (count _ranks -1)))];
_x addEventHandler ["getIn",{
(_this select 2) setUnitRank ((_this select 0) getVariable ["AIrank","PRIVATE"]);
if((_this select 1) == "driver")then{
(_this select 2) setSkill 1;
};
}];
_x addEventHandler ["getOut",{
(_this select 2) setSkill ((_this select 2) getVariable ["AIskill",0.7]);
}];
_x addeventHandler ["handleDamage",{
if(isNull (_this select 3))then{false};
}];
// Fill driver seats first
(_units select _forEachIndex) assignAsDriver _x;
if(_x emptyPositions "GUNNER" > 0)then{ // Assign a gunner
_x allowCrewInImmobile true; //allow gunner to stay in immobilized vehicle
(_units select (_forEachIndex + (count _convoyVehicles))) assignAsGunner _x;
};
}forEach _convoyVehicles;
//Order all Units to get in
_units allowGetIn true;
_units orderGetIn true;
//Wait until every unit has boarded a vehicle
_start = time;
waitUntil {
uisleep 1;
{
(alive _x && vehicle _x == _x)
} count _units == 0 || time - _start >= 30
};
if({alive _x && vehicle _x == _x}count _units > 0)then{
{ /* Move stuck AI into vehicles */
if(vehicle _x == _x)then{
_y = _x;
{ /* Fill driver/gunner seats first */
if(_x emptyPositions "DRIVER" > 0)exitWith{_y moveInDriver _x; _y setSkill 1};
if(_x emptyPositions "GUNNER" > 0)exitWith{_y moveInGunner _x};
}forEach _convoyVehicles;
{ /* Fill cargo seats */
if(_x emptyPositions "CARGO" > 0)exitWith{_y moveInCargo _x};
}forEach (_convoyVehicles - [_mainVehicle]);
};
_x setUnitRank ((vehicle _x) getVariable ["AIrank","PRIVATE"]);
}forEach _units;
};
//-- Get lowest TopSpeed from all vehicles
_topSpeeds = [];
{
_maxSpd = getNumber (configFile >> "cfgVehicles" >> typeOf _x >> "maxSpeed");
if(!isNil "_maxSpd")then{_topSpeeds pushBack _maxSpd};
}forEach _convoyVehicles;
_select = 0;
_maxSpd = _topSpeeds select _select;
while{{_maxSpd > _x}count _topSpeeds != 0}do{
_select = _select + 1;
_maxSpd = _topSpeeds select _select;
};
{_x forceSpeed (_maxSpd*0.8)*0.2777778}forEach _convoyVehicles; // m/s
//DEBUG
if(SEM_debug in ["log","full"])then{diag_log format["SEM DEBUG: Convoy Vehicles TopSpeeds: %1 - Selected lowest: %2", _topSpeeds, _maxSpd]};
//_group move _endPos;
{driver _x move _endPos}count _convoyVehicles;
_group setSpeedMode "FULL";//"FULL";
_group setBehaviour "SAFE"; //"CARELESS";
_group setCombatMode "GREEN";
_group setFormation "COLUMN";
uisleep 30;
/* temporary definition of 3 vehicles */
_veh1 = _convoyVehicles select 0;
_veh2 = _convoyVehicles select 1;
_veh3 = _convoyVehicles select 2;
_lastMoveCheck = time;
_oldPos = getPos _mainVehicle;
/* Convoy loop */
_stayToDefend = true;
while{{_x distance _endPos < 20}count _convoyVehicles < 1}do{ //CONVOY LOOP
_vehiclePos = getPos _mainVehicle;
_vehFrontPos = getPos _vehFront;
if({!canMove _x}count _convoyVehicles > 0 && _stayToDefend)then{
{if(canMove _x)then{(driver _x) doMove _vehiclePos}}forEach _convoyVehicles;
sleep 5;
{
if(_x distance _vehiclePos < 50)then[{
if(_x != gunner (vehicle _x))then{
_x action ["GetOut", (vehicle _x)];
sleep 0.5;
[_x] orderGetIn false;
[_x] allowGetIn false;
_x doMove _vehiclePos;
};
},{
_x doMove _vehiclePos;
}];
}forEach units _group;
_group move _vehiclePos;
_group setSpeedMode "FULL";
if({_x distance _veh2 < 50}count units _group == count units _group)then{
_endPos = _vehiclePos;
};
}
else{
//-- Work In Progress!
if({alive _x && !(vehicle _x in _convoyVehicles)}count units _group > 0)then{ //AI has left the vehicle
_group setBehaviour "CARELESS";
_group setCombatMode "GREEN";
{
if(!(vehicle _x in _convoyVehicles))then{
[_x] allowGetIn true;
[_x] orderGetIn true;
};
}forEach units _group;
uisleep 10; //Brake the loop for 10 seconds
_group move _endPos;
}
else{ //Do vehicle speed management and continue travel to destination
_group setBehaviour "SAFE";
_group setCombatMode "GREEN";
_group setSpeedMode "FULL";
if(time - _lastMoveCheck > 60)then{
_group move _endPos;
_lastMoveCheck = time;
if(_vehiclePos distance _oldPos < 30)then {
//FAILSAFE IF CONVOY IS STUCK
{
driver _x doMove _endPos
} count _convoyVehicles;
sleep 20;
if(_vehiclePos distance _oldPos < 10)then{
_endPos = _vehiclePos;
};
}
else {
_group move _endPos
};
_oldPos = getPos _mainVehicle;
_group move _endPos;
};
//Speed Management for Vehicle 1
if(_veh1 distance _veh2 > 80 || _veh1 distance _veh3 > 120)then{
if(_veh1 distance _veh2 > 90 || _veh1 distance _veh3 > 130)then{
_veh1 limitSpeed 0;
}else{
if(speed _veh3 < 10)then{
_veh1 limitSpeed (1 max (speed _veh3));
}else{
_veh1 limitSpeed (_maxSpd*0.4);
};
};
}else{
if(speed _veh3 < 10)then{
_veh1 limitSpeed (_maxSpd*0.1);
}else{
_veh1 limitSpeed (_maxSpd*0.8);
};
};
//Speed Management for Vehicle 2
if(_veh2 distance _veh1 > 80)then{
if(_veh2 distance _veh3 < _veh2 distance _veh1)then{
_veh2 limitSpeed (_maxSpd*0.8);
}
else{
_veh2 limitSpeed _maxSpd;
};
}else{
if(_veh2 distance _veh1 < 50)then{
_veh2 limitSpeed (1 max (speed _veh1));
}
else{
if(_veh2 distance _veh3 > _veh2 distance _veh1)then{
_veh2 limitSpeed (_maxSpd*0.5);
}
else{
_veh2 limitSpeed (_maxSpd*0.8);
};
};
};
//Speed Management for Vehicle 3
if(_veh3 distance _veh2 > 80 || _veh3 distance _veh1 > 150)then{
if(_veh3 distance _veh2 < 40)then{
_veh3 limitSpeed (1 max (speed _veh2));
}else{
_veh3 limitSpeed _maxSpd;
};
}else{
if(_veh3 distance _veh2 < 40)then{
_veh3 limitSpeed (1 max (speed _veh2));
}
else{
_veh3 limitSpeed (_maxSpd*0.8);
};
};
};
};
//code to end the while
_unitsAlive = ({alive _x}count units _group);
if(_unitsAlive < 1) then {
_endPos = _vehiclePos;
};
if (damage _mainVehicle == 1) then {
_endPos = _vehiclePos;
};
if({isPlayer _x && alive _x}count crew _mainVehicle > 0)then{
doStop (units _group);
{
_x spawn{
_this action ["engineOff", (vehicle _this)];
sleep 0.5;
deleteVehicle _this;
};
}foreach units _group;
_endPos = _vehiclePos;
};
uisleep 1;
};
//END OF LOOP
if ({alive _x}count units _group > 0 && damage _mainVehicle < 1) then {
_group move _vehiclePos;
uisleep 10;
{
if(_x != gunner (vehicle _x))then{
[_x,_vehiclePos] spawn{
private "_unit";
_unit = _this select 0;
doStop _unit;
uisleep 1;
_unit action ["engineOff", (vehicle _unit)];
_unit action ["GetOut", (vehicle _unit)];
unassignVehicle _unit;
sleep 0.1;
[_unit] orderGetIn false;
[_unit] allowGetIn false;
};
};
} forEach (units _group);
_group move _vehiclePos;
_group setBehaviour "AWARE";
_group setFormation "FILE";
_group setCombatMode "YELLOW";
[_group, _vehiclePos] call SEM_fnc_AImove;
};