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

349 lines
11 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},{_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;
//(_units select _forEachIndex) moveInDriver _x;
//(_units select _forEachIndex) setSkill 1;
//(_units select _forEachIndex) setUnitRank (_x getVariable ["AIrank","PRIVATE"]);
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;
//(_units select (_forEachIndex + (count _convoyVehicles))) moveInGunner _x;
//(_units select (_forEachIndex + (count _convoyVehicles))) setUnitRank (_x getVariable ["AIrank","PRIVATE"]);
};
}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{sleep 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]};
hint "start";
_group move _endPos;
//{driver _x move _endPos}count _convoyVehicles;
_group setSpeedMode "FULL";//"FULL";
_group setBehaviour "SAFE"; //"CARELESS";
_group setCombatMode "GREEN";
_group setFormation "COLUMN";
/* 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
hint "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;
sleep 10; //Brake the loop for 10 seconds
_group move _endPos;
//_group setSpeedMode "NORMAL";
}else{ //Do vehicle speed management and continue travel to destination
//_group move _endPos;
//{driver _x move _endPos}count _convoyVehicles;
_group setBehaviour "SAFE";
_group setCombatMode "GREEN";
//_group setFormation "COLUMN";//"FILE";
_group setSpeedMode "FULL";
if(time - _lastMoveCheck > 60)then{
_group move _endPos;
_lastMoveCheck = time;
if(_vehiclePos distance _oldPos < 30)then[{
hint "Convoy is stuck";
//FAILSAFE IF CONVOY IS STUCK
{driver _x doMove _endPos}count _convoyVehicles;
//_group setSpeedMode "FULL";
sleep 10; //Brake the loop for 20 seconds
//_group move _endPos;
//_group setSpeedMode "NORMAL";
},{_group move _endPos}];
_oldPos = getPos _mainVehicle;
_group move _endPos;
};
//-- Distance Checks
// forceSpeed = m/s
// limitSpeed = km/h
// 1 km/h == ~0.2777778 m/s
/*
//Check Formation
_distanceA = _veh1 distance _veh2;
_distanceB = _veh1 distance _veh3;
if(_distanceA > _distanceB)then{
_3inFrontOf2 = [_veh2, _veh3, 0] call BIS_fnc_isInFrontOf;
if(_3inFrontOf2 || abs(_distanceA - _distanceB) > 10)then{//Swap Vehicles position in convoy (2 <-> 3)
//diag_log format["A: Distance 1-2: %1 - Distance 1-3: %2", round (_veh1 distance _veh2), round (_veh1 distance _veh3)];
_vehinMiddle = _veh3;
_veh3 = _veh2;
_veh2 = _vehinMiddle;
//diag_log format["B: Distance 1-2: %1 - Distance 1-3: %2", round (_veh1 distance _veh2), round (_veh1 distance _veh3)];
};
};
*/
//Speed Management for Vehicle 1
if(_veh1 distance _veh2 > 80 || _veh1 distance _veh3 > 120)then{
if(_veh1 distance _veh2 > 100 || _veh1 distance _veh3 > 150)then{
//_veh1 forceSpeed (_maxSpd*0.1)*0.2777778;
_veh1 limitSpeed 0;
}else{
if(speed _veh3 < 10)then{
//_veh1 forceSpeed (1 max (speed _veh3)*0.2777778);
_veh1 limitSpeed (1 max (speed _veh3));
}else{
//_veh1 forceSpeed (_maxSpd*0.4)*0.2777778;
_veh1 limitSpeed (_maxSpd*0.5);
};
};
}else{
if(speed _veh3 < 10)then{
//_veh1 forceSpeed (_maxSpd*0.1)*0.2777778;
_veh1 limitSpeed (_maxSpd*0.1);
}else{
//_veh1 forceSpeed (_maxSpd*0.8)*0.2777778; //-- m/s
_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 forceSpeed (_maxSpd*0.8)*0.2777778;
_veh2 limitSpeed (_maxSpd*0.8);
}else{
//Move faster to catch up with Vehicle1
//_veh2 forceSpeed _maxSpd*0.2777778;
_veh2 limitSpeed _maxSpd;
};
}else{
if(_veh2 distance _veh1 < 40)then{
//_veh2 forceSpeed (1 max (speed _veh1)*0.2777778);
_veh2 limitSpeed (1 max (speed _veh1));
}else{
if(_veh2 distance _veh3 > _veh2 distance _veh1)then{ //let Vehicle3 catch up
//_veh2 forceSpeed (_maxSpd*0.5)*0.2777778;
_veh2 limitSpeed (_maxSpd*0.5);
}else{
//_veh2 forceSpeed (_maxSpd*0.8)*0.2777778;
_veh2 limitSpeed (_maxSpd*0.8);
};
};
};
//Speed Management for Vehicle 3
if(_veh3 distance _veh2 > 80 || _veh3 distance _veh1 > 120)then{ //catch up
//_veh3 forceSpeed _maxSpd*0.2777778;
_veh3 limitSpeed _maxSpd;
}else{
if(_veh3 distance _veh2 < 40)then{
//_veh3 forceSpeed (1 max (speed _veh2)*0.2777778);
_veh3 limitSpeed (1 max (speed _veh2));
}else{
//if(speed _veh1 < 10)then{ //FAILSAFE IF CONVOY IS STUCK
// (driver _veh3) doMove (getPos _veh1);
//_veh3 forceSpeed (_maxSpd*0.8)*0.2777778;
// _veh3 limitSpeed (_maxSpd*0.8);
//}else{
//_veh3 forceSpeed (_maxSpd*0.8)*0.2777778;
_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
hint "Dynamic Mission Status: Convoy Ended";
if({alive _x}count units _group > 0 && damage _mainVehicle < 1)then{
_group move _vehiclePos;
sleep 10;
{
if(_x != gunner (vehicle _x))then{
[_x,_vehiclePos] spawn{ private "_unit";
_unit = _this select 0;
doStop _unit;
sleep 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;
};