using Content.Shared.Damage; using Content.Shared.Tag; using Content.Shared.Weapons.Ranged.Events; using Content.Shared.Weapons.Ranged.Systems; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; namespace Content.Shared.Weapons.Ranged.Components; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] [Access(typeof(SharedGunSystem))] public sealed partial class GunComponent : Component { #region Sound /// /// The base sound to use when the gun is fired. /// [DataField] public SoundSpecifier? SoundGunshot = new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/smg.ogg"); /// /// The sound to use when the gun is fired. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public SoundSpecifier? SoundGunshotModified; [DataField] public SoundSpecifier? SoundEmpty = new SoundPathSpecifier("/Audio/Weapons/Guns/Empty/empty.ogg"); /// /// Sound played when toggling the for this gun. /// [DataField] public SoundSpecifier? SoundMode = new SoundPathSpecifier("/Audio/Weapons/Guns/Misc/selector.ogg"); #endregion #region Recoil // These values are very small for now until we get a debug overlay and fine tune it /// /// The base scalar value applied to the vector governing camera recoil. /// [DataField, AutoNetworkedField] public float CameraRecoilScalar = 1f; /// /// A scalar value applied to the vector governing camera recoil. /// If 0, there will be no camera recoil. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public float CameraRecoilScalarModified = 1f; /// /// Last time the gun fired. /// Used for recoil purposes. /// [DataField] public TimeSpan LastFire = TimeSpan.Zero; /// /// What the current spread is for shooting. This gets changed every time the gun fires. /// [DataField] [AutoNetworkedField] public Angle CurrentAngle; /// /// The base value for how much the spread increases every time the gun fires. /// [DataField] public Angle AngleIncrease = Angle.FromDegrees(0.5); /// /// How much the spread increases every time the gun fires. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public Angle AngleIncreaseModified; /// /// The base value for how much the decreases per second. /// [DataField] public Angle AngleDecay = Angle.FromDegrees(4); /// /// How much the decreases per second. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public Angle AngleDecayModified; /// /// The base value for the maximum angle allowed for /// [DataField] [AutoNetworkedField] public Angle MaxAngle = Angle.FromDegrees(2); /// /// The maximum angle allowed for /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public Angle MaxAngleModified; /// /// The base value for the minimum angle allowed for /// [DataField] [AutoNetworkedField] public Angle MinAngle = Angle.FromDegrees(1); /// /// The minimum angle allowed for . /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public Angle MinAngleModified; #endregion /// /// Whether this gun is shot via the use key or the alt-use key. /// [DataField, AutoNetworkedField] public bool UseKey = true; /// /// Where the gun is being requested to shoot. /// [ViewVariables] public EntityCoordinates? ShootCoordinates = null; /// /// The base value for how many shots to fire per burst. /// [DataField, AutoNetworkedField] public int ShotsPerBurst = 3; /// /// How many shots to fire per burst. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public int ShotsPerBurstModified = 3; /// /// Used for tracking semi-auto / burst /// [ViewVariables] [AutoNetworkedField] public int ShotCounter = 0; /// /// The base value for how many times it shoots per second. /// [DataField] [AutoNetworkedField] public float FireRate = 8f; /// /// How many times it shoots per second. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public float FireRateModified; /// /// Starts fire cooldown when equipped if true. /// [DataField] public bool ResetOnHandSelected = true; /// /// Type of ammo the gun can work with /// [DataField] public List>? CompatibleAmmo; /// /// Damage the gun deals when used with wrong ammo /// [DataField] public DamageSpecifier? DamageOnWrongAmmo = null; /// /// The base value for how fast the projectile moves. /// [DataField] public float ProjectileSpeed = 25f; /// /// How fast the projectile moves. /// /// [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)] public float ProjectileSpeedModified; /// /// When the gun is next available to be shot. /// Can be set multiple times in a single tick due to guns firing faster than a single tick time. /// [DataField(customTypeSerializer:typeof(TimeOffsetSerializer))] [AutoNetworkedField] public TimeSpan NextFire = TimeSpan.Zero; /// /// What firemodes can be selected. /// [DataField] [AutoNetworkedField] public SelectiveFire AvailableModes = SelectiveFire.SemiAuto; /// /// What firemode is currently selected. /// [DataField] [AutoNetworkedField] public SelectiveFire SelectedMode = SelectiveFire.SemiAuto; /// /// Whether or not information about /// the gun will be shown on examine. /// [DataField] public bool ShowExamineText = true; /// /// Whether or not someone with the /// clumsy trait can shoot this /// [DataField] public bool ClumsyProof = false; } [Flags] public enum SelectiveFire : byte { Invalid = 0, // Combat mode already functions as the equivalent of Safety SemiAuto = 1 << 0, Burst = 1 << 1, FullAuto = 1 << 2, // Not in the building! }