DayZ 1.27
DayZ Explorer by KGB
 
Загрузка...
Поиск...
Не найдено
HFSMBase.c
См. документацию.
1void fsmDebugPrint (string s)
2{
3#ifdef FSM_DEBUG
4 PrintToRPT("" + s); // comment/uncomment to hide/see debug logs
5#else
6 //Print("" + s); // comment/uncomment to hide/see debug logs
7#endif
8}
9void fsmDebugSpam (string s)
10{
11#ifdef FSM_DEBUG_SPAM
12 PrintToRPT("" + s); // comment/uncomment to hide/see debug logs
13#else
14 //Print("" + s); // comment/uncomment to hide/see debug logs
15#endif
16}
17
18
27class HFSMBase<Class FSMStateBase, Class FSMEventBase, Class FSMActionBase, Class FSMGuardBase>
28{
29 protected ref FSMStateBase m_State;
30 protected FSMStateBase m_OwnerState;
31 protected ref FSMStateBase m_InitialState;
33 protected bool m_HasCompletions = false;
34
35 void HFSMBase (FSMStateBase ownerState = NULL)
36 {
37 m_OwnerState = ownerState;
38 }
39
43 FSMStateBase GetCurrentState ()
44 {
45 return m_State;
46 }
47
51 void SetCurrentState (FSMStateBase state)
52 {
53 if(m_State != state)
54 {
55 m_State = state;
56 }
57 }
58
61 FSMStateBase GetOwnerState ()
62 {
63 return m_OwnerState;
64 }
65
71 bool GetHierarchyPath (FSMStateBase state, out array<FSMStateBase> path)
72 {
73 FSMStateBase curr = state;
74 while (curr)
75 {
76 path.Insert(curr);
77 curr = curr.GetParentState();
78 }
79 return path.Count() > 0;
80 }
81
86 void SetInitialState (FSMStateBase initial_state)
87 {
88 m_InitialState = initial_state;
89 }
90
94 {
95 m_Transitions.Insert(t);
96 //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] +++ ow=" + this.GetOwnerState() + " this=" + this + " t=" + t + " state=" + t.m_srcState + "-------- event=" + t.m_event + "[G=" + t.m_guard +"]/A=" + t.m_action + " --------|> dst=" + t.m_dstState);
97 if (t.m_event == NULL)
98 {
99 Print("Warning (performance): FSM " + this + " has completion transition for src=" + t.m_srcState + " ---NULL----|> dst=" + t.m_dstState);
100 m_HasCompletions = true;
101 }
102 }
103
108 void Start (FSMEventBase initial_event = NULL, bool useExistingState = false)
109 {
111 {
112 fsmDebugPrint("[hfsm] " + this.ToString() + "::Start(" + initial_event.ToString() + "), init_state=" + m_InitialState.ToString());
113 }
114
115 if (!useExistingState)
117
118 m_State.OnEntry(initial_event);
119
122 }
123
126 bool IsRunning () { return m_State != NULL; }
130 void Terminate (FSMEventBase terminal_event = NULL)
131 {
133 {
134 fsmDebugPrint("[hfsm] " + this.ToString() + "::Terminate(" + terminal_event.ToString() + ")");
135 }
136
137 if (IsRunning())
138 {
139 m_State.OnExit(terminal_event);
140 m_State = NULL;
141 }
142 }
143 void Abort (FSMEventBase abort_event = NULL)
144 {
146 {
147 fsmDebugPrint("[hfsm] " + this.ToString() + "::Abort(" + abort_event.ToString() + ")");
148 }
149
150 if (IsRunning())
151 {
152 m_State.OnAbort(abort_event);
153 m_State = NULL;
154 }
155 }
156
159 void Update (float dt)
160 {
161 if (IsRunning())
162 m_State.OnUpdate(dt);
163 }
164
166 {
168 {
169 fsmDebugPrint("[hfsm] (local abort) state=" + t.m_srcState.ToString() + "-------- ABORT event=" + e.ToString() + "[G=" + t.m_guard.ToString() +"]/A=" + t.m_action.ToString() + " --------|> dst=" + t.m_dstState.ToString());
170 }
171
172 m_State.OnAbort(e); // 1) call onAbort on old state
173
174 if (t.m_action)
175 t.m_action.Action(e); // 2) execute transition action (if any)
176
177 auto tmp = t.m_srcState.GetParentState();
178 if (tmp == t.m_dstState.GetParentState())
179 {
180 m_State = t.m_dstState; // 3) change state to new (or NULL)
181
182 if (t.m_dstState != NULL)
183 {
184 m_State.OnEntry(e); // 4a1) call onEntry on new state (see 4a2) )
185 return ProcessEventResult.FSM_OK;
186 }
187 else
188 {
190 {
191 fsmDebugPrint("[hfsm] abort & terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
192 }
193
194 return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
195 }
196 }
197 else
198 {
199 m_State = NULL;
200 return ProcessEventResult.FSM_ABORTED; // 4c) or signal abort to parent (with appropriate transition)
201 }
202 }
203
212 FSMStateBase FindAbortDestinationState (FSMEventBase e)
213 {
215 {
216 if (GetOwnerState())
217 fsmDebugPrint("[hfsm] SUB! " + GetOwnerState().Type().ToString() + "::FindAbortDestinationState(" + e.Type().ToString() + ")");
218 else
219 fsmDebugPrint("[hfsm] root::FindAbortDestinationState(" + e.Type().ToString() + ")");
220 }
221
222 // 1) look in submachine first (if any)
223 if (m_State && m_State.HasFSM())
224 {
226 FSMStateBase abort_dst = a.FindAbortDestinationState(e);
227
228 if (abort_dst)
229 {
230 return abort_dst;
231 }
232 }
233
234 // 2) local transitions
236 if (i == -1)
237 {
239 {
240 fsmDebugPrint("[hfsm] abort event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
241 }
242
243 return NULL;
244 }
245
247 return t.m_dstState;
248 }
249
258 FSMStateBase ProcessAbortEvent(FSMEventBase e, out ProcessEventResult result)
259 {
261 {
262 if (GetOwnerState())
263 fsmDebugPrint("[hfsm] SUB! " + GetOwnerState().Type().ToString() + "::ProcessAbortEvent(" + e.Type().ToString() + ")");
264 else
265 fsmDebugPrint("[hfsm] root::ProcessAbortEvent(" + e.Type().ToString() + ")");
266 }
267
268 // 1) look in submachine first (if any)
269 if (m_State && m_State.HasFSM())
270 {
272 ProcessEventResult subfsm_res;
273 FSMStateBase abort_dst = a.ProcessAbortEvent(e, subfsm_res);
274
275 switch (subfsm_res)
276 {
277 case ProcessEventResult.FSM_OK:
278 {
280 {
281 fsmDebugPrint("[hfsm] event processed by sub machine=" + m_State.ToString());
282 }
283 result = subfsm_res; // 1.1) submachine accepted event
284 return NULL;
285 }
286 case ProcessEventResult.FSM_ABORTED:
287 {
289 {
290 fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString());
291 }
292 m_State.OnAbort(e); // 1.2) submachine aborted, abort submachine owner (i.e. this)
293
294 if (GetOwnerState() == abort_dst.GetParentState())
295 {
297 {
298 fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString() + " & abort destination reached.");
299 }
300 m_State = abort_dst;
301 m_State.OnEntry(e); // 1.3) submachine aborted, call onEntry on new state (cross-hierarchy transition)
302 result = ProcessEventResult.FSM_OK;
303 return NULL;
304 }
305 else
306 {
307 result = ProcessEventResult.FSM_ABORTED; // 1.4) submachine has aborted, look for destination state in parent
308 return NULL;
309 }
310
311 break;
312 }
313 case ProcessEventResult.FSM_TERMINATED:
314 {
315 break; // submachine has finished, look for local transitions from exited submachine
316 }
317 case ProcessEventResult.FSM_NO_TRANSITION:
318 {
320 {
321 fsmDebugPrint("[hfsm] aborted (but no transition) sub machine=" + m_State.ToString());
322 }
323 break; // submachine has no transition, look for transitions in local machine
324 }
325 }
326 }
327
328 // 2) local transitions
330 if (i == -1)
331 {
333 {
334 fsmDebugPrint("[hfsm] abort event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
335 }
336 result = ProcessEventResult.FSM_NO_TRANSITION;
337 return NULL;
338 }
339
342 result = res;
343 switch (res)
344 {
345 case ProcessEventResult.FSM_OK:
346 {
347 //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] abort event processed by machine=" + m_State.ToString());
348 return NULL; // machine accepted event
349 }
350 case ProcessEventResult.FSM_ABORTED:
351 {
353 {
354 fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString() + " will fall-through to dst=" + t.m_dstState);
355 }
356 return t.m_dstState; // store destination state for parent(s)
357 }
358
359 case ProcessEventResult.FSM_TERMINATED:
360 {
362 {
363 fsmDebugPrint("[hfsm] aborted & terminated sub machine=" + m_State.ToString());
364 }
365 break; // submachine has finished, look for local transitions from exited submachine
366 }
367 case ProcessEventResult.FSM_NO_TRANSITION:
368 {
369 break; // submachine has no transition, look for transitions in local machine
370 }
371 }
372 return NULL;
373 }
374
375
384 {
386 {
387 if (GetOwnerState())
388 fsmDebugPrint("[hfsm] SUB!::" + GetOwnerState().Type().ToString() + "::ProcessEvent(" + e.Type().ToString() + ")");
389 else
390 fsmDebugPrint("[hfsm] root::ProcessEvent(" + e.Type().ToString() + " =" + e.DumpToString());
391 }
392
393 // 1) completion transitions have priority (if any)
396
397 // 2) submachine then (if any)
398 if (m_State && m_State.HasFSM())
399 {
400 ProcessEventResult subfsm_res = m_State.ProcessEvent(e);
401
402 switch (subfsm_res)
403 {
404 case ProcessEventResult.FSM_OK:
405 {
406 if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] event processed by sub machine=" + m_State.ToString());
407 return subfsm_res; // submachine accepted event
408 }
409 case ProcessEventResult.FSM_TERMINATED:
410 {
411 break; // submachine has finished, look for local transitions from exited submachine
412 }
413 case ProcessEventResult.FSM_NO_TRANSITION:
414 {
415 break; // submachine has no transition, look for transitions in local machine
416 }
417 }
418 }
419
420 // 3) local transitions
422 if (i == -1)
423 {
425 {
426 fsmDebugPrint("[hfsm] event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
427 }
428 return ProcessEventResult.FSM_NO_TRANSITION;
429 }
430
433 if (row.m_dstState != NULL)
434 {
435 // this is regular transition
436 if (row.m_srcState.GetParentState() == row.m_dstState.GetParentState())
437 res = LocalTransition(i, e); // transition is within this state machine
438 else
439 Error("cross-hierarchy transition or misconfigured transition detected!");
440 //res = HierarchicTransition(i, e); // transition has to cross hierarchy
441 }
442 else
443 {
444 // this is terminating transition
445 if (row.m_srcState.GetParentState() == GetOwnerState())
446 res = LocalTransition(i, e); // terminating transition is within this state machine
447 else
448 Error("cross-hierarchy transition or misconfigured transition detected!");
449 //res = HierarchicTransition(i, e); // source node crosses hierarchy (terminate lies always within this machine)
450 }
451 return res;
452 }
453
454 protected int FindFirstUnguardedTransition (FSMEventBase e)
455 {
456 FSMStateBase curr_state = m_State;
457
458 int count = m_Transitions.Count();
459 for (int i = 0; i < count; ++i)
460 {
462 if ((t.m_srcState == curr_state) && (t.m_event != NULL) && (t.m_event.Type() == e.Type()))
463 {
464 //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] [" + i + "/" + count + "] *** matched! t=" + t + " state=" + t.m_srcState + "-------- event=" + t.m_event + "[G=" + t.m_guard +"]/A=" + t.m_action + " --------|> dst=" + t.m_dstState);
465 bool hasGuard = t.m_guard != NULL;
466 if (!hasGuard || (hasGuard && t.m_guard.GuardCondition(e))) // 1) exec guard (if any)
467 {
468 return i;
469 }
470 }
471 //else if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm][" + i + "/" + count + "] ... matching t=" + t + " state=" + t.m_srcState + "-------- event=" + t.m_event + "[G=" + t.m_guard +"]/A=" + t.m_action + " --------|> dst=" + t.m_dstState);
472 }
473 return -1;
474 }
475
476 FSMStateBase FindTransitionState(FSMStateBase s, FSMEventBase e)
477 {
478 FSMStateBase curr_state = s;
479
480 int count = m_Transitions.Count();
481 for (int i = 0; i < count; ++i)
482 {
484 if ((t.m_srcState == curr_state) && (t.m_event != NULL) && (t.m_event.Type() == e.Type()))
485 {
486 return t.m_dstState;
487 }
488 }
489 return null;
490 }
491
492 FSMStateBase FindGuardedTransitionState(FSMStateBase s, FSMEventBase e)
493 {
494 FSMStateBase curr_state = s;
495
496 int count = m_Transitions.Count();
497 for (int i = 0; i < count; ++i)
498 {
500 if ((t.m_srcState == curr_state) && (t.m_event != NULL) && (t.m_event.Type() == e.Type()))
501 {
502 bool hasGuard = t.m_guard != NULL;
503 if (!hasGuard || (hasGuard && t.m_guard.GuardCondition(e))) // 1) exec guard (if any)
504 {
505 return t.m_dstState;
506 }
507 }
508 }
509 return null;
510 }
511
513 {
514 if (IsRunning())
515 {
516 FSMStateBase curr_state = m_State;
517
518 int count = m_Transitions.Count();
519 for (int i = 0; i < count; ++i)
520 {
522
523 //if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] (local) matching state=" + t.m_srcState + "-------- event=" + t.m_event + "[G=" + t.m_guard +"]/A=" + t.m_action + " --------|> dst=" + t.m_dstState);
524 if ((t.m_srcState.Type() == curr_state.Type()) && (t.m_event == NULL))
525 {
526 bool hasGuard = t.m_guard != NULL;
527 if (!hasGuard || (hasGuard && t.m_guard.GuardCondition(NULL))) // 1) exec guard (if any)
528 {
529 return i;
530 }
531 }
532 }
533 }
534 return -1;
535 }
536
537
545 {
547 {
548 fsmDebugPrint("[hfsm] (local) state=" + t.m_srcState.ToString() + "-------- event=" + e.ToString() + "[G=" + t.m_guard.ToString() +"]/A=" + t.m_action.ToString() + " --------|> dst=" + t.m_dstState.ToString());
549 }
550
551 m_State.OnExit(e); // 1) call onExit on old state
552
553 if (t.m_action)
554 t.m_action.Action(e); // 2) execute transition action (if any)
555
556 m_State = t.m_dstState; // 3) change state to new
557
558 if (t.m_dstState != NULL)
559 {
560 m_State.OnEntry(e); // 4a) call onEntry on new state
561
562 if (GetOwnerState())
563 GetOwnerState().OnSubMachineChanged(t.m_srcState, t.m_dstState); // 5a) notify owner state about change in submachine
564
565 if (m_State)
566 m_State.OnStateChanged(t.m_srcState, t.m_dstState); // 5b) notify current state about change in machine
567
568 return ProcessEventResult.FSM_OK;
569 }
570 else
571 {
573 {
574 fsmDebugPrint("[hfsm] terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
575 }
576
577 if (GetOwnerState())
578 GetOwnerState().OnSubMachineChanged(t.m_srcState, NULL); // 5) notify owner state about change in submachine
579 return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
580 }
581 }
582
594
596 {
597 int completionIdx = FindFirstCompletionTransition();
598 while (completionIdx != -1)
599 {
602 if (row.m_dstState != NULL)
603 {
604 // this is regular completion transition
605 if (row.m_srcState.GetParentState() == row.m_dstState.GetParentState())
606 res = LocalTransition(completionIdx, NULL); // transition is within this state machine
607 else
608 Error("cross-hierarchy transition or misconfigured transition detected!");
609 //res = HierarchicTransition(completionIdx, NULL); // transition has to cross hierarchy
610 }
611 else
612 {
613 // this is terminating completion transition
614 if (row.m_srcState.GetParentState() == GetOwnerState())
615 res = LocalTransition(completionIdx, NULL); // terminating transition is within this state machine
616 else
617 Error("cross-hierarchy transition or misconfigured transition detected!");
618 //res = HierarchicTransition(completionIdx, NULL); // source node crosses hierarchy (terminate lies always within this machine)
619 }
620
621 completionIdx = FindFirstCompletionTransition();
622 }
623 return ProcessEventResult.FSM_NO_TRANSITION;
624 }
625};
626
697
proto string ToString()
ProcessEventResult
Определения FSMBase.c:41
void fsmDebugSpam(string s)
Определения HFSMBase.c:9
void fsmDebugPrint(string s)
Определения HFSMBase.c:1
string Type
Определения JsonDataContaminatedArea.c:11
string path
Определения OptionSelectorMultistate.c:142
Super root of all classes in Enforce script.
Определения EnScript.c:11
represents transition src -— event[guard]/action -—|> dst
ProcessEventResult ProcessEvent(FSMEventBase e)
instructs the hierarchical state machine to process the event e
Определения HFSMBase.c:383
ProcessEventResult ProcessAbortTransition(FSMTransition< FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase > t, FSMEventBase e)
Определения HFSMBase.c:165
ref FSMStateBase m_InitialState
state that owns this fsm (or null if root)
Определения HFSMBase.c:31
void Update(float dt)
if machine running, call OnUpdate() on current state
Определения HFSMBase.c:159
bool IsRunning()
returns true if machine is in running state
Определения HFSMBase.c:126
FSMStateBase FindGuardedTransitionState(FSMStateBase s, FSMEventBase e)
Определения HFSMBase.c:492
FSMStateBase FindTransitionState(FSMStateBase s, FSMEventBase e)
Определения HFSMBase.c:476
void Start(FSMEventBase initial_event=NULL, bool useExistingState=false)
starts the state machine by entering the initial_state (using intial_event as argument to initial sta...
Определения HFSMBase.c:108
ref array< ref FSMTransition< FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase > > m_Transitions
configurable initial state of the machine
Определения HFSMBase.c:32
bool GetHierarchyPath(FSMStateBase state, out array< FSMStateBase > path)
returns hierarchic state (path to root) of a state
Определения HFSMBase.c:71
FSMStateBase ProcessAbortEvent(FSMEventBase e, out ProcessEventResult result)
instructs the hierarchical state machine to process the event e
Определения HFSMBase.c:258
void AddTransition(FSMTransition< FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase > t)
adds transition into transition table
Определения HFSMBase.c:93
ProcessEventResult ProcessLocalTransition(FSMTransition< FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase > t, FSMEventBase e)
instructs the state machine to process the event locally - no hierarchy is crossed
Определения HFSMBase.c:544
void Terminate(FSMEventBase terminal_event=NULL)
terminates the state machine
Определения HFSMBase.c:130
static bool IsWeaponLogEnable()
Определения Debug.c:718
static bool IsInventoryHFSMLogEnable()
Определения Debug.c:668
Определения Debug.c:594
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
void Error(string err)
Messagebox with error message.
Определения EnDebug.c:90
proto void Print(void var)
Prints content of variable to console/log.
proto void PrintToRPT(void var)
Prints content of variable to RPT file (performance warning - each write means fflush!...
static proto string ToString(void var, bool type=false, bool name=false, bool quotes=true)
Return string representation of variable.
bool IsRunning()
Определения tools.c:264