4class WeaponFSM extends HFSMBase<WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase>
6 private static const int MAX_SYNCHRONIZE_ATTEMPTS = 12;
7 private static const int MIN_SYNCHRONIZE_INTERVAL = 3000;
8 private static const int RESET_SYNCHRONIZE_THRESHOLD = 3600000;
9 private int m_SynchronizeAttempts;
10 private int m_LastSynchronizeTime;
12 protected int m_NextStateId = 0;
17 if (state && state.GetInternalStateID() == -1)
19 state.SetInternalStateID(m_NextStateId);
22 m_UniqueStates.Insert(state);
33 super.AddTransition(t);
35 SetInternalID(t.m_srcState);
36 SetInternalID(t.m_dstState);
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());
48 if (t.m_dstState != NULL)
53 GetOwnerState().OnSubMachineChanged(t.m_srcState, t.m_dstState);
56 m_State.OnStateChanged(t.m_srcState, t.m_dstState);
63 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] terminating fsm: state=" + t.m_srcState.ToString() +
" event=" + e.ToString());
66 GetOwnerState().OnSubMachineChanged(t.m_srcState, NULL);
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());
79 auto tmp = t.m_srcState.GetParentState();
80 if (tmp == t.m_dstState.GetParentState())
84 if (t.m_dstState != NULL)
92 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] abort & terminating fsm: state=" + t.m_srcState.ToString() +
" event=" + e.ToString());
112 fsmDebugPrint(
"[hfsm] root::ProcessAbortEvent(" + e.Type().ToString() +
")");
138 if (GetOwnerState() == abort_dst.GetParentState())
171 int i = FindFirstUnguardedTransition(e);
174 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] abort event has no transition: src=" +
m_State.ToString() +
" e=" + e.Type().ToString());
183 i = FindFirstUnguardedTransition(e);
186 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] abort event has no transition: src=" +
m_State.ToString() +
" e=" + e.Type().ToString());
206 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] aborted sub machine=" +
m_State.ToString() +
" will fall-through to dst=" + t.m_dstState);
233 fsmDebugPrint(
"[hfsm] root::ProcessEvent(" + e.Type().ToString() +
" =" + e.DumpToString());
237 if (m_HasCompletions)
238 ProcessCompletionTransitions();
264 int i = FindFirstUnguardedTransition(e);
267 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] event has no transition: src=" +
m_State.ToString() +
" e=" + e.Type().ToString());
275 i = FindFirstUnguardedTransition(e);
278 if (
LogManager.IsInventoryHFSMLogEnable())
fsmDebugPrint(
"[hfsm] event has no transition: src=" +
m_State.ToString() +
" e=" + e.Type().ToString());
285 if (row.m_dstState != NULL)
288 if (row.m_srcState.GetParentState() == row.m_dstState.GetParentState())
289 res = LocalTransition(i, e);
291 Error(
"cross-hierarchy transition or misconfigured transition detected!");
297 if (row.m_srcState.GetParentState() == GetOwnerState())
298 res = LocalTransition(i, e);
300 Error(
"cross-hierarchy transition or misconfigured transition detected!");
312 int state_count = m_UniqueStates.Count();
313 for (
int idx = 0; idx < state_count; ++idx)
315 int state_id = m_UniqueStates.Get(idx).GetInternalStateID();
317 return m_UniqueStates.Get(idx);
331 int count = m_Transitions.Count();
332 for (
int i = 0; i < count; ++i)
336 if (state &&
id == state.GetCurrentStateID())
344 int curr_state_id = -1;
345 if (!ctx.Read(curr_state_id))
347 Error(
"[wpnfsm] LoadCurrentFSMState - cannot read current state");
355 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] synced current state=" + state +
" id=" + curr_state_id); }
361 Error(
"[wpnfsm] LoadCurrentFSMState - cannot find state for id=" + curr_state_id);
371 if (LoadAndSetCurrentFSMState(ctx, version))
373 bool res =
m_State.LoadCurrentFSMState(ctx, version);
374 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugSpam(
"[wpnfsm] LoadCurrentFSMState - loaded current state=" + GetCurrentState()); }
382 if (LoadAndSetCurrentFSMState(ctx, version))
385 int state_count = m_UniqueStates.Count();
386 for (
int idx = 0; idx < state_count; ++idx)
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));
403 int curr_state_id = state.GetInternalStateID();
404 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] SaveCurrentFSMState - saving current state=" + GetCurrentState() +
" id=" + curr_state_id); }
406 if (!ctx.Write(curr_state_id))
408 Error(
"[wpnfsm] SaveCurrentFSMState - cannot save curr_state_id=" + curr_state_id);
413 if (!state.SaveCurrentFSMState(ctx))
415 Error(
"[wpnfsm] SaveCurrentFSMState - cannot save currrent state=" +state);
424 int curr_state_id = state.GetInternalStateID();
425 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] SaveCurrentUnstableFSMState - saving current state=" + GetCurrentState() +
" id=" + curr_state_id); }
427 if (!ctx.Write(curr_state_id))
429 Error(
"[wpnfsm] SaveCurrentFSMState - cannot save curr_state_id=" + curr_state_id);
434 int state_count = m_UniqueStates.Count();
435 for (
int idx = 0; idx < state_count; ++idx)
437 int state_id = m_UniqueStates.Get(idx).GetInternalStateID();
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);
445 Error(
"[wpnfsm] SaveCurrentUnstableFSMState state=" + m_UniqueStates.Get(idx) +
" with unassigned ID!");
455 Internal_ValidateAndRepair();
464 bool repaired =
false;
468 if (state && state.IsRepairEnabled())
473 repaired |= ValidateAndRepairHelper(weapon,
475 state.HasMagazine(), ( weapon.GetMagazine(0) != null ),
476 new WeaponEventAttachMagazine,
new WeaponEventDetachMagazine,
479 repaired |= ValidateAndRepairHelper(weapon,
481 state.IsJammed(), weapon.IsJammed(),
482 new WeaponEventTriggerToJam,
new WeaponEventUnjam,
485 if (weapon.IsJammed())
488 int nMuzzles = weapon.GetMuzzleCount();
493 repaired |= ValidateAndRepairHelper(weapon,
494 "ChamberFiredRepair",
495 state.IsChamberFiredOut(0), weapon.IsChamberFiredOut(0),
496 new WeaponEventTrigger,
new WeaponEventMechanism,
499 repaired |= ValidateAndRepairHelper(weapon,
501 state.IsChamberFull(0), weapon.IsChamberFullEx(0),
502 new WeaponEventLoad1Bullet,
new WeaponEventMechanism,
509 for (
int i = 0; i < nMuzzles; ++i)
511 repaired |= ValidateAndRepairHelper(weapon,
512 "ChamberFiredRepair",
513 state.IsChamberFiredOut(i), weapon.IsChamberFiredOut(i),
517 repaired |= ValidateAndRepairHelper(weapon,
519 state.IsChamberFull(i), weapon.IsChamberFull(i),
535 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] " + weapon.GetDebugName(weapon) +
" ValidateAndRepair - " +
name +
" - " +
m_State +
" - state: " + stateCondition +
" & weapon: " + gunCondition); }
537 if (stateCondition != gunCondition)
545 ErrorEx(
string.Format(
"[wpnfsm] ValidateAndRepair Attempting to repair: %1 - %2 - %3 - state: %4 != weapon: %5",
549 repairedState = ValidateAndRepairStateFinder(gunCondition, e1, e2, state);
556 state = repairedState;
557 weapon.SyncSelectionState(state.HasBullet(), state.HasMagazine());
558 repairedState.SyncAnimState();
566 if (m_SynchronizeAttempts < MAX_SYNCHRONIZE_ATTEMPTS)
568 int currentTime =
g_Game.GetTime();
569 int timeDiff = currentTime - m_LastSynchronizeTime;
572 if (timeDiff > MIN_SYNCHRONIZE_INTERVAL)
576 if (timeDiff > RESET_SYNCHRONIZE_THRESHOLD)
577 m_SynchronizeAttempts = 0;
582 weapon.RandomizeFSMState();
584 weapon.Synchronize();
586 ++m_SynchronizeAttempts;
587 m_LastSynchronizeTime = currentTime;
592 OnFailThresholdBreached(weapon,
name, stateCondition, gunCondition);
606 Error(
string.Format(
"[wpnfsm] %1 ValidateAndRepair THRESHOLD BREACH - %2 - %3 - state: %4 != weapon: %5",
607 weapon.GetDebugName(weapon),
name,
m_State, stateCondition, gunCondition));
616 interState = FindTransitionState(state, e1);
618 interState = FindTransitionState(state, e2);
635 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] OnStoreLoad - loading current state=" + state +
" id=" +
id); }
641 Print(
"[wpnfsm] Warning! OnStoreLoad - cannot load curent weapon state, id=" +
id);
662 return state.GetCurrentStateID();
665 WeaponStateBase abort_dst = FindAbortDestinationState(
new WeaponEventHumanCommandActionAborted(null));
668 if (closest_stable_state)
670 Print(
"[wpnfsm] Save occured in fsm transition! current state=" + GetCurrentState() +
" closes stable state=" + closest_stable_state +
" id=" + closest_stable_state.GetCurrentStateID());
671 return closest_stable_state.GetCurrentStateID();
674 Print(
"[wpnfsm] Warning! Save occured in fsm transition! GetCurrentStateID - cannot find closest weapon stable state.");
686 id = curr.GetInternalStateID();
695 int id = GetCurrentStableStateID();
696 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugSpamALot(
"[wpnfsm] OnStoreSave - saving current state=" + GetCurrentState() +
" id=" +
id); }
711 RandomizeFSMStateEx(muzzleStates, hasMagazine, isJammed);
722 int tc = m_Transitions.Count();
727 if (state && candidates.Find(state) ==
INDEX_NOT_FOUND && state.HasMagazine() == hasMagazine && state.IsJammed() == isJammed)
729 if (state.IsSingleState())
732 candidates.Insert(state);
736 int nMuzzles = muzzleStates.Count();
737 int nMuzzlesState = state.GetMuzzleStateCount();
738 if (nMuzzles != nMuzzlesState)
740 ErrorEx(
string.Format(
"Number of muzzles on the weapon (%1) does not correspond with what state has configured (%2).", nMuzzles, nMuzzlesState));
745 for (
int i = 0; i < nMuzzles; ++i)
747 if (muzzleStates[i] != state.GetMuzzleState(i))
755 candidates.Insert(state);
759 int cc = candidates.Count();
762 int randomIndex =
Math.RandomInt(0, cc);
766 if (!Internal_ValidateAndRepair())
768 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] RandomizeFSMState - randomized current state=" +
m_State +
" id=" + selected.GetCurrentStateID()); }
769 selected.SyncAnimState();
773 if (
LogManager.IsWeaponLogEnable()) {
wpnDebugPrint(
"[wpnfsm] RandomizeFSMState - warning - cannot randomize, no states available"); }
void wpnDebugSpamALot(string s)
void wpnDebugSpam(string s)
void wpnDebugPrint(string s)
PlayerSpawnPresetDiscreteItemSetSlotData name
one set for cargo
represents transition src -— event[guard]/action -—|> dst
bool LoadCurrentUnstableFSMState(ParamsWriteContext ctx, int version)
override WeaponStateBase ProcessAbortEvent(WeaponEventBase e, out ProcessEventResult result)
void RandomizeFSMState(bool hasBullet, bool hasMagazine, bool isJammed)
Deprecated, use RandomizeFSMStateEx for better results.
void OnFailThresholdBreached(Weapon weapon, string name, bool stateCondition, bool gunCondition)
bool LoadAndSetCurrentFSMState(ParamsReadContext ctx, int version)
bool SaveCurrentUnstableFSMState(ParamsWriteContext ctx)
bool SaveCurrentFSMState(ParamsWriteContext ctx)
save current state of fsm
ProcessEventResult ProcessLocalTransition(FSMTransition< WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase > t, WeaponEventBase e)
ProcessEventResult ProcessAbortTransition(FSMTransition< WeaponStateBase, WeaponEventBase, WeaponActionBase, WeaponGuardBase > t, WeaponEventBase e)
bool LoadCurrentFSMState(ParamsReadContext ctx, int version)
load current state of fsm
void SetInternalID(WeaponStateBase state)
unique list of states in this machine (automation of save/load)
bool ValidateAndRepairHelper(Weapon_Base weapon, string name, bool stateCondition, bool gunCondition, WeaponEventBase e1, WeaponEventBase e2, out WeaponStableState state)
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
int GetCurrentStableStateID()
WeaponStableState FindStableStateForID(int id)
load from database - reverse lookup for state from saved id
WeaponStateBase FindStateForInternalID(int id)
retrieve base state that matches given internal id
bool Internal_ValidateAndRepair()
validate the state of the gun and repair if mismatch
WeaponStableState ValidateAndRepairStateFinder(bool condition, WeaponEventBase e1, WeaponEventBase e2, WeaponStableState state)
void OnStoreSave(ParamsWriteContext ctx)
save state of fsm
override ProcessEventResult ProcessEvent(WeaponEventBase e)
void ValidateAndRepair()
validate the state of the gun and repair if mismatch
bool OnStoreLoad(ParamsReadContext ctx, int version)
load state of fsm
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...
base class for hierarchic finite state machine
Serialization general interface. Serializer API works with:
signalize mechanism manipulation
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)
represent weapon state base
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
void Start()
Plays all elements this effects consists of.
const int INDEX_NOT_FOUND
void Error(string err)
Messagebox with error message.
proto void Print(void var)
Prints content of variable to console/log.
void fsmDebugSpam(string s)
void fsmDebugPrint(string s)
enum EObjectTemperatureState m_State
enum FSMTransition WeaponTransition