GunComponent.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using System.Numerics;
  2. using Content.Shared.Weapons.Ranged.Events;
  3. using Content.Shared.Weapons.Ranged.Systems;
  4. using Robust.Shared.Audio;
  5. using Robust.Shared.GameStates;
  6. using Robust.Shared.Map;
  7. using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
  8. namespace Content.Shared.Weapons.Ranged.Components;
  9. [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(fieldDeltas: true), AutoGenerateComponentPause]
  10. [Access(typeof(SharedGunSystem))]
  11. public sealed partial class GunComponent : Component
  12. {
  13. #region Sound
  14. /// <summary>
  15. /// The base sound to use when the gun is fired.
  16. /// </summary>
  17. [DataField]
  18. public SoundSpecifier? SoundGunshot = new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/smg.ogg");
  19. /// <summary>
  20. /// The sound to use when the gun is fired.
  21. /// <seealso cref="GunRefreshModifiersEvent"/>
  22. /// </summary>
  23. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  24. public SoundSpecifier? SoundGunshotModified;
  25. [DataField]
  26. public SoundSpecifier? SoundEmpty = new SoundPathSpecifier("/Audio/Weapons/Guns/Empty/empty.ogg");
  27. /// <summary>
  28. /// Sound played when toggling the <see cref="SelectedMode"/> for this gun.
  29. /// </summary>
  30. [DataField]
  31. public SoundSpecifier? SoundMode = new SoundPathSpecifier("/Audio/Weapons/Guns/Misc/selector.ogg");
  32. #endregion
  33. #region Recoil
  34. // These values are very small for now until we get a debug overlay and fine tune it
  35. /// <summary>
  36. /// The base scalar value applied to the vector governing camera recoil.
  37. /// </summary>
  38. [DataField, AutoNetworkedField]
  39. public float CameraRecoilScalar = 1f;
  40. /// <summary>
  41. /// A scalar value applied to the vector governing camera recoil.
  42. /// If 0, there will be no camera recoil.
  43. /// <seealso cref="GunRefreshModifiersEvent"/>
  44. /// </summary>
  45. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  46. public float CameraRecoilScalarModified = 1f;
  47. /// <summary>
  48. /// Last time the gun fired.
  49. /// Used for recoil purposes.
  50. /// </summary>
  51. [DataField]
  52. public TimeSpan LastFire = TimeSpan.Zero;
  53. /// <summary>
  54. /// What the current spread is for shooting. This gets changed every time the gun fires.
  55. /// </summary>
  56. [DataField]
  57. [AutoNetworkedField]
  58. public Angle CurrentAngle;
  59. /// <summary>
  60. /// The base value for how much the spread increases every time the gun fires.
  61. /// </summary>
  62. [DataField]
  63. public Angle AngleIncrease = Angle.FromDegrees(0.5);
  64. /// <summary>
  65. /// How much the spread increases every time the gun fires.
  66. /// <seealso cref="GunRefreshModifiersEvent"/>
  67. /// </summary>
  68. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  69. public Angle AngleIncreaseModified;
  70. /// <summary>
  71. /// The base value for how much the <see cref="CurrentAngle"/> decreases per second.
  72. /// </summary>
  73. [DataField]
  74. public Angle AngleDecay = Angle.FromDegrees(4);
  75. /// <summary>
  76. /// How much the <see cref="CurrentAngle"/> decreases per second.
  77. /// <seealso cref="GunRefreshModifiersEvent"/>
  78. /// </summary>
  79. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  80. public Angle AngleDecayModified;
  81. /// <summary>
  82. /// The base value for the maximum angle allowed for <see cref="CurrentAngle"/>
  83. /// </summary>
  84. [DataField]
  85. [AutoNetworkedField]
  86. public Angle MaxAngle = Angle.FromDegrees(2);
  87. /// <summary>
  88. /// The maximum angle allowed for <see cref="CurrentAngle"/>
  89. /// <seealso cref="GunRefreshModifiersEvent"/>
  90. /// </summary>
  91. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  92. public Angle MaxAngleModified;
  93. /// <summary>
  94. /// The base value for the minimum angle allowed for <see cref="CurrentAngle"/>
  95. /// </summary>
  96. [DataField]
  97. [AutoNetworkedField]
  98. public Angle MinAngle = Angle.FromDegrees(1);
  99. /// <summary>
  100. /// The minimum angle allowed for <see cref="CurrentAngle"/>.
  101. /// <seealso cref="GunRefreshModifiersEvent"/>
  102. /// </summary>
  103. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  104. public Angle MinAngleModified;
  105. #endregion
  106. /// <summary>
  107. /// Whether this gun is shot via the use key or the alt-use key.
  108. /// </summary>
  109. [DataField, AutoNetworkedField]
  110. public bool UseKey = true;
  111. /// <summary>
  112. /// Where the gun is being requested to shoot.
  113. /// </summary>
  114. [ViewVariables]
  115. public EntityCoordinates? ShootCoordinates = null;
  116. /// <summary>
  117. /// Who the gun is being requested to shoot at directly.
  118. /// </summary>
  119. [ViewVariables]
  120. public EntityUid? Target = null;
  121. /// <summary>
  122. /// The base value for how many shots to fire per burst.
  123. /// </summary>
  124. [DataField, AutoNetworkedField]
  125. public int ShotsPerBurst = 3;
  126. /// <summary>
  127. /// How many shots to fire per burst.
  128. /// <seealso cref="GunRefreshModifiersEvent"/>
  129. /// </summary>
  130. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  131. public int ShotsPerBurstModified = 3;
  132. /// <summary>
  133. /// How long time must pass between burstfire shots.
  134. /// </summary>
  135. [DataField, AutoNetworkedField]
  136. public float BurstCooldown = 0.25f;
  137. /// <summary>
  138. /// The fire rate of the weapon in burst fire mode.
  139. /// </summary>
  140. [DataField, AutoNetworkedField]
  141. public float BurstFireRate = 8f;
  142. /// <summary>
  143. /// Whether the burst fire mode has been activated.
  144. /// </summary>
  145. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  146. public bool BurstActivated = false;
  147. /// <summary>
  148. /// The burst fire bullet count.
  149. /// </summary>
  150. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  151. public int BurstShotsCount = 0;
  152. /// <summary>
  153. /// Used for tracking semi-auto / burst
  154. /// </summary>
  155. [ViewVariables]
  156. [AutoNetworkedField]
  157. public int ShotCounter = 0;
  158. /// <summary>
  159. /// The base value for how many times it shoots per second.
  160. /// </summary>
  161. [DataField]
  162. [AutoNetworkedField]
  163. public float FireRate = 8f;
  164. /// <summary>
  165. /// How many times it shoots per second.
  166. /// <seealso cref="GunRefreshModifiersEvent"/>
  167. /// </summary>
  168. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  169. public float FireRateModified;
  170. /// <summary>
  171. /// Starts fire cooldown when equipped if true.
  172. /// </summary>
  173. [DataField]
  174. public bool ResetOnHandSelected = true;
  175. /// <summary>
  176. /// The base value for how fast the projectile moves.
  177. /// </summary>
  178. [DataField]
  179. public float ProjectileSpeed = 25f;
  180. /// <summary>
  181. /// How fast the projectile moves.
  182. /// <seealso cref="GunRefreshModifiersEvent"/>
  183. /// </summary>
  184. [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
  185. public float ProjectileSpeedModified;
  186. /// <summary>
  187. /// When the gun is next available to be shot.
  188. /// Can be set multiple times in a single tick due to guns firing faster than a single tick time.
  189. /// </summary>
  190. [DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
  191. [AutoNetworkedField]
  192. [AutoPausedField]
  193. public TimeSpan NextFire = TimeSpan.Zero;
  194. /// <summary>
  195. /// What firemodes can be selected.
  196. /// </summary>
  197. [DataField]
  198. [AutoNetworkedField]
  199. public SelectiveFire AvailableModes = SelectiveFire.SemiAuto;
  200. /// <summary>
  201. /// What firemode is currently selected.
  202. /// </summary>
  203. [DataField]
  204. [AutoNetworkedField]
  205. public SelectiveFire SelectedMode = SelectiveFire.SemiAuto;
  206. /// <summary>
  207. /// Whether or not information about
  208. /// the gun will be shown on examine.
  209. /// </summary>
  210. [DataField]
  211. public bool ShowExamineText = true;
  212. /// <summary>
  213. /// Whether or not someone with the
  214. /// clumsy trait can shoot this
  215. /// </summary>
  216. [DataField]
  217. public bool ClumsyProof = false;
  218. /// <summary>
  219. /// Firing direction for an item not being held (e.g. shuttle cannons, thrown guns still firing).
  220. /// </summary>
  221. [DataField]
  222. public Vector2 DefaultDirection = new Vector2(0, -1);
  223. }
  224. [Flags]
  225. public enum SelectiveFire : byte
  226. {
  227. Invalid = 0,
  228. // Combat mode already functions as the equivalent of Safety
  229. SemiAuto = 1 << 0,
  230. Burst = 1 << 1,
  231. FullAuto = 1 << 2, // Not in the building!
  232. }