Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_AIProcessFailedMovementResult.c
Go to the documentation of this file.
1
3{
4 static const string PORT_MOVE_RESULT = "MoveResult";
5 static const string PORT_HANDLER_ID = "FailedHandlerId";
6 static const string PORT_IS_WAYPOINT_RELATED = "IsWaypointRelated";
7 static const string PORT_MOVE_LOCATION = "MoveLocation";
8
11 protected bool m_bProducedError; // the node will not produce another error unless you run the tree with "always reinit" true
12 protected bool m_bReturnRunning; // when returning running we dont want to produce another errors
13
14 //------------------------------------------------------------------------------------------------
15 override void OnInit(AIAgent owner)
16 {
17 SCR_AIGroup group = SCR_AIGroup.Cast(owner);
18 if (!group)
19 return;
20
21 m_Group = group;
23 }
24
25 //------------------------------------------------------------------------------------------------
26 override void OnEnter(AIAgent owner)
27 {
28 m_bReturnRunning = false;
29 }
30
31 //------------------------------------------------------------------------------------------------
32 override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
33 {
34 int moveResult;
36 return ENodeResult.RUNNING;
37
38 if (!GetVariableIn(PORT_MOVE_RESULT, moveResult))
39 {
40 NodeErrorOnce(owner, "Missing move result for SCR_AIProcessFailedMovementResult node");
41 m_bReturnRunning = true;
42 return ENodeResult.RUNNING;
43 }
44
45#ifdef WORKBENCH
46 PrintDebug(owner, string.Format("Move failed with result %1", SCR_Enum.GetEnumName(EMoveError, moveResult)));
47#endif
48
49
50 int failedHandlerId;
51 GetVariableIn(PORT_HANDLER_ID, failedHandlerId);
52
53 bool isWaypointRelated;
54 GetVariableIn(PORT_IS_WAYPOINT_RELATED, isWaypointRelated);
55
56 vector moveLocation, startLocation;
57 GetVariableIn(PORT_MOVE_LOCATION, moveLocation);
58 if (m_Group)
59 startLocation = m_Group.GetLeaderEntity().GetOrigin(); // safer than obtaining position of the group
60
61 // we failed inside one of our vehicles -> leave the vehicle of the handlerId and try again
62 IEntity vehicleUsed;
63 SCR_AIGroupVehicle groupVehicle;
64 if (failedHandlerId != AIGroupMovementComponent.DEFAULT_HANDLER_ID)
65 {
66 groupVehicle = m_GroupUtilityComponent.m_VehicleMgr.FindVehicleBySubgroupId(failedHandlerId);
67 if (groupVehicle)
68 vehicleUsed = groupVehicle.GetEntity();
69 }
70
71 // Navlink is being negotiated, try again
72 if (moveResult == EMoveError.WAITING_ON_NAVLINK)
73 {
74 return ENodeResult.FAIL;
75 }
76
77 // Ivoke event about failed movement
78 m_GroupUtilityComponent.OnMoveFailed(moveResult, vehicleUsed, isWaypointRelated, moveLocation);
79
80 // Failed movement
81 if (moveResult == EMoveError.UNKNOWN)
82 {
83 if (isWaypointRelated)
84 {
85 SCR_AIActivityBase activity = SCR_AIActivityBase.Cast(m_GroupUtilityComponent.GetCurrentAction());
86
87 // Just fail action if failed move is a result or removed waypoint
88 if (activity && !activity.m_RelatedWaypoint)
89 {
90#ifdef WORKBENCH
91 PrintDebug(owner, string.Format("Failed move from %1 as result of deleted waypoint %2", startLocation, moveLocation));
92#endif
93 FailAction();
94 return ENodeResult.FAIL;
95 }
96
97 // If wp related and wp is the same we just return running
98 // As a result group will be stuck to allow us to debug it
99 NodeErrorOnce(owner, string.Format("Failed move from %1 to waypoint %2", startLocation, moveLocation));
100 m_bReturnRunning = true;
101 return ENodeResult.RUNNING;
102 }
103
104 FailAction();
105#ifdef WORKBENCH
106 PrintDebug(owner, string.Format("Failed move from %1 while following the entity %2", startLocation, moveLocation));
107#endif
108 // If result is not waypoint related we just fail
109 return ENodeResult.FAIL;
110 }
111
112 // If stopped or vehicle is not used, complete waypoint if related and fail action
113 if (moveResult == EMoveError.STOPPED || !vehicleUsed)
114 {
115#ifdef WORKBENCH
116 PrintDebug(owner, string.Format("Move failed with result %1 from %2 to location %3, failing action.", SCR_Enum.GetEnumName(EMoveError, moveResult), startLocation, moveLocation));
117#endif
118 if (isWaypointRelated)
120
121 // Fail action
122 FailAction();
123 m_bReturnRunning = true;
124 return ENodeResult.RUNNING;
125 }
126#ifdef WORKBENCH
127 PrintDebug(owner, string.Format("Move failed with result %1 from %2 to location %3, retrying without vehicle.", SCR_Enum.GetEnumName(EMoveError, moveResult), startLocation, moveLocation));
128#endif
129 // Exit vehicle and try again
130 if (vehicleUsed)
131 {
132 // If failed because the driver is dead, we dont need to leave vehicle
133 if (moveResult != EMoveError.ENTITY_CANT_MOVE)
134 {
135 // higher priority to overwrite conflicting forced move priorities
136 SCR_AIGetOutActivity getOut = new SCR_AIGetOutActivity(m_GroupUtilityComponent, null, vehicleUsed, priority: SCR_AIActionBase.PRIORITY_BEHAVIOR_GET_OUT_VEHICLE_HIGH_PRIORITY, priorityLevel: SCR_AIActionBase.PRIORITY_LEVEL_PLAYER);
137 m_GroupUtilityComponent.AddAction(getOut);
138 }
139
140 // If vehicle got stuck turn the hazard lights on
141 if (moveResult == EMoveError.STUCK)
142 {
143 // Turn them only if there's no enemy around
144 TryTurnOnHazardLightsOnStuck(groupVehicle);
145 }
146 }
147
148 // Fail a node to enable tree to try again
149 return ENodeResult.FAIL;
150 }
151
152 //------------------------------------------------------------------------------------------------
153 protected void TryTurnOnHazardLightsOnStuck(notnull SCR_AIGroupVehicle groupVehicle)
154 {
155 IEntity driver = groupVehicle.GetDriver();
156
157 if (!driver)
158 return;
159
160 bool turnOnLights = m_GroupUtilityComponent && m_GroupUtilityComponent.m_Perception && !m_GroupUtilityComponent.m_Perception.m_MostDangerousCluster;
161 if (!turnOnLights)
162 return;
163
164 // We want to turn on hazard lights
165
166 // Bail if it's forbidden by settings of driver
167 SCR_AICharacterSettingsComponent settingsComp = SCR_AICharacterSettingsComponent.FindOnControlledEntity(driver);
168 if (settingsComp)
169 {
171 if (setting && !setting.IsLightInterractionAllowed())
172 return;
173 }
174
175 SCR_AIVehicleUsability.TurnOnVehicleHazardLights(groupVehicle.GetEntity());
176 }
177
178 //------------------------------------------------------------------------------------------------
179 void PrintDebug(AIAgent owner, string message)
180 {
181#ifdef WORKBENCH
182 if (!DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_AI_PRINT_DEBUG))
183 return;
184
185 Print(string.Format("%1: %2", owner.ToString(), message));
186#endif
187 }
188
189 //------------------------------------------------------------------------------------------------
191 {
192 AIActionBase currentAction = m_GroupUtilityComponent.GetExecutedAction();
193 if (currentAction)
194 currentAction.Fail();
195 }
196
197 //------------------------------------------------------------------------------------------------
199 {
200 if (!m_Group)
201 return;
202 AIWaypoint waypoint = m_Group.GetCurrentWaypoint();
203 if (waypoint)
204 m_Group.CompleteWaypoint(waypoint);
205 }
206
207 //------------------------------------------------------------------------------------------------
208 static override protected bool CanReturnRunning() { return true; }
209
210 //------------------------------------------------------------------------------------------------
211 protected static ref TStringArray s_aVarsOut = {};
213
214 //------------------------------------------------------------------------------------------------
215 protected static ref TStringArray s_aVarsIn = {PORT_MOVE_RESULT, PORT_HANDLER_ID, PORT_IS_WAYPOINT_RELATED, PORT_MOVE_LOCATION};
216 override TStringArray GetVariablesIn() { return s_aVarsIn; }
217
218 //------------------------------------------------------------------------------------------------
219 protected static override string GetOnHoverDescription()
220 {
221 return "Processes failed movement result for proper BT reaction, calls group's failed move invoker";
222 }
223
224 //------------------------------------------------------------------------------------------------
225 protected ENodeResult NodeErrorOnce(AIAgent owner, string errorMessage)
226 {
227 if (!m_bProducedError)
228 NodeError(this, owner, errorMessage);
229 m_bProducedError = true;
230 return ENodeResult.FAIL;
231 }
232}
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ENodeResult NodeError(Node node, AIAgent owner, string msg)
Error call to be used in scripted BT nodes.
Definition NodeError.c:3
void SCR_AIActivityBase(SCR_AIGroupUtilityComponent utility, AIWaypoint relatedWaypoint)
Diagnostic and developer menu system.
Definition DiagMenu.c:18
proto bool GetVariableIn(string name, out void val)
This class is used for keeping track of vehicles assigned to group.
ENodeResult NodeErrorOnce(AIAgent owner, string errorMessage)
void PrintDebug(AIAgent owner, string message)
override ENodeResult EOnTaskSimulate(AIAgent owner, float dt)
void TryTurnOnHazardLightsOnStuck(notnull SCR_AIGroupVehicle groupVehicle)
ENodeResult
Definition ENodeResult.c:13
EMoveError
Definition EMoveError.c:13
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
array< string > TStringArray
Definition Types.c:385