-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathfnc_doFleeing.sqf
More file actions
174 lines (145 loc) · 5.6 KB
/
fnc_doFleeing.sqf
File metadata and controls
174 lines (145 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "script_component.hpp"
/*
* Author: nkenny
* Adds debug and unique behaviour on unit fleeing
*
* Arguments:
* 0: unit fleeing <OBJECT>
*
* Return Value:
* boolean
*
* Example:
* [bob] call lambs_main_fnc_fleeing;
*
* Public: No
*/
#define SEARCH_FOR_HIDE 12
#define SEARCH_FOR_BUILDING 8
params ["_unit"];
// check disabled
if (
_unit getVariable [QEGVAR(danger,disableAI), false]
|| {!(_unit checkAIFeature "PATH")}
|| {!(_unit checkAIFeature "MOVE")}
|| {GVAR(disableAIFleeing)}
|| {(currentCommand _unit) in ["GET IN", "ACTION", "REARM", "HEAL"]}
) exitWith {false};
// check for vehicle
private _onFoot = isNull (objectParent _unit);
// variable
_unit setVariable [QGVAR(currentTask), ["Fleeing (vehicle)", "Fleeing"] select _onFoot, GVAR(debug_functions)];
_unit setVariable [QGVAR(currentTarget), objNull, GVAR(debug_functions)];
// eventhandler
[QGVAR(OnFleeing), [_unit, group _unit]] call FUNC(eventCallback);
// 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
};
// enemy
private _enemy = _unit findNearestEnemy _unit;
private _distance2D = _unit distance2D _enemy;
// get destination
private _eyePos = eyePos _unit;
private _suppression = getSuppression _unit;
// on foot and seen by enemy
private _onFootAndSeen = _distance2D < 75 || {_suppression > 0.9} || {([objNull, "VIEW", objNull] checkVisibility [_eyePos, eyePos _enemy]) > 0.01};
if (_onFootAndSeen) then {
// variable
_unit setVariable [QGVAR(currentTask), "Fleeing (enemy near)", GVAR(debug_functions)];
_unit setVariable [QGVAR(currentTarget), _enemy, GVAR(debug_functions)];
// ACE3 ~ prevents stopping to heal!
_unit setVariable ["ace_medical_ai_lastFired", CBA_missionTime];
// callout
if (RND(0.4) && {_suppression > 0.5}) then {
[_unit, "Stealth", "panic", 55] call FUNC(doCallout);
};
// calm and inside or under cover!
if ((_suppression < 0.2) && {lineIntersects [_eyePos, _eyePos vectorAdd [0, 0, 10], _unit] || {_distance2D < 15}}) exitWith {
_unit setUnitPos "DOWN";// ~ this forces unit stance which may override mission maker. The effect is good however - nkenny
doStop _unit;
};
// find nearby cover
private _cover = nearestTerrainObjects [_unit, ["BUSH", "TREE", "HIDE", "ROCK", "WALL", "FENCE"], SEARCH_FOR_HIDE, false, true];
// speed and stance (based on cover)
_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
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 {
// follow self! ~ bugfix which prevents units from getting stuck in fleeing loop inside fsm. - nkenny
_unit doFollow (leader _unit);
// reset
_unit setUnitPos "AUTO";
_unit setUnitPosWeak "MIDDLE";
};
// debug
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 ((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)
] call FUNC(debugLog);
};
// end
true