123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /**@class WeaponStateBase
- * @brief represent weapon state base
- *
- * Class comes with entry/update/abort/exit hooks that can be overriden in custom states
- *
- * Class is ready for hierarchic composition, i.e. this state having a sub-machine running
- * under hood. If no m_fsm member is configured, class acts as ordinary plain
- * finite machine state.
- **/
- class WeaponStateBase
- {
- Weapon_Base m_weapon; /// weapon that this state relates to
- WeaponStateBase m_parentState; /// hierarchical parent state of this state (or null)
- ref WeaponFSM m_fsm; /// nested state machine (or null)
- int m_InternalID = -1; /// internal state id used for load/restore
- void WeaponStateBase (Weapon_Base w = NULL, WeaponStateBase parent = NULL) { m_weapon = w; m_parentState = parent; }
- /**@fn SetParentState
- * @brief allows construction of hierarchical state machine
- **/
- void SetParentState (WeaponStateBase parent) { m_parentState = parent; }
- /**@fn GetParentState
- * @return state that owns this sub-state (or null if plain state)
- **/
- WeaponStateBase GetParentState () { return m_parentState; }
- bool HasFSM () { return m_fsm != NULL; }
- WeaponFSM GetFSM () { return m_fsm; }
- void SetInternalStateID (int i) { m_InternalID = i; }
- int GetInternalStateID () { return m_InternalID; }
- bool SaveCurrentFSMState (ParamsWriteContext ctx)
- {
- if (HasFSM())
- {
- if (IsIdle())
- {
- if (LogManager.IsWeaponLogEnable()) { wpnDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::SaveCurrentFSMState - idle state, skipping other substates"); }
- return m_fsm.SaveCurrentFSMState(ctx);
- }
- else
- {
- // if parent state is !idle (unstable) then save whole machine
- if (LogManager.IsWeaponLogEnable()) { wpnDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::SaveCurrentFSMState - NOT idle state, saving full submachine state"); }
- return m_fsm.SaveCurrentUnstableFSMState(ctx);
- }
- return false;
- }
- return true;
- }
- bool LoadCurrentFSMState (ParamsReadContext ctx, int version)
- {
- if (HasFSM())
- {
- if (IsIdle())
- {
- if (LogManager.IsWeaponLogEnable()) { wpnDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::LoadCurrentFSMState - idle state, skipping other substates"); }
- if (m_fsm.LoadCurrentFSMState(ctx, version))
- return true;
- else
- Error("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::LoadCurrentFSMState - Cannot load stable state for weapon=" + this);
- }
- else
- {
- // if parent state is !idle (unstable) then load whole machine
- if (LogManager.IsWeaponLogEnable()) { wpnDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::LoadCurrentFSMState - NOT idle state, loading full submachine state"); }
- if (m_fsm.LoadCurrentUnstableFSMState(ctx, version))
- return true;
- else
- Error("[wpnfsm] " + Object.GetDebugName(m_weapon) + " WeaponStateBase::LoadCurrentFSMState - Cannot load unstable state for weapon=" + this);
- }
- return false;
- }
- return true;
- }
- bool ProcessEvent (WeaponEventBase e)
- {
- if (HasFSM())
- return m_fsm.ProcessEvent(e);
- return false;
- }
- /**@fn AddTransition
- * @brief adds transition into m_fsm transition table
- **/
- void AddTransition (WeaponTransition t)
- {
- if (HasFSM())
- m_fsm.AddTransition(t);
- else
- Error("[wpnfsm] " + Object.GetDebugName(m_weapon) + " adding transition to state without FSM. Configure FSM first.");
- }
- /**@fn OnEntry
- * @brief called upon entry to state
- * @NOTE if state has (non-running) sub-machine, it's started on entry
- * @param[in] e the event that triggered transition to this state
- **/
- void OnEntry (WeaponEventBase e)
- {
- if (HasFSM() && !m_fsm.IsRunning())
- {
- if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(m_weapon) + " { " + this.Type().ToString() + " Has Sub-FSM! Starting submachine..."); }
- m_fsm.Start(e);
- }
- else
- if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(m_weapon) + " { " + this.Type().ToString()); }
- }
- /**@fn OnUpdate
- * @brief ongoing behavior, performed while being in the state
- *
- * @NOTE: this is supposed to be the Do() operation in UML speak
- **/
- void OnUpdate (float dt)
- {
- if (HasFSM() && m_fsm.IsRunning())
- m_fsm.GetCurrentState().OnUpdate(dt);
- }
- /**@fn OnAbort
- * @brief called when abort signal arrives
- * @param[in] e the event that triggered abort from this state
- **/
- void OnAbort (WeaponEventBase e)
- {
- if (HasFSM() && m_fsm.IsRunning())
- {
- if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(m_weapon) + " OnAbort " + this.Type().ToString() + " Has Sub-FSM! Aborting submachine..."); }
- m_fsm.Abort(e);
- }
- if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(m_weapon) + " } ABORTED " + this.Type().ToString()); }
- }
- /**@fn OnExit
- * @brief called on exit from state
- * @param[in] e the event that triggered transition from this state
- **/
- void OnExit (WeaponEventBase e)
- {
- if (LogManager.IsWeaponLogEnable()) { wpnDebugPrint("[wpnfsm] " + Object.GetDebugName(m_weapon) + " } " + this.Type().ToString()); }
- }
- /**@fn IsWaitingForActionFinish
- * @brief waiting for active animation action/actionType finish
- * @return true if this state or active substate is waiting for finish signal
- **/
- bool IsWaitingForActionFinish () { return HasFSM() && m_fsm.IsRunning() && m_fsm.GetCurrentState().IsWaitingForActionFinish(); }
- /**@fn IsIdle
- * @brief idle state does not expect any animation events
- * @return true if this state is idle
- **/
- bool IsIdle () { return false; }
-
- /**@fn IsBoltOpen
- * @return true if weapon bolt is open
- **/
- bool IsBoltOpen () { return false; }
- /**@fn OnSubMachineChanged
- * @brief called when sub-machine has changed its state
- * @param[in] src from state (previous)
- * @param[in] dst to state (current)
- **/
- void OnSubMachineChanged (WeaponStateBase src, WeaponStateBase dst) { }
- /**@fn OnStateChanged
- * @brief called on current state when state machine has changed its state
- * @param[in] src from state (previous)
- * @param[in] dst to state (current)
- **/
- void OnStateChanged (WeaponStateBase src, WeaponStateBase dst) { }
-
- float GetCoolDown() { return 0; }
- };
|