Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vehicle brain improvements #432

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 146 additions & 21 deletions addons/danger/functions/fnc_brainVehicle.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* handles vehicle brain
*
* Arguments:
* 0: unit doing the avaluation <OBJECT>
* 0: unit doing the evaluation <OBJECT>
* 2: current action queue <ARRAY>
*
* Return Value:
Expand Down Expand Up @@ -55,7 +55,7 @@ private _attack = _cause in [DANGER_ENEMYDETECTED, DANGER_ENEMYNEAR, DANGER_HIT,

// update dangerPos if attacking. Check that the position is not too far above, or below ground.
if (_attack) then {
private _dangerPos = _unit getHideFrom _dangerCausedBy;
_dangerPos = _unit getHideFrom _dangerCausedBy;
if (_dangerPos isEqualTo [0, 0, 0]) exitWith {_attack = false;};
_dangerPos = ASLToAGL (ATLToASL _dangerPos);
if ((_dangerPos select 2) > 6 || {(_dangerPos select 2) < 2}) then {_dangerPos set [2, 1]};
Expand All @@ -78,6 +78,63 @@ if (_artillery) exitWith {
{
_x setSuppression 0.94; // to prevent instant laser aim on exiting vehicle
} forEach _vehicleCrew; // There may be more than one unit in vehicle
[_unit, "Combat", "Eject", 125] call EFUNC(main,doCallout);
};

// mortars fire rounds
private _mortarTime = _vehicle getVariable [QEGVAR(main,mortarTime), 0];
if (_attack && {_vehicle isKindOf "StaticMortar"} && {unitReady _vehicle} && {_mortarTime < time}) then {

// delay
_timeout = _timeout + 2;
_vehicle doWatch _dangerPos;

// check ammo & range
private _ammo = getArtilleryAmmo [_vehicle];
private _shell = _ammo param [0, ""];
if (_shell isEqualTo "") exitWith {};
private _flareIndex = _ammo findIf {"flare" in (toLower _x)};
private _smokeIndex = _ammo findIf {"smoke" in (toLower _x)};

// check friendlies
private _dangerRound = false;
private _repeatRounds = true;
if ( RND(0.8) || { ([_unit, _dangerPos, 150] call EFUNC(main,findNearbyFriendlies)) isNotEqualTo [] } ) then {
if (_smokeIndex isNotEqualTo -1) then {
_shell = _ammo select _smokeIndex;
_repeatRounds = RND(0.5);
} else {
_dangerRound = true;
};
};

// check night
if ( RND(0.2) && { _unit call EFUNC(main,isNight) } && { _flareIndex isNotEqualTo -1 } ) then {
_dangerPos = _dangerPos getPos [-50 + random 100, (_vehicle getDir _dangerPos) - 45 + random 90];
_shell = _ammo select _flareIndex;
_dangerRound = false;
_repeatRounds = false;
};

// check for issues
if ( _dangerRound || !( _dangerPos inRangeOfArtillery [[_vehicle], _shell] ) ) exitWith {};

// execute fire command
_vehicle commandArtilleryFire [_dangerPos getPos [30 + random 80, (_dangerPos getDir _vehicle) - 10 + random 20], _shell, 1 + random 2];
_vehicle setVariable [QEGVAR(main,mortarTime), time + 24 + random 6];
_unit setVariable [QEGVAR(main,currentTask), "Mortar Fire", EGVAR(main,debug_functions)];
if (_repeatRounds) then {
[
{
params [["_vehicle", objNull], ["_dangerPos", [0, 0, 0]], ["_shell", ""]];
if (canFire _vehicle && unitReady _vehicle) then {
_vehicle commandArtilleryFire [_dangerPos, _shell, ( 2 + random 1 ) min ((gunner _vehicle) ammo (currentMuzzle (gunner _vehicle)))];
};
},
[_vehicle, _dangerPos, _shell],
18 + random 6
] call CBA_fnc_waitAndExecute;
};
};
[_timeout] + _causeArray
};
Expand All @@ -97,6 +154,7 @@ if (_vehicle isKindOf "StaticWeapon") exitWith {
if ((count (magazines _vehicle)) isEqualTo 0 || {(_unit findNearestEnemy _dangerPos) distance _vehicle < (6 + random 15)}) then {
private _vehicleCrew = (crew _vehicle);
_vehicleCrew orderGetIn false;
[_unit, "Combat", "Eject"] call EFUNC(main,doCallout);
{
_x setSuppression 0.94; // to prevent instant laser aim on exiting vehicle
} forEach _vehicleCrew; // There may be more than one unit in vehicle
Expand All @@ -113,7 +171,7 @@ if (_vehicle isKindOf "StaticWeapon") exitWith {
};

// update information
if (_cause isEqualTo DANGER_ENEMYNEAR) then {[_unit, _dangerCausedBy] call EFUNC(main,doShareInformation);};
if (_cause in [DANGER_ENEMYNEAR, DANGER_SCREAM]) then {[_unit, _dangerCausedBy] call EFUNC(main,doShareInformation);};

// select turret ammunition
if (_attack && {!EGVAR(main,disableAutonomousMunitionSwitching) && {!(isNull _dangerCausedBy) && {
Expand Down Expand Up @@ -143,14 +201,6 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith {
// keep cargo aboard!
_vehicle setUnloadInCombat [false, false];

// vehicle jink
private _oldDamage = _vehicle getVariable [QGVAR(vehicleDamage), 0];
if (_validTarget && {_distance < (12 + random 15) || {damage _vehicle > _oldDamage}}) exitWith {
_vehicle setVariable [QGVAR(vehicleDamage), damage _vehicle];
[_unit] call EFUNC(main,doVehicleJink);
[_timeout + _delay] + _causeArray
};

// foot infantry support ~ unload
private _group = group _vehicle;
private _cargo = ((fullCrew [_vehicle, "cargo"]) apply {_x select 0});
Expand Down Expand Up @@ -179,7 +229,8 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith {
[
{
params [["_cargo", []], ["_side", east], ["_vehicle", objNull]];
_cargo orderGetIn false;
{_x action ["Eject", _vehicle];} forEach _cargo;
[selectRandom _cargo, "Combat", "Dismount"] call EFUNC(main,doCallout);
_cargo allowGetIn false;
if (EGVAR(main,debug_functions)) then {["%1 %2 unloading %3 carried troops", _side, getText (configOf _vehicle >> "displayName"), count _cargo] call EFUNC(main,debugLog);};
},
Expand All @@ -191,20 +242,40 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith {
[_timeout + _delay + 1] + _causeArray
};

// move into gunners seat ~ Enemy Detected, commander alive but gunner dead
private _slow = speed _vehicle < 20;
if (
RND(0.4)
&& {_slow}
&& {someAmmo _vehicle}
&& {_cause isEqualTo DANGER_ENEMYDETECTED}
&& {!alive (gunner _vehicle)}
&& {(commander _vehicle) call EFUNC(main,isAlive)}
) exitWith {
(commander _vehicle) assignAsGunner _vehicle;
[_timeout + 3] + _causeArray
};

// vehicle jink
private _oldDamage = _vehicle getVariable [QGVAR(vehicleDamage), 0];
if (_slow && _validTarget && {_distance < (12 + random 15) || {damage _vehicle > _oldDamage}} && {(driver _vehicle) call EFUNC(main,isAlive)}) exitWith {
_vehicle setVariable [QGVAR(vehicleDamage), damage _vehicle];
[_unit] call EFUNC(main,doVehicleJink);
[_timeout + _delay] + _causeArray
};

// tank assault
if (_attack && {speed _vehicle < 20}) then {
if (_attack && {_slow} && {(getUnitState _unit) isEqualTo "OK"}) then {

// rotate
if ((getUnitState _unit) isEqualTo "OK") then {
[_vehicle, _dangerPos] call EFUNC(main,doVehicleRotate);
};
private _rotate = [_vehicle, _dangerPos] call EFUNC(main,doVehicleRotate);

// assault
if (_distance < 750 && {_dangerCausedBy isKindOf "Man"} && {_cause isEqualTo DANGER_ENEMYDETECTED}) then {
if (!_rotate && {_distance < 750} && {_dangerCausedBy isKindOf "CAManBase"} && {(gunner _vehicle) call EFUNC(main,isAlive)}) then {
[
{_this call EFUNC(main,doVehicleAssault)},
[_unit, _dangerPos, _dangerCausedBy],
_delay - 1
_delay - 1.5
] call CBA_fnc_waitAndExecute;
};
};
Expand All @@ -221,14 +292,47 @@ if (_car) exitWith {
private _delay = 0;
private _slow = speed _vehicle < 30;

// move into gunners seat ~ 30-90 meters and Enemy Detected
if (
_slow
&& {canUnloadInCombat _vehicle}
&& {someAmmo _vehicle}
&& {_cause isEqualTo DANGER_ENEMYDETECTED}
&& {_vehicle distanceSqr _dangerPos < (900 + random 3600)}
&& {!alive (gunner _vehicle)}
) exitWith {
_unit action ["Eject", _vehicle];
_unit assignAsGunner _vehicle;
[
{
params ["_unit", "_vehicle"];
if (_unit call EFUNC(main,isAlive)) then {
[_unit, "Stealth", "Eject"] call EFUNC(main,doCallout);
_unit setDir (_unit getDir _vehicle);
_unit action ["getInGunner", _vehicle];
};
}, [_unit, _vehicle], 0.9
] call CBA_fnc_waitAndExecute;
[_timeout + 3] + _causeArray
};

// escape ~ if enemy within 15-50 meters or explosions are nearby!
if (_slow && {(side _dangerCausedBy) isNotEqualTo (side _unit)} && {_cause isEqualTo DANGER_EXPLOSION || {_vehicle distanceSqr _dangerCausedBy < (225 + random 1225)}}) exitWith {
if (
_slow
&& {(side _dangerCausedBy) isNotEqualTo (side _unit)}
&& {_cause isEqualTo DANGER_EXPLOSION || {_vehicle distanceSqr _dangerCausedBy < (225 + random 1225)}}
&& {(driver _vehicle) call EFUNC(main,isAlive)}
) exitWith {
[_unit] call EFUNC(main,doVehicleJink);
[_timeout + 3] + _causeArray
};

// look to danger
if (_attack && {_vehicle knowsAbout _dangerCausedBy > 3}) then {_vehicle doWatch (AGLToASL _dangerPos);};
// look toward danger
if (
_attack
&& {_vehicle knowsAbout _dangerCausedBy > 3}
&& {(gunner _vehicle) call EFUNC(main,isAlive)}
) then {_vehicle doWatch (AGLToASL _dangerPos);};

// suppression
if (_attack && {_slow}) then {
Expand All @@ -241,6 +345,27 @@ if (_car) exitWith {
[_timeout + _delay] + _causeArray
};

// vehicle type ~ Unarmed car
if (_vehicle isKindOf "Car_F" && {!someAmmo _vehicle}) then {

// speed
private _stopped = speed _vehicle < 2;

// is static and a driver and enemy near and a threat - enemy within 10-35 meters
if (
_stopped
&& {!isNull (driver _vehicle)}
&& {canUnloadInCombat _vehicle}
&& {_cause isEqualTo DANGER_ENEMYDETECTED}
&& {_vehicle distanceSqr _dangerCausedBy < (100 + random 225)}
) then {
private _driver = driver _vehicle;
_driver action ["Eject", _vehicle];
_driver setSuppression 0.94; // to prevent instant laser aim on exiting vehicle
[_driver, "Combat", "Eject"] call EFUNC(main,doCallout);
};
};

// Make leadership assessment as infantry
if (_unit call FUNC(isLeader)) then {
[_unit, _dangerCausedBy] call FUNC(tactics);
Expand Down
92 changes: 70 additions & 22 deletions addons/main/functions/UnitAction/fnc_doFleeing.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*
* Public: No
*/
#define SEARCH_FOR_HIDE 6
#define SEARCH_FOR_HIDE 12
#define SEARCH_FOR_BUILDING 8

params ["_unit"];
Expand All @@ -25,7 +25,7 @@ if (
|| {!(_unit checkAIFeature "PATH")}
|| {!(_unit checkAIFeature "MOVE")}
|| {GVAR(disableAIFleeing)}
|| {currentCommand _unit in ["GET IN", "ACTION", "REARM", "HEAL"]}
|| {(currentCommand _unit) in ["GET IN", "ACTION", "REARM", "HEAL"]}
) exitWith {false};

// check for vehicle
Expand All @@ -38,30 +38,70 @@ _unit setVariable [QGVAR(currentTarget), objNull, GVAR(debug_functions)];
// eventhandler
[QGVAR(OnFleeing), [_unit, group _unit]] call FUNC(eventCallback);

// Abandon vehicles in need!
private _vehicle = vehicle _unit;
if (
RND(0.5)
&& {!_onFoot}
&& {morale _unit < 0}
&& {canUnloadInCombat _vehicle || {_vehicle isKindOf "StaticWeapon"}}
&& {(speed _vehicle) < 3}
&& {isTouchingGround _vehicle}
) exitWith {
[_unit] orderGetIn false;
_unit setSuppression 1; // prevents instant laser aim - nkenny

// Vehicle sub-actions
if (!_onFoot) exitWith {

// get vehicle
private _vehicle = vehicle _unit;
private _changeSeats = (speed _vehicle) < 3 && { isTouchingGround _vehicle };

// move into gunners seat ~ Enemy Detected, commander alive but gunner dead
private _candidate = call {
if ((commander _vehicle) call EFUNC(main,isAlive)) exitWith {commander _vehicle};
if ((driver _vehicle) call EFUNC(main,isAlive)) exitWith {driver _vehicle};
objNull
};

if (
_changeSeats
&& {!isNull _candidate}
&& {someAmmo _vehicle}
&& {!((gunner _vehicle) call EFUNC(main,isAlive))}
) exitWith {
if (_vehicle isKindOf "Tank") then {
_candidate assignAsGunner _vehicle;
} else {
_candidate action ["Eject", _vehicle];
_candidate assignAsGunner _vehicle;
[
{
params ["_unit", "_vehicle"];
if (_unit call EFUNC(main,isAlive)) then {
_unit setDir (_unit getDir _vehicle);
_unit action ["getInGunner", _vehicle];
};
}, [_candidate, _vehicle], 0.8
] call CBA_fnc_waitAndExecute;
};
false
};

// Abandon vehicles in need!
private _abandonChance = ( (1 - damage _vehicle) + (_unit skillFinal "courage") ) * 0.5;
if (!canMove _vehicle || {fuel _vehicle < 0.1} || {_vehicle isKindOf "StaticWeapon"}) then { _abandonChance = _abandonChance * 0.25 };
if (someAmmo _vehicle) then { _abandonChance = _abandonChance * 1.3 };
if (
RND(_abandonChance)
&& {canUnloadInCombat _vehicle || (damage _vehicle) > 0.9}
&& {_changeSeats}
) exitWith {
if (_abandonChance < 0.5) then {_unit leaveVehicle _vehicle;};
[_unit] orderGetIn false;
_unit setSuppression 1; // prevents instant laser aim - nkenny
false
};

// exit
false
};

// no further action in vehicle
if (!_onFoot) exitWith {false};

// enemy
private _enemy = _unit findNearestEnemy _unit;
private _distance2D = _unit distance2D _enemy;

// get destination
private _pos = (expectedDestination _unit) select 0;
private _eyePos = eyePos _unit;
private _suppression = getSuppression _unit;

Expand Down Expand Up @@ -94,11 +134,18 @@ if (_onFootAndSeen) then {
_unit forceSpeed -1;
_unit setUnitPos (["MIDDLE", "DOWN"] select (_suppression > 0 || {_cover isNotEqualTo []})); // test nkenny

// update cover
_cover = _cover apply {_x getPos [1.5, _enemy getDir _x]};

// find buildings to hide
private _buildings = [_unit, SEARCH_FOR_BUILDING, true, true] call FUNC(findBuildings);
_buildings append (_cover apply {getPos _x});
if ((_buildings isNotEqualTo []) && {_distance2D > 5}) then {
_unit doMove selectRandom _buildings;
if (_distance2D > 30) then {
private _buildings = [_unit, SEARCH_FOR_BUILDING, true, true] call FUNC(findBuildings);
_cover append _buildings;
};

// execute move
if (_cover isNotEqualTo [] && {_distance2D > 5}) then {
_unit doMove selectRandom _cover;
};

} else {
Expand All @@ -107,6 +154,7 @@ if (_onFootAndSeen) then {

// reset
_unit setUnitPos "AUTO";
_unit setUnitPosWeak "MIDDLE";
};

// debug
Expand All @@ -115,7 +163,7 @@ if (GVAR(debug_functions)) then {
"%1 Fleeing! %2 (%3m %4%5%6)",
side _unit,
name _unit,
[format ["Enemy @ %1", round _distance2D], format ["Destination @ %1", round (_unit distance2D _pos)]] select (isNull _enemy),
[format ["Enemy @ %1", round _distance2D], format ["Destination @ %1", round (_unit distance2D ((expectedDestination _unit) select 0))]] select (isNull _enemy),
["", "- suppressed "] select (_suppression > 0),
["", "- inside "] select (lineIntersects [_eyePos, _eyePos vectorAdd [0, 0, 10], _unit]),
["", "- spotted "] select (([objNull, "VIEW", objNull] checkVisibility [_eyePos, eyePos _enemy]) > 0.01)
Expand Down
Loading
Loading