diff --git a/addons/danger/functions/fnc_brainVehicle.sqf b/addons/danger/functions/fnc_brainVehicle.sqf index 1cd890e8..991a95d1 100644 --- a/addons/danger/functions/fnc_brainVehicle.sqf +++ b/addons/danger/functions/fnc_brainVehicle.sqf @@ -51,7 +51,15 @@ _causeArray params ["_cause", "_dangerPos", "", "_dangerCausedBy"]; // "_dangerU _unit setVariable [QEGVAR(main,FSMDangerCauseData), _causeArray, EGVAR(main,debug_functions)]; // is it an attack? -private _attack = _cause in [DANGER_ENEMYDETECTED, DANGER_ENEMYNEAR, DANGER_HIT, DANGER_CANFIRE, DANGER_BULLETCLOSE] && {(side _dangerCausedBy) isNotEqualTo (side _unit)}; +private _attack = _cause in [DANGER_ENEMYDETECTED, DANGER_ENEMYNEAR, DANGER_HIT, DANGER_CANFIRE, DANGER_BULLETCLOSE] && {(side _dangerCausedBy) isNotEqualTo (side _unit)} && {!isNull _dangerCausedBy}; + +// update dangerPos if attacking. Check that the position is not too far above, or below ground. +if (_attack) then { + private _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]}; +}; // vehicle type ~ Artillery private _artillery = _vehicle getVariable [QEGVAR(main,isArtillery), getNumber (configOf _vehicle >> "artilleryScanner") > 0]; @@ -78,8 +86,8 @@ if (_vehicle isKindOf "Air") exitWith { private _static = _vehicle isKindOf "StaticWeapon"; if (_static) exitWith { - // get out if enemy near - if ((_unit findNearestEnemy _dangerPos) distance _vehicle < (6 + random 15)) then { + // get out if enemy near OR out of ammunition + if ((count (magazines _vehicle)) isEqualTo 0 || {(_vehicle findNearestEnemy _vehicle) distance _vehicle < (6 + random 15)}) then { (units _unit) orderGetIn false; _unit setSuppression 0.94; // to prevent instant laser aim on exiting vehicle }; @@ -122,6 +130,9 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith { private _validTarget = (side _unit) isNotEqualTo (side _dangerCausedBy); private _distance = _vehicle distance _dangerCausedBy; + // 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 { @@ -130,21 +141,6 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith { [_timeout + _delay] + _causeArray }; - // tank assault - if (_attack && {speed _vehicle < 20}) then { - // rotate - [_vehicle, _dangerCausedBy] call EFUNC(main,doVehicleRotate); - - // assault - if (_distance < 750 && {_dangerCausedBy isKindOf "Man"}) then { - [ - {_this call EFUNC(main,doVehicleAssault)}, - [_unit, _dangerPos, _dangerCausedBy], - _delay - 1 - ] call CBA_fnc_waitAndExecute; - }; - }; - // foot infantry support ~ unload private _group = group _vehicle; private _cargo = ((fullCrew [_vehicle, "cargo"]) apply {_x select 0}); @@ -152,23 +148,46 @@ if (_armored && {!isNull _dangerCausedBy}) exitWith { if ( _validTarget && {_cargo isNotEqualTo []} - && {!(terrainIntersectASL [eyePos _vehicle, (eyePos _dangerCausedBy) vectorAdd [0, 0, 3]]) || {_distance < 300}} - && {_unit knowsAbout _dangerCausedBy > 1} - ) then { + && {speed _vehicle < 10} + && {_distance < 350} + && {_unit knowsAbout _dangerCausedBy > 2 || {_distance < 220}} + && {!(terrainIntersectASL [eyePos _vehicle, (eyePos _dangerCausedBy) vectorAdd [0, 0, 2]]) || {_distance < 200}} + ) exitWith { // define enemy direction _group setFormDir (_vehicle getDir _dangerCausedBy); + _cargo doMove _dangerPos; // delayed unload [ { params [["_cargo", []], ["_side", EAST], ["_vehicle", objNull]]; _cargo orderGetIn false; + _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);}; }, [_cargo, side _group, _vehicle], - _delay * 2 + 0.1 ] call CBA_fnc_waitAndExecute; + + // exit + [_timeout + _delay + 1] + _causeArray + }; + + // tank assault + if (_attack && {speed _vehicle < 20}) then { + + // rotate + [_vehicle, _dangerPos] call EFUNC(main,doVehicleRotate); + + // assault + if (_distance < 750 && {_dangerCausedBy isKindOf "Man"}) then { + [ + {_this call EFUNC(main,doVehicleAssault)}, + [_unit, _dangerPos, _dangerCausedBy], + _delay - 1 + ] call CBA_fnc_waitAndExecute; + }; }; // timeout @@ -183,20 +202,19 @@ if (_car) exitWith { private _delay = 0; private _slow = speed _vehicle < 30; - // look to danger - if (!isNull _dangerCausedBy && {_vehicle knowsAbout _dangerCausedBy > 3}) then {_vehicle doWatch ATLtoASL (_vehicle getHideFrom _dangerCausedBy);}; - - // escape - if (_slow && {_vehicle distance _dangerCausedBy < (15 + random 35)}) then { + // escape ~ if enemy within 15-50 meters or explosions are nearby! + if (_slow && {_cause isEqualTo DANGER_EXPLOSION || {_vehicle distanceSqr _dangerCausedBy < (225 + random 1225)}}) exitWith { [_unit] call EFUNC(main,doVehicleJink); - _slow = false; - _delay = 3; + [_timeout + 3] + _causeArray }; + // look to danger + if (_attack && {_vehicle knowsAbout _dangerCausedBy > 3}) then {_vehicle doWatch (AGLtoASL _dangerPos);}; + // suppression if (_attack && {_slow}) then { - [_unit, (_unit getHideFrom _dangerCausedBy) vectorAdd [0, 0, random 1]] call EFUNC(main,doVehicleSuppress); - [{_this call EFUNC(main,doVehicleSuppress)}, [_unit, _dangerPos], 3] call CBA_fnc_waitAndExecute; + [_unit, _dangerPos vectorAdd [0, 0, random 1]] call EFUNC(main,doVehicleSuppress); + [{_this call EFUNC(main,doVehicleSuppress)}, [_unit, _dangerPos vectorAdd [0, 0, random 2]], 3] call CBA_fnc_waitAndExecute; _delay = random 4; }; diff --git a/addons/danger/functions/fnc_tacticsAssess.sqf b/addons/danger/functions/fnc_tacticsAssess.sqf index 6db6870d..d0fabe6e 100644 --- a/addons/danger/functions/fnc_tacticsAssess.sqf +++ b/addons/danger/functions/fnc_tacticsAssess.sqf @@ -33,7 +33,7 @@ private _group = group _unit; // set variable _group setVariable [QGVAR(isExecutingTactic), true]; _group setVariable [QGVAR(contact), time + 600]; -_group enableAttack false; +if (isNull objectParent _unit) then {_group enableAttack false;}; // set current task _unit setVariable [QEGVAR(main,currentTarget), objNull, EGVAR(main,debug_functions)]; diff --git a/addons/danger/functions/fnc_tacticsFlank.sqf b/addons/danger/functions/fnc_tacticsFlank.sqf index 74f70142..4d353571 100644 --- a/addons/danger/functions/fnc_tacticsFlank.sqf +++ b/addons/danger/functions/fnc_tacticsFlank.sqf @@ -108,7 +108,7 @@ _group setFormation "FILE"; { _x setUnitPos "DOWN"; _x setVariable [QGVAR(forceMove), true]; -} foreach _units; +} foreach (_units select {isNull objectParent _x}); // leader smoke ~ deploy concealment to enable movement if (!GVAR(disableAutonomousSmokeGrenades)) then {[_unit, _overwatch] call EFUNC(main,doSmoke);}; diff --git a/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf b/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf index e79b3d90..53e516f0 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupFlank.sqf @@ -46,11 +46,15 @@ private _posASL = AGLtoASL (selectRandom _pos); } foreach _units; // vehicles -{ - private _posAGL = selectRandom _pos; - _x doWatch _posAGL; - [_x, _posAGL] call FUNC(doVehicleSuppress); -} foreach _vehicles; +if (_cycle isEqualTo 1) then { + { + private _posAGL = selectRandom _pos; + _x doWatch _posAGL; + [_x, _posAGL] call FUNC(doVehicleSuppress); + } foreach _vehicles; +} else { + _vehicles doMove _overwatch; +}; // recursive cyclic if !(_cycle <= 1 || {_units isEqualTo []}) then { diff --git a/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf b/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf index 10334fba..4c35cfa9 100644 --- a/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf +++ b/addons/main/functions/GroupAction/fnc_doGroupStaticFind.sqf @@ -35,7 +35,7 @@ if (_units isEqualTo []) exitWith { _units }; // man empty statics private _weapons = nearestObjects [_unit, ["StaticWeapon"], 75, true]; -_weapons = _weapons select { simulationEnabled _x && { !isObjectHidden _x } && { locked _x != 2 } && { (_x emptyPositions "Gunner") > 0 } }; +_weapons = _weapons select { simulationEnabled _x && { !isObjectHidden _x } && { locked _x != 2 } && { (_x emptyPositions "Gunner") > 0 } && { (count magazines _x) > 0 } }; // orders if !((_weapons isEqualTo []) || (_units isEqualTo [])) then { // De Morgan's laws FTW diff --git a/addons/main/functions/UnitAction/fnc_doFleeing.sqf b/addons/main/functions/UnitAction/fnc_doFleeing.sqf index 42300742..00bdae7d 100644 --- a/addons/main/functions/UnitAction/fnc_doFleeing.sqf +++ b/addons/main/functions/UnitAction/fnc_doFleeing.sqf @@ -39,12 +39,13 @@ _unit setVariable [QGVAR(currentTarget), objNull, GVAR(debug_functions)]; [QGVAR(OnFleeing), [_unit, group _unit]] call FUNC(eventCallback); // Abandon vehicles in need! +private _vehicle = vehicle _unit; if ( RND(0.5) && {!_onFoot} - && {canUnloadInCombat (vehicle _unit)} - && {(speed (vehicle _unit)) < 3} - && {isTouchingGround vehicle _unit} + && {canUnloadInCombat _vehicle || {_vehicle isKindOf "StaticWeapon"}} + && {(speed _vehicle) < 3} + && {isTouchingGround _vehicle} ) exitWith { [_unit] orderGetIn false; _unit setSuppression 1; // prevents instant laser aim - nkenny diff --git a/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf b/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf index 7eb5ff03..44c4d267 100644 --- a/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf +++ b/addons/main/functions/VehicleAction/fnc_doVehicleAssault.sqf @@ -46,13 +46,17 @@ if (_buildings isNotEqualTo []) then { }; // add predicted location -- just to ensure shots fired! -if (_buildings isEqualTo []) then {_buildings pushBack _predictedPos;}; +if (_buildings isEqualTo []) then { + _predictedPos = ASLtoAGL (ATLtoASL _predictedPos); + if ((_predictedPos select 2) > 6) then {_predictedPos set [2, 0.5]}; + _buildings pushBack _predictedPos; +}; // pos _pos = selectRandom _buildings; // look at position -_vehicle doWatch _pos; +_vehicle doWatch (AGLtoASL _pos); // suppression private _suppression = [_unit, _pos] call FUNC(doVehicleSuppress); diff --git a/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf b/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf index ac8fc39e..def69989 100644 --- a/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf +++ b/addons/main/functions/VehicleAction/fnc_doVehicleRotate.sqf @@ -23,24 +23,25 @@ params ["_unit", ["_target", []], ["_threshold", 18]]; if (_target isEqualTo []) then { - _target = getPosATL (_unit findNearestEnemy _unit); + _target = _unit getHideFrom (_unit findNearestEnemy _unit); }; +if (_target isEqualTo [0, 0, 0] || {_unit distanceSqr _target < 2}) exitWith {false}; // cannot move or moving -if (!canMove _unit || {currentCommand _unit isEqualTo "MOVE"}) exitWith {true}; +if (!canMove _unit || {currentCommand _unit isEqualTo "MOVE"}) exitWith {false}; -// CQB tweak -- look instead -if (_unit distance _target < 75) exitWith { - (vehicle _unit) doWatch _target; - true +// CQB tweak -- target within 75m - look instead +if (_unit distanceSqr _target < 5625) exitWith { + (vehicle _unit) doWatch (ATLtoASL _target); + false }; _unit setVariable [QGVAR(currentTarget), _target, GVAR(debug_functions)]; _unit setVariable [QGVAR(currentTask), "Vehicle Rotate", GVAR(debug_functions)]; -// within acceptble limits -- suppress instead +// within acceptble limits if (_unit getRelDir _target < _threshold || {_unit getRelDir _target > (360-_threshold)}) exitWith { - true + false }; // settings