diff --git a/Content.Shared/Weapons/Ranged/Components/GunComponent.cs b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs
new file mode 100644
index 00000000000..bcc56c28ab1
--- /dev/null
+++ b/Content.Shared/Weapons/Ranged/Components/GunComponent.cs
@@ -0,0 +1,282 @@
+using System.Numerics;
+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.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Shared.Weapons.Ranged.Components;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
+[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;
+
+ ///
+ /// Who the gun is being requested to shoot at directly.
+ ///
+ [ViewVariables]
+ public EntityUid? Target = 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;
+
+ ///
+ /// How long time must pass between burstfire shots.
+ ///
+ [DataField, AutoNetworkedField]
+ public float BurstCooldown = 0.25f;
+
+ ///
+ /// The fire rate of the weapon in burst fire mode.
+ ///
+ [DataField, AutoNetworkedField]
+ public float BurstFireRate = 8f;
+
+ ///
+ /// Whether the burst fire mode has been activated.
+ ///
+ [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
+ public bool BurstActivated = false;
+
+ ///
+ /// The burst fire bullet count.
+ ///
+ [AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
+ public int BurstShotsCount = 0;
+
+ ///
+ /// 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;
+
+ ///
+ /// 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]
+ [AutoPausedField]
+ 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;
+
+ ///
+ /// Firing direction for an item not being held (e.g. shuttle cannons, thrown guns still firing).
+ ///
+ [DataField]
+ public Vector2 DefaultDirection = new Vector2(0, -1);
+
+ ///
+ /// Corvax-Next. The percentage chance of a given gun to accidentally discharge if violently thrown into a wall or person
+ ///
+ [DataField]
+ public float FireOnDropChance = 0.1f;
+}
+
+[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!
+}