DayZ 1.24
Loading...
Searching...
No Matches
WeaponFSM.c
Go to the documentation of this file.
4class WeaponFSM extends HFSMBase<WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase>
5{
6 private static const int MAX_SYNCHRONIZE_ATTEMPTS = 12;
7 private static const int MIN_SYNCHRONIZE_INTERVAL = 3000; // ms
8 private static const int RESET_SYNCHRONIZE_THRESHOLD = 3600000; // ms
11
12 protected int m_NextStateId = 0;
13 protected ref array<WeaponStateBase> m_UniqueStates = new array<WeaponStateBase>;
14
16 {
17 if (state && state.GetInternalStateID() == -1)
18 {
19 state.SetInternalStateID(m_NextStateId);
20
21 //if (LogManager.IsWeaponLogEnable()) { wpnDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " unique state=" + state + " has id=" + m_NextStateId); }
22 m_UniqueStates.Insert(state);
23 ++m_NextStateId;
24 }
25 }
26
32 {
33 super.AddTransition(t);
34
35 SetInternalID(t.m_srcState);
36 SetInternalID(t.m_dstState);
37 }
38
40 {
41 if (LogManager.IsInventoryHFSMLogEnable()) 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());
42
43 if (t.m_action)
44 t.m_action.Action(e); // 2) execute transition action (if any)
45
46 m_State = t.m_dstState; // 3) change state to new
47
48 if (t.m_dstState != NULL)
49 {
50 m_State.OnEntry(e); // 4a) call onEntry on new state
51
52 if (GetOwnerState())
53 GetOwnerState().OnSubMachineChanged(t.m_srcState, t.m_dstState); // 5a) notify owner state about change in submachine
54
55 if (m_State)
56 m_State.OnStateChanged(t.m_srcState, t.m_dstState); // 5b) notify current state about change in machine
57
58 ValidateAndRepair();
59 return ProcessEventResult.FSM_OK;
60 }
61 else
62 {
63 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
64
65 if (GetOwnerState())
66 GetOwnerState().OnSubMachineChanged(t.m_srcState, NULL); // 5) notify owner state about change in submachine
67 ValidateAndRepair();
68 return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
69 }
70 }
71
73 {
74 if (LogManager.IsInventoryHFSMLogEnable()) 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());
75
76 if (t.m_action)
77 t.m_action.Action(e); // 2) execute transition action (if any)
78
79 auto tmp = t.m_srcState.GetParentState();
80 if (tmp == t.m_dstState.GetParentState())
81 {
82 m_State = t.m_dstState; // 3) change state to new (or NULL)
83
84 if (t.m_dstState != NULL)
85 {
86 m_State.OnEntry(e); // 4a1) call onEntry on new state (see 4a2) )
87 ValidateAndRepair();
88 return ProcessEventResult.FSM_OK;
89 }
90 else
91 {
92 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] abort & terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
93
94 return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
95 }
96 }
97 else
98 {
99 m_State = NULL;
100 ValidateAndRepair();
101 return ProcessEventResult.FSM_ABORTED; // 4c) or signal abort to parent (with appropriate transition)
102 }
103 }
104
106 {
108 {
109 if (GetOwnerState())
110 fsmDebugPrint("[hfsm] SUB! " + GetOwnerState().Type().ToString() + "::ProcessAbortEvent(" + e.Type().ToString() + ")");
111 else
112 fsmDebugPrint("[hfsm] root::ProcessAbortEvent(" + e.Type().ToString() + ")");
113 }
114
115 // 1) look in submachine first (if any)
116 if (m_State && m_State.HasFSM())
117 {
120 WeaponStateBase abort_dst = a.ProcessAbortEvent(e, subfsm_res);
121
122 switch (subfsm_res)
123 {
124 case ProcessEventResult.FSM_OK:
125 {
126 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] event processed by sub machine=" + m_State.ToString());
127
128 result = subfsm_res; // 1.1) submachine accepted event
129 ValidateAndRepair();
130 return NULL;
131 }
132 case ProcessEventResult.FSM_ABORTED:
133 {
134 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString());
135
136 m_State.OnAbort(e); // 1.2) submachine aborted, abort submachine owner (i.e. this)
137
138 if (GetOwnerState() == abort_dst.GetParentState())
139 {
140 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString() + " & abort destination reached.");
141
143 m_State.OnEntry(e); // 1.3) submachine aborted, call onEntry on new state (cross-hierarchy transition)
144 result = ProcessEventResult.FSM_OK;
145 ValidateAndRepair();
146 return NULL;
147 }
148 else
149 {
150 result = ProcessEventResult.FSM_ABORTED; // 1.4) submachine has aborted, look for destination state in parent
151 ValidateAndRepair();
152 return NULL;
153 }
154
155 break;
156 }
157 case ProcessEventResult.FSM_TERMINATED:
158 {
159 break; // submachine has finished, look for local transitions from exited submachine
160 }
161 case ProcessEventResult.FSM_NO_TRANSITION:
162 {
163 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] aborted (but no transition) sub machine=" + m_State.ToString());
164
165 break; // submachine has no transition, look for transitions in local machine
166 }
167 }
168 }
169
170 // 2) local transitions
171 int i = FindFirstUnguardedTransition(e);
172 if (i == -1)
173 {
174 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] abort event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
175
176 result = ProcessEventResult.FSM_NO_TRANSITION;
177 ValidateAndRepair();
178 return NULL;
179 }
180
181 m_State.OnAbort(e);
182
183 i = FindFirstUnguardedTransition(e);
184 if (i == -1)
185 {
186 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] abort event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
187
188 result = ProcessEventResult.FSM_NO_TRANSITION;
189 ValidateAndRepair();
190 return NULL;
191 }
192
194 ProcessEventResult res = ProcessAbortTransition(t, e);
195 result = res;
196 switch (res)
197 {
198 case ProcessEventResult.FSM_OK:
199 {
200 //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] abort event processed by machine=" + m_State.ToString());
201 ValidateAndRepair();
202 return NULL; // machine accepted event
203 }
204 case ProcessEventResult.FSM_ABORTED:
205 {
206 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] aborted sub machine=" + m_State.ToString() + " will fall-through to dst=" + t.m_dstState);
207
208 ValidateAndRepair();
209 return t.m_dstState; // store destination state for parent(s)
210 }
211
212 case ProcessEventResult.FSM_TERMINATED:
213 {
214 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] aborted & terminated sub machine=" + m_State.ToString());
215
216 break; // submachine has finished, look for local transitions from exited submachine
217 }
218 case ProcessEventResult.FSM_NO_TRANSITION:
219 {
220 break; // submachine has no transition, look for transitions in local machine
221 }
222 }
223 return NULL;
224 }
225
227 {
229 {
230 if (GetOwnerState())
231 fsmDebugPrint("[hfsm] SUB!::" + GetOwnerState().Type().ToString() + "::ProcessEvent(" + e.Type().ToString() + ")");
232 else
233 fsmDebugPrint("[hfsm] root::ProcessEvent(" + e.Type().ToString() + " =" + e.DumpToString());
234 }
235
236 // 1) completion transitions have priority (if any)
237 if (m_HasCompletions)
238 ProcessCompletionTransitions();
239
240 // 2) submachine then (if any)
241 if (m_State && m_State.HasFSM())
242 {
243 ProcessEventResult subfsm_res = m_State.ProcessEvent(e);
244
245 switch (subfsm_res)
246 {
247 case ProcessEventResult.FSM_OK:
248 {
249 if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[hfsm] event processed by sub machine=" + m_State.ToString());
250 return subfsm_res; // submachine accepted event
251 }
252 case ProcessEventResult.FSM_TERMINATED:
253 {
254 break; // submachine has finished, look for local transitions from exited submachine
255 }
256 case ProcessEventResult.FSM_NO_TRANSITION:
257 {
258 break; // submachine has no transition, look for transitions in local machine
259 }
260 }
261 }
262
263 // 3) local transitions
264 int i = FindFirstUnguardedTransition(e);
265 if (i == -1)
266 {
267 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
268
269 return ProcessEventResult.FSM_NO_TRANSITION;
270 }
271
272 m_State.OnExit(e);
273
274 // 3.5) find correct transition after handled exit
275 i = FindFirstUnguardedTransition(e);
276 if (i == -1)
277 {
278 if (LogManager.IsInventoryHFSMLogEnable()) fsmDebugPrint("[hfsm] event has no transition: src=" + m_State.ToString() + " e=" + e.Type().ToString());
279
280 return ProcessEventResult.FSM_NO_TRANSITION;
281 }
282
285 if (row.m_dstState != NULL)
286 {
287 // this is regular transition
288 if (row.m_srcState.GetParentState() == row.m_dstState.GetParentState())
289 res = LocalTransition(i, e); // transition is within this state machine
290 else
291 Error("cross-hierarchy transition or misconfigured transition detected!");
292 //res = HierarchicTransition(i, e); // transition has to cross hierarchy
293 }
294 else
295 {
296 // this is terminating transition
297 if (row.m_srcState.GetParentState() == GetOwnerState())
298 res = LocalTransition(i, e); // terminating transition is within this state machine
299 else
300 Error("cross-hierarchy transition or misconfigured transition detected!");
301 //res = HierarchicTransition(i, e); // source node crosses hierarchy (terminate lies always within this machine)
302 }
303 return res;
304 }
305
311 {
312 int state_count = m_UniqueStates.Count();
313 for (int idx = 0; idx < state_count; ++idx)
314 {
315 int state_id = m_UniqueStates.Get(idx).GetInternalStateID();
316 if (state_id == id)
317 return m_UniqueStates.Get(idx);
318 }
319 return null;
320 }
321
327 {
328 if (id == 0)
329 return null;
330
331 int count = m_Transitions.Count();
332 for (int i = 0; i < count; ++i)
333 {
334 WeaponTransition trans = m_Transitions.Get(i);
336 if (state && id == state.GetCurrentStateID())
337 return state;
338 }
339 return null;
340 }
341
343 {
344 int curr_state_id = -1;
345 if (!ctx.Read(curr_state_id))
346 {
347 Error("[wpnfsm] LoadCurrentFSMState - cannot read current state");
348 return false;
349 }
350
351 WeaponStateBase state = FindStateForInternalID(curr_state_id);
352 if (state)
353 {
354 Terminate();
355 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] synced current state=" + state + " id=" + curr_state_id);
356 m_State = state;
357 Start(null, true);
358 return true;
359 }
360 else
361 Error("[wpnfsm] LoadCurrentFSMState - cannot find state for id=" + curr_state_id);
362 return false;
363
364 }
365
370 {
371 if (LoadAndSetCurrentFSMState(ctx, version))
372 {
373 bool res = m_State.LoadCurrentFSMState(ctx, version);
374 if (LogManager.IsWeaponLogEnable()) wpnDebugSpam("[wpnfsm] LoadCurrentFSMState - loaded current state=" + GetCurrentState());
375 return res;
376 }
377 return false;
378 }
379
381 {
382 if (LoadAndSetCurrentFSMState(ctx, version))
383 {
384 // read all substates
385 int state_count = m_UniqueStates.Count();
386 for (int idx = 0; idx < state_count; ++idx)
387 {
388 if (LogManager.IsWeaponLogEnable()) wpnDebugSpam("[wpnfsm] LoadCurrentUnstableFSMState " + idx + "/" + state_count + " id=" + m_UniqueStates.Get(idx).GetInternalStateID() + " state=" + m_UniqueStates.Get(idx));
389 if (!m_UniqueStates.Get(idx).LoadCurrentFSMState(ctx, version))
390 Error("[wpnfsm] LoadCurrentUnstableFSMState - cannot load unique state " + idx + "/" + state_count + " with id=" + m_UniqueStates.Get(idx).GetInternalStateID() + " state=" + m_UniqueStates.Get(idx));
391 }
392 return true;
393 }
394 return false;
395 }
396
401 {
402 WeaponStateBase state = GetCurrentState();
403 int curr_state_id = state.GetInternalStateID();
404 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] SaveCurrentFSMState - saving current state=" + GetCurrentState() + " id=" + curr_state_id);
405
406 if (!ctx.Write(curr_state_id))
407 {
408 Error("[wpnfsm] SaveCurrentFSMState - cannot save curr_state_id=" + curr_state_id);
409 return false;
410 }
411
412 // write only current state
413 if (!state.SaveCurrentFSMState(ctx))
414 {
415 Error("[wpnfsm] SaveCurrentFSMState - cannot save currrent state=" + state);
416 return false;
417 }
418 return true;
419 }
420
422 {
423 WeaponStateBase state = GetCurrentState();
424 int curr_state_id = state.GetInternalStateID();
425 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] SaveCurrentUnstableFSMState - saving current state=" + GetCurrentState() + " id=" + curr_state_id);
426
427 if (!ctx.Write(curr_state_id))
428 {
429 Error("[wpnfsm] SaveCurrentFSMState - cannot save curr_state_id=" + curr_state_id);
430 return false;
431 }
432
433 // write all substates
434 int state_count = m_UniqueStates.Count();
435 for (int idx = 0; idx < state_count; ++idx)
436 {
437 int state_id = m_UniqueStates.Get(idx).GetInternalStateID();
438 if (state_id != -1)
439 {
440 if (LogManager.IsWeaponLogEnable()) wpnDebugSpam("[wpnfsm] SaveCurrentUnstableFSMState " + idx + "/" + state_count + " id=" + state_id + " name=" + m_UniqueStates.Get(idx));
441 if (!m_UniqueStates.Get(idx).SaveCurrentFSMState(ctx))
442 Error("SaveCurrentUnstableFSMState - cannot save unique state=" + m_UniqueStates.Get(idx) + " idx=" + idx + "/" + state_count + " with id=" + state_id);
443 }
444 else
445 Error("[wpnfsm] SaveCurrentUnstableFSMState state=" + m_UniqueStates.Get(idx) + " with unassigned ID!");
446 }
447 return true;
448 }
449
454 {
455 Internal_ValidateAndRepair();
456 }
457
463 {
464 bool repaired = false;
465
466 // Only repair stable states
468 if (state && state.IsRepairEnabled())
469 {
470 Weapon_Base weapon = state.m_weapon;
471 if (weapon)
472 {
473 repaired |= ValidateAndRepairHelper(weapon,
474 "MagazineRepair",
475 state.HasMagazine(), (weapon.GetMagazine(0) != null),
476 new WeaponEventAttachMagazine, new WeaponEventDetachMagazine,
477 state);
478
479 repaired |= ValidateAndRepairHelper(weapon,
480 "JammedRepair",
481 state.IsJammed(), weapon.IsJammed(),
482 new WeaponEventTriggerToJam, new WeaponEventUnjam,
483 state);
484
485 if (weapon.IsJammed())
486 return repaired;
487
488 int nMuzzles = weapon.GetMuzzleCount();
489 switch (nMuzzles)
490 {
491 case 1:
492 {
493 repaired |= ValidateAndRepairHelper(weapon,
494 "ChamberFiredRepair",
495 state.IsChamberFiredOut(0), weapon.IsChamberFiredOut(0),
496 new WeaponEventTrigger, new WeaponEventMechanism,
497 state);
498
499 repaired |= ValidateAndRepairHelper(weapon,
500 "ChamberRepair",
501 state.IsChamberFull(0), weapon.IsChamberFullEx(0),
502 new WeaponEventLoad1Bullet, new WeaponEventMechanism,
503 state);
504
505 break;
506 }
507 default:
508 {
509 for (int i = 0; i < nMuzzles; ++i)
510 {
511 repaired |= ValidateAndRepairHelper(weapon,
512 "ChamberFiredRepair",
513 state.IsChamberFiredOut(i), weapon.IsChamberFiredOut(i),
514 null, null, // A bit brute forced, not really any clean way to transition
515 state);
516
517 repaired |= ValidateAndRepairHelper(weapon,
518 "ChamberRepair",
519 state.IsChamberFull(i), weapon.IsChamberFull(i),
520 null, null, // A bit brute forced, not really any clean way to transition
521 state);
522 }
523
524 break;
525 }
526 }
527 }
528 }
529
530 return repaired;
531 }
532
534 {
535 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] " + weapon.GetDebugName(weapon) + " ValidateAndRepair - " + name + " - " + m_State + " - state: " + stateCondition + " & weapon: " + gunCondition);
536
538 {
540
541 // Seeing this message is not TOO bad, it just means this system is working
542 // It is simply being listed in the logs to identify how much the FSM state and weapon state still desyncs
543 // Which can be because of a myriad of causes, such as incorrectly set up transitions
544 // Or simply certain timings of certain actions or interrupts lined up perfectly, which can have repro rates such as 1/300
545 Error(string.Format("[wpnfsm] ValidateAndRepair Attempting to repair: %1 - %2 - %3 - state: %4 != weapon: %5",
547
548 if (e1 && e2)
549 repairedState = ValidateAndRepairStateFinder(gunCondition, e1, e2, state);
550
551 if (repairedState)
552 {
553 Terminate();
555 Start(null, true);
557 weapon.SyncSelectionState(state.HasBullet(), state.HasMagazine());
558 repairedState.SyncAnimState();
559
560 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] " + weapon.GetDebugName(weapon) + " ValidateAndRepair - " + name + " - Result - " + m_State);
561 return true;
562 }
563 else
564 {
565 // Last ditch effort
566 if (m_SynchronizeAttempts < MAX_SYNCHRONIZE_ATTEMPTS)
567 {
568 int currentTime = g_Game.GetTime();
569 int timeDiff = currentTime - m_LastSynchronizeTime;
570
571 // Careful with calling synchronize
572 if (timeDiff > MIN_SYNCHRONIZE_INTERVAL)
573 {
574 // If a lot of time passed since last attempt
575 // There is a possibility the weapon was fixed for a period
576 if (timeDiff > RESET_SYNCHRONIZE_THRESHOLD)
577 m_SynchronizeAttempts = 0;
578
579 // Only call this on server or in SP
580 // Synchronize will ask the server for its FSM state anyways
581 if (g_Game.IsServer())
582 weapon.RandomizeFSMState();
583
584 weapon.Synchronize();
585
586 ++m_SynchronizeAttempts;
587 m_LastSynchronizeTime = currentTime;
588 }
589 }
590 else
591 OnFailThresholdBreached(weapon, name, stateCondition, gunCondition);
592 }
593 }
594
595 return false;
596 }
597
599 {
600 // Now seeing THIS one, after the one above, THIS one CAN be bad
601 // As the state was identified as being desynced with the actual weapon state
602 // But the system was unable to fix it, so the weapon is now working improperly or not at all
603 // There is even the possibility that this weapon is now permanently broken
604 Error(string.Format("[wpnfsm] %1 ValidateAndRepair THRESHOLD BREACH - %2 - %3 - state: %4 != weapon: %5",
606
607 // At this point might even consider just deleting the weapon :c
608 }
609
611 {
613 if (condition)
614 interState = FindTransitionState(state, e1);
615 else
616 interState = FindTransitionState(state, e2);
617
618 WeaponEventBase e = new WeaponEventHumanCommandActionFinished;
619 return WeaponStableState.Cast(FindGuardedTransitionState(interState, e));
620 }
621
626 {
627 int id = 0;
628 ctx.Read(id);
629 WeaponStableState state = FindStableStateForID(id);
630 if (state)
631 {
632 Terminate();
633 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] OnStoreLoad - loading current state=" + state + " id=" + id);
634 m_State = state;
635 Start(null, true);
636 }
637 else
638 Print("[wpnfsm] Warning! OnStoreLoad - cannot load curent weapon state, id=" + id);
639
640 return true;
641 }
642
654 {
655 // 1) if current state is stable state then return ID directly
656 WeaponStableState state = WeaponStableState.Cast(GetCurrentState());
657 if (state)
658 return state.GetCurrentStateID();
659
660 // 2) otherwise find closest stable state (by looking on abort event)
661 WeaponStateBase abort_dst = FindAbortDestinationState(new WeaponEventHumanCommandActionAborted(null));
663
665 {
666 Print("[wpnfsm] Save occured in fsm transition! current state=" + GetCurrentState() + " closes stable state=" + closest_stable_state + " id=" + closest_stable_state.GetCurrentStateID());
667 return closest_stable_state.GetCurrentStateID();
668 }
669
670 Print("[wpnfsm] Warning! Save occured in fsm transition! GetCurrentStateID - cannot find closest weapon stable state.");
671 return 0;
672 }
673
678 {
679 WeaponStateBase curr = GetCurrentState();
680 int id = 0;
681 if (curr)
682 id = curr.GetInternalStateID();
683 return id;
684 }
685
690 {
691 int id = GetCurrentStableStateID();
692 if (LogManager.IsWeaponLogEnable()) wpnDebugSpamALot("[wpnfsm] OnStoreSave - saving current state=" + GetCurrentState() + " id=" + id);
693 ctx.Write(id);
694 }
695
700 {
702 if (hasBullet)
704 else
706
707 RandomizeFSMStateEx(muzzleStates, hasMagazine, isJammed);
708 }
709
716 {
718 int tc = m_Transitions.Count();
719 foreach (WeaponTransition trans : m_Transitions)
720 {
722 if (state && state.HasMagazine() == hasMagazine && state.IsJammed() == isJammed)
723 {
724 if (state.IsSingleState())
725 {
726 // There is only one, insert it and stop
727 candidates.Insert(state);
728 break;
729 }
730
731 int nMuzzles = muzzleStates.Count();
732 int nMuzzlesState = state.GetMuzzleStateCount();
733 if (nMuzzles != nMuzzlesState)
734 {
735 ErrorEx(string.Format("Number of muzzles on the weapon (%1) does not correspond with what state has configured (%2).", nMuzzles, nMuzzlesState));
736 continue;
737 }
738
739 bool equal = true;
740 for (int i = 0; i < nMuzzles; ++i)
741 {
742 if (muzzleStates[i] != state.GetMuzzleState(i))
743 {
744 equal = false;
745 break;
746 }
747 }
748
749 if (equal)
750 candidates.Insert(state);
751 }
752 }
753
754 int cc = candidates.Count();
755 if (cc)
756 {
757 int randomIndex = Math.RandomInt(0, cc);
759 Terminate();
761 if (!Internal_ValidateAndRepair())
762 Start(null, true);
763 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] RandomizeFSMState - randomized current state=" + m_State + " id=" + selected.GetCurrentStateID());
764 selected.SyncAnimState();
765 }
766 else
767 {
768 if (LogManager.IsWeaponLogEnable()) wpnDebugPrint("[wpnfsm] RandomizeFSMState - warning - cannot randomize, no states available");
769 }
770 }
771};
772
void wpnDebugSpamALot(string s)
Definition Debug.c:25
void wpnDebugSpam(string s)
Definition Debug.c:17
void wpnDebugPrint(string s)
Definition Debug.c:9
PlayerSpawnPresetDiscreteItemSetSlotData name
one set for cargo
DayZGame g_Game
Definition DayZGame.c:3528
void Start()
Plays all elements this effects consists of.
Definition Effect.c:149
proto string ToString()
ProcessEventResult
Definition FSMBase.c:41
void fsmDebugSpam(string s)
Definition HFSMBase.c:9
void fsmDebugPrint(string s)
Definition HFSMBase.c:1
string Type
bool m_State
MuzzleState
bool OnStoreLoad(ParamsReadContext ctx, int version)
load state of fsm
Definition WeaponFSM.c:625
override WeaponStateBase ProcessAbortEvent(WeaponEventBase e, out ProcessEventResult result)
Definition WeaponFSM.c:105
void OnFailThresholdBreached(Weapon weapon, string name, bool stateCondition, bool gunCondition)
Definition WeaponFSM.c:598
void RandomizeFSMStateEx(array< MuzzleState > muzzleStates, bool hasMagazine, bool isJammed)
With the parameters given, selects a random suitable state for the FSM of the weapon @NOTE: It is bet...
Definition WeaponFSM.c:715
override void AddTransition(FSMTransition< WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase > t)
adds transition into transition table As a side effect registers the state(s) into m_UniqueStates
Definition WeaponFSM.c:31
bool Internal_ValidateAndRepair()
validate the state of the gun and repair if mismatch
Definition WeaponFSM.c:462
void RandomizeFSMState(bool hasBullet, bool hasMagazine, bool isJammed)
Deprecated, use RandomizeFSMStateEx for better results.
Definition WeaponFSM.c:699
ProcessEventResult ProcessLocalTransition(FSMTransition< WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase > t, WeaponEventBase e)
Definition WeaponFSM.c:39
bool SaveCurrentFSMState(ParamsWriteContext ctx)
save current state of fsm
Definition WeaponFSM.c:400
ProcessEventResult ProcessAbortTransition(FSMTransition< WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase > t, WeaponEventBase e)
Definition WeaponFSM.c:72
void SetInternalID(WeaponStateBase state)
unique list of states in this machine (automation of save/load)
Definition WeaponFSM.c:15
bool LoadCurrentFSMState(ParamsReadContext ctx, int version)
load current state of fsm
Definition WeaponFSM.c:369
bool ValidateAndRepairHelper(Weapon_Base weapon, string name, bool stateCondition, bool gunCondition, WeaponEventBase e1, WeaponEventBase e2, out WeaponStableState state)
Definition WeaponFSM.c:533
WeaponStableState FindStableStateForID(int id)
load from database - reverse lookup for state from saved id
Definition WeaponFSM.c:326
WeaponStateBase FindStateForInternalID(int id)
retrieve base state that matches given internal id
Definition WeaponFSM.c:310
WeaponStableState ValidateAndRepairStateFinder(bool condition, WeaponEventBase e1, WeaponEventBase e2, WeaponStableState state)
Definition WeaponFSM.c:610
void ValidateAndRepair()
validate the state of the gun and repair if mismatch
Definition WeaponFSM.c:453
base class for hierarchic finite state machine
static bool IsWeaponLogEnable()
Definition Debug.c:799
static bool IsInventoryHFSMLogEnable()
Definition Debug.c:749
Definition EnMath.c:7
Serialization general interface. Serializer API works with:
Definition Serializer.c:56
signalize mechanism manipulation
Definition Events.c:35
weapon finite state machine
script counterpart to engine's class Weapon
represents weapon's stable state (i.e. the basic states that the weapon will spend the most time in)
Definition Crossbow.c:27
represent weapon state base
Definition BulletHide.c:2
string ToString()
Definition EnConvert.c:3
void Error(string err)
Messagebox with error message.
Definition EnDebug.c:90
proto void Print(void var)
Prints content of variable to console/log.
enum ShapeType ErrorEx
static proto int RandomInt(int min, int max)
Returns a random int number between and min [inclusive] and max [exclusive].