weaponstablestate.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /**@class WeaponStableState
  2. * @brief represents weapon's stable state (i.e. the basic states that the weapon will spend the most time in)
  3. *
  4. * Stable states have associated animation states that they supposed to be in.
  5. * If they are not, the SetWeaponAnimState is called on the weapon in order to
  6. * set to required (configured) state
  7. *
  8. * @NOTE: OnExit from stable state, the weapon's animation state (@see
  9. * Weapon_Base::m_weaponAnimState) is set to -1 (unknown) In case of action
  10. * abort the final stable state is forced to set proper animation state
  11. * according to configuration (@see m_animState)
  12. **/
  13. enum MuzzleState
  14. {
  15. //! UNKNOWN
  16. U = -1,
  17. //! EMPTY
  18. E = 0,
  19. //! FIRED
  20. F = 1,
  21. //! LOADED
  22. L = 2
  23. }
  24. class WeaponStableState extends WeaponStateBase
  25. {
  26. int m_animState;
  27. ref array<MuzzleState> m_muzzleHasBullet = new array<MuzzleState>();
  28. void WeaponStableState(Weapon_Base w = NULL, WeaponStateBase parent = NULL, int anim_state = -1)
  29. {
  30. m_animState = anim_state;
  31. InitMuzzleArray();
  32. ValidateMuzzleArray();
  33. }
  34. void SyncAnimState()
  35. {
  36. int curr = m_weapon.GetWeaponAnimState();
  37. if (curr != m_animState)
  38. {
  39. //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " synchronizing anim state: " + curr + " --> " + m_animState);
  40. PlayerBase p;
  41. if (Class.CastTo(p, m_weapon.GetHierarchyParent()))
  42. {
  43. if (p.GetItemInHands() == m_weapon)
  44. {
  45. HumanCommandWeapons hcw = p.GetCommandModifier_Weapons();
  46. if (hcw)
  47. {
  48. hcw.SetInitState(m_animState);
  49. if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " state=" + m_weapon.GetCurrentState().Type() + " synchronized anim state: " + typename.EnumToString(PistolAnimState, curr) + " --> " + typename.EnumToString(PistolAnimState, m_animState));
  50. }
  51. else
  52. {
  53. Human wpnOwner = Human.Cast(m_weapon.GetHierarchyRootPlayer());
  54. HumanCommandWeapons.StaticSetInitState(wpnOwner, m_animState);
  55. if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " state=" + m_weapon.GetCurrentState().Type() + " synchronized remote anim state: " + typename.EnumToString(PistolAnimState, curr) + " --> " + typename.EnumToString(PistolAnimState, m_animState));
  56. }
  57. }
  58. m_weapon.SetWeaponAnimState(m_animState);
  59. }
  60. else
  61. {
  62. m_weapon.SetGroundAnimFrameIndex(m_animState);
  63. }
  64. }
  65. }
  66. override void OnEntry(WeaponEventBase e)
  67. {
  68. super.OnEntry(e);
  69. m_weapon.SetJammed(false);
  70. if (e)
  71. SyncAnimState();
  72. m_weapon.ResetWeaponAnimState();
  73. }
  74. override void OnUpdate(float dt)
  75. {
  76. super.OnUpdate(dt);
  77. SyncAnimState();
  78. }
  79. override void OnExit(WeaponEventBase e)
  80. {
  81. m_weapon.ResetWeaponAnimState();
  82. super.OnExit(e);
  83. }
  84. override bool IsIdle() { return true; }
  85. int GetCurrentStateID() { return 0; }
  86. /** \name Weapon state properties
  87. * Properties defining the state in several properties for other systems
  88. * Override these to set them up
  89. *
  90. * Several systems depends on this:
  91. * WeaponFSM.RandomizeFSMState, which picks out a suitable FSM state when attaching magazine through CE
  92. * WeaponFSM.ValidateAndRepair, which will attempt to identify a desync and repair the FSM state if so
  93. *
  94. * @WARNING So it is important to set these up correctly to prevent any desync of weapon FSM and actual wepon state
  95. */
  96. //@{
  97. /**@brief Whether WeaponFSM.ValidateAndRepair should be applied on this state
  98. * @NOTE: This property was implemented at the same time as ValARep
  99. * To have it disabled by default
  100. * In case there are modders who created their own state
  101. * But potentially did not set up their properties correctly
  102. * As having ValARep run on an improper setup would result in horrible VME spam and desync
  103. * @WARNING: When enabling repair, it is imperative that all properties are set up correctly.
  104. **/
  105. bool IsRepairEnabled() { return false; }
  106. /**@brief Whether there is a bullet in the chamber
  107. * @NOTE: This should only be false when it is empty
  108. * So this is true when there is a bullet in the chamber
  109. * Regardless of the bullet being loaded, firedout or jammed
  110. **/
  111. bool HasBullet() { return false; }
  112. //! Whether there is a magazine attached
  113. bool HasMagazine() { return false; }
  114. //! Whether the gun is jammed
  115. bool IsJammed() { return false; }
  116. //! Whether the gun is discharged
  117. bool IsDischarged() { return false; }
  118. //! Whether the gun is open
  119. bool IsWeaponOpen() { return false; }
  120. //! Override with the filling of m_muzzleHasBullet
  121. void InitMuzzleArray() { m_muzzleHasBullet = { MuzzleState.U }; }
  122. //! Special one for when the weapon only has one singular state (like Magnum)
  123. bool IsSingleState() { return false; }
  124. //@}
  125. /** \name Weapon state properties helpers
  126. * Several helpers for better access of certain properties
  127. */
  128. //@{
  129. //! Get chamber state of the muzzle at index
  130. MuzzleState GetMuzzleState(int idx) { return m_muzzleHasBullet[idx]; }
  131. int GetMuzzleStateCount() { return m_muzzleHasBullet.Count(); }
  132. bool IsChamberValid(int idx) { return m_muzzleHasBullet[idx] != MuzzleState.U; }
  133. bool IsChamberFiredOut(int idx) { return m_muzzleHasBullet[idx] == MuzzleState.F; }
  134. bool IsChamberFull(int idx) { return m_muzzleHasBullet[idx] != MuzzleState.E; }
  135. //@}
  136. //! Safety check and error message in case not set up correctly
  137. void ValidateMuzzleArray()
  138. {
  139. // There is only one
  140. if (IsSingleState())
  141. return;
  142. bool failed = false;
  143. if (!failed)
  144. {
  145. foreach (MuzzleState state : m_muzzleHasBullet)
  146. {
  147. if ( state == MuzzleState.U )
  148. {
  149. failed = true;
  150. break;
  151. }
  152. }
  153. }
  154. if (failed)
  155. {
  156. ErrorExSeverity severity = ErrorExSeverity.ERROR;
  157. #ifdef DEVELOPER
  158. if (DayZGame.m_IsPreviewSpawn)
  159. {
  160. // we do not want VMEs when spawning the item in order to visualize it for preview in script console
  161. severity = ErrorExSeverity.INFO;
  162. }
  163. #endif
  164. ErrorEx("Muzzle array validation has failed. Please set up the correct muzzle states by overriding InitMuzzleArray.", severity);
  165. }
  166. }
  167. };