123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /**@class WeaponStableState
- * @brief represents weapon's stable state (i.e. the basic states that the weapon will spend the most time in)
- *
- * Stable states have associated animation states that they supposed to be in.
- * If they are not, the SetWeaponAnimState is called on the weapon in order to
- * set to required (configured) state
- *
- * @NOTE: OnExit from stable state, the weapon's animation state (@see
- * Weapon_Base::m_weaponAnimState) is set to -1 (unknown) In case of action
- * abort the final stable state is forced to set proper animation state
- * according to configuration (@see m_animState)
- **/
- enum MuzzleState
- {
- //! UNKNOWN
- U = -1,
- //! EMPTY
- E = 0,
- //! FIRED
- F = 1,
- //! LOADED
- L = 2
- }
- class WeaponStableState extends WeaponStateBase
- {
- int m_animState;
-
- ref array<MuzzleState> m_muzzleHasBullet = new array<MuzzleState>();
- void WeaponStableState(Weapon_Base w = NULL, WeaponStateBase parent = NULL, int anim_state = -1)
- {
- m_animState = anim_state;
- InitMuzzleArray();
- ValidateMuzzleArray();
- }
- void SyncAnimState()
- {
- int curr = m_weapon.GetWeaponAnimState();
- if (curr != m_animState)
- {
- //if (LogManager.IsWeaponLogEnable()) fsmDebugSpam("[wpnfsm] " + Object.GetDebugName(m_weapon) + " synchronizing anim state: " + curr + " --> " + m_animState);
- PlayerBase p;
- if (Class.CastTo(p, m_weapon.GetHierarchyParent()))
- {
- if (p.GetItemInHands() == m_weapon)
- {
- HumanCommandWeapons hcw = p.GetCommandModifier_Weapons();
- if (hcw)
- {
- hcw.SetInitState(m_animState);
- 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));
- }
- else
- {
- Human wpnOwner = Human.Cast(m_weapon.GetHierarchyRootPlayer());
- HumanCommandWeapons.StaticSetInitState(wpnOwner, m_animState);
- 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));
- }
- }
- m_weapon.SetWeaponAnimState(m_animState);
- }
- else
- {
- m_weapon.SetGroundAnimFrameIndex(m_animState);
- }
- }
- }
- override void OnEntry(WeaponEventBase e)
- {
- super.OnEntry(e);
- m_weapon.SetJammed(false);
- if (e)
- SyncAnimState();
- m_weapon.ResetWeaponAnimState();
- }
- override void OnUpdate(float dt)
- {
- super.OnUpdate(dt);
- SyncAnimState();
- }
- override void OnExit(WeaponEventBase e)
- {
- m_weapon.ResetWeaponAnimState();
- super.OnExit(e);
- }
- override bool IsIdle() { return true; }
- int GetCurrentStateID() { return 0; }
-
- /** \name Weapon state properties
- * Properties defining the state in several properties for other systems
- * Override these to set them up
- *
- * Several systems depends on this:
- * WeaponFSM.RandomizeFSMState, which picks out a suitable FSM state when attaching magazine through CE
- * WeaponFSM.ValidateAndRepair, which will attempt to identify a desync and repair the FSM state if so
- *
- * @WARNING So it is important to set these up correctly to prevent any desync of weapon FSM and actual wepon state
- */
- //@{
-
- /**@brief Whether WeaponFSM.ValidateAndRepair should be applied on this state
- * @NOTE: This property was implemented at the same time as ValARep
- * To have it disabled by default
- * In case there are modders who created their own state
- * But potentially did not set up their properties correctly
- * As having ValARep run on an improper setup would result in horrible VME spam and desync
- * @WARNING: When enabling repair, it is imperative that all properties are set up correctly.
- **/
- bool IsRepairEnabled() { return false; }
-
- /**@brief Whether there is a bullet in the chamber
- * @NOTE: This should only be false when it is empty
- * So this is true when there is a bullet in the chamber
- * Regardless of the bullet being loaded, firedout or jammed
- **/
- bool HasBullet() { return false; }
-
- //! Whether there is a magazine attached
- bool HasMagazine() { return false; }
-
- //! Whether the gun is jammed
- bool IsJammed() { return false; }
-
- //! Whether the gun is discharged
- bool IsDischarged() { return false; }
-
- //! Whether the gun is open
- bool IsWeaponOpen() { return false; }
-
- //! Override with the filling of m_muzzleHasBullet
- void InitMuzzleArray() { m_muzzleHasBullet = { MuzzleState.U }; }
-
- //! Special one for when the weapon only has one singular state (like Magnum)
- bool IsSingleState() { return false; }
-
- //@}
-
- /** \name Weapon state properties helpers
- * Several helpers for better access of certain properties
- */
- //@{
-
- //! Get chamber state of the muzzle at index
- MuzzleState GetMuzzleState(int idx) { return m_muzzleHasBullet[idx]; }
- int GetMuzzleStateCount() { return m_muzzleHasBullet.Count(); }
- bool IsChamberValid(int idx) { return m_muzzleHasBullet[idx] != MuzzleState.U; }
- bool IsChamberFiredOut(int idx) { return m_muzzleHasBullet[idx] == MuzzleState.F; }
- bool IsChamberFull(int idx) { return m_muzzleHasBullet[idx] != MuzzleState.E; }
-
- //@}
-
- //! Safety check and error message in case not set up correctly
- void ValidateMuzzleArray()
- {
- // There is only one
- if (IsSingleState())
- return;
-
- bool failed = false;
-
- if (!failed)
- {
- foreach (MuzzleState state : m_muzzleHasBullet)
- {
- if ( state == MuzzleState.U )
- {
- failed = true;
- break;
- }
- }
- }
-
- if (failed)
- {
- ErrorExSeverity severity = ErrorExSeverity.ERROR;
-
- #ifdef DEVELOPER
- if (DayZGame.m_IsPreviewSpawn)
- {
- // we do not want VMEs when spawning the item in order to visualize it for preview in script console
- severity = ErrorExSeverity.INFO;
- }
- #endif
-
- ErrorEx("Muzzle array validation has failed. Please set up the correct muzzle states by overriding InitMuzzleArray.", severity);
- }
- }
- };
|