botstates.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**@class BotStateBase
  2. * @brief represent weapon state base
  3. *
  4. * Class comes with entry/update/exit hooks that can be overriden in custom states
  5. *
  6. * Class is ready for hierarchic composition, i.e. this state having a sub-machine running
  7. * under hood. If no m_FSM member is configured, class acts as ordinary plain
  8. * finite machine state.
  9. **/
  10. class BotStateBase
  11. {
  12. PlayerBase m_Owner; /// man that this state belongs to
  13. Bot m_Bot; /// bot that this state belongs to
  14. BotStateBase m_ParentState; /// hierarchical parent state of this state (or null)
  15. ref BotFSM m_FSM; /// nested state machine (or null)
  16. void BotStateBase (Bot bot = NULL, BotStateBase parent = NULL) { m_Bot = bot; m_Owner = bot.m_Owner; m_ParentState = parent; }
  17. PlayerBase GetPlayerOwner() { return m_Owner; }
  18. /**@fn SetParentState
  19. * @brief allows construction of hierarchical state machine
  20. **/
  21. void SetParentState (BotStateBase parent) { m_ParentState = parent; }
  22. /**@fn GetParentState
  23. * @return state that owns this sub-state (or null if plain state)
  24. **/
  25. BotStateBase GetParentState () { return m_ParentState; }
  26. bool HasFSM () { return m_FSM != NULL; }
  27. BotFSM GetFSM () { return m_FSM; }
  28. bool ProcessEvent (BotEventBase e)
  29. {
  30. if (HasFSM())
  31. return m_FSM.ProcessEvent(e);
  32. return false;
  33. }
  34. /**@fn AddTransition
  35. * @brief adds transition into m_FSM transition table
  36. **/
  37. void AddTransition (FSMTransition<BotStateBase, BotEventBase, BotActionBase, BotGuardBase> t)
  38. {
  39. if (HasFSM())
  40. m_FSM.AddTransition(t);
  41. else
  42. Error("[botfsm] adding transition to state without FSM. Configure FSM first.");
  43. }
  44. /**@fn OnEntry
  45. * @brief called upon entry to state
  46. * @NOTE if state has (non-running) sub-machine, it's started on entry
  47. * @param[in] e the event that triggered transition to this state
  48. **/
  49. void OnEntry (BotEventBase e)
  50. {
  51. if (HasFSM() && !m_FSM.IsRunning())
  52. {
  53. botDebugPrint("[botfsm] { " + this.Type().ToString() + " Has Sub-FSM! Starting submachine...");
  54. m_FSM.Start(e);
  55. }
  56. else
  57. botDebugPrint("[botfsm] { " + this.Type().ToString());
  58. }
  59. /**@fn OnUpdate
  60. * @brief ongoing behavior, performed while being in the state
  61. *
  62. * @NOTE: this is supposed to be the Do() operation in UML speak
  63. **/
  64. void OnUpdate (float dt)
  65. {
  66. if (HasFSM() && m_FSM.IsRunning())
  67. m_FSM.GetCurrentState().OnUpdate(dt);
  68. }
  69. /**@fn OnAbort
  70. * @brief called when abort signal arrives
  71. * @param[in] e the event that triggered abort from this state
  72. **/
  73. void OnAbort (BotEventBase e)
  74. {
  75. if (HasFSM() && m_FSM.IsRunning())
  76. {
  77. botDebugPrint("[botfsm] OnAbort " + this.Type().ToString() + " Has Sub-FSM! Aborting submachine...");
  78. m_FSM.Abort(e);
  79. }
  80. botDebugPrint("[botfsm] } ABORTED " + this.Type().ToString());
  81. }
  82. /**@fn OnExit
  83. * @brief called on exit from state
  84. * @param[in] e the event that triggered transition from this state
  85. **/
  86. void OnExit (BotEventBase e)
  87. {
  88. botDebugPrint("[botfsm] } " + this.Type().ToString());
  89. }
  90. /**@fn IsWaitingForActionFinish
  91. * @brief waiting for active animation action/actionType finish
  92. * @return true if this state or active substate is waiting for finish signal
  93. **/
  94. bool IsWaitingForActionFinish () { return HasFSM() && m_FSM.IsRunning() && m_FSM.GetCurrentState().IsWaitingForActionFinish(); }
  95. /**@fn IsIdle
  96. * @brief idle state does not expect any animation events
  97. * @return true if this state is idle
  98. **/
  99. bool IsIdle () { return false; }
  100. /**@fn OnSubMachineChanged
  101. * @brief called when sub-machine has changed its state
  102. * @param[in] src from state (previous)
  103. * @param[in] dst to state (current)
  104. **/
  105. void OnSubMachineChanged (BotStateBase src, BotStateBase dst) { }
  106. /**@fn OnStateChanged
  107. * @brief called on current state when state machine has changed its state
  108. * @param[in] src from state (previous)
  109. * @param[in] dst to state (current)
  110. **/
  111. void OnStateChanged (BotStateBase src, BotStateBase dst) { }
  112. };
  113. class BotStateIdle : BotStateBase
  114. {
  115. void BotStateIdle (Bot bot = NULL, BotStateBase parent = NULL) { m_Bot = bot; m_Owner = m_Bot.m_Owner; m_ParentState = parent; }
  116. override bool IsIdle () { return true; }
  117. };