using System.Numerics; using Content.Shared._White.Weapons.Ranged.DualWield; using Content.Shared.Weapons.Ranged.Events; 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] 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. /// WWDP rename: formely "LastFire". /// [DataField] [AutoNetworkedField] public TimeSpan CurrentAngleLastUpdate = TimeSpan.Zero; /// /// What the current spread is for shooting. This gets changed every time the gun fires. /// [DataField] [AutoNetworkedField] public Angle CurrentAngle; // WWDP EDIT START [AutoNetworkedField] [ViewVariables(VVAccess.ReadWrite)] public Angle BonusAngle; [AutoNetworkedField, ViewVariables(VVAccess.ReadOnly)] public TimeSpan BonusAngleLastUpdate; [DataField] [AutoNetworkedField] public Angle BonusAngleDecay = Angle.FromDegrees(40); [DataField] [AutoNetworkedField] public Angle MaxBonusAngle = Angle.FromDegrees(30); [ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] public Angle BonusAngleDecayModified; [ViewVariables(VVAccess.ReadWrite)] [AutoNetworkedField] public Angle MaxBonusAngleModified; /// /// Bonus spread angle increase per tile traversed (assuming zero travel time) /// [DataField, AutoNetworkedField] public Angle BonusAngleIncreaseMove = Angle.FromDegrees(20); /// /// Bonus spread angle increase per angle turned (assuming instantaneous turn) /// [DataField, AutoNetworkedField] public Angle BonusAngleIncreaseTurn = Angle.FromDegrees(0.25); // WWDP EDIT END /// /// 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; /// /// After dealing a melee attack with this gun, the minimum cooldown in seconds before the gun can shoot again. /// [DataField] public float MeleeCooldown = 0.528f; /// /// 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); /// /// The percentage chance of a given gun to accidentally discharge if violently thrown into a wall or person /// [DataField] public float FireOnDropChance = 0.1f; /// /// If this weapon is using any kind of "Shotgun-like" ammunition, this applies as a multiplier on the spread arc. // EG: 1.5 with standard buckshot gives a shotgun arc of 22.5 degrees. /// [DataField] public float ShotgunSpreadMultiplier = 1f; /// /// This multiplier will apply per projectile fired by the weapon. /// [DataField] public float DamageModifier = 1f; /// /// This multiplier increases the amount of projectiles fired by a shotgun. /// [DataField] public float ShotgunProjectileCountModifier = 1f; /// /// If this weapon is using any kind of "Shotgun-like" ammunition, setting this to true makes it use the /// classic style of "uniform" spread. Whereas when left off, each pellet fires in a uniform arc. /// [DataField] public bool UniformSpread; /// /// The amount of Force (in Newtons) to eject spent cartridges with. /// [DataField] public float EjectionForce = 0.04f; [DataField] public float EjectionSpeed = 20f; [DataField] public float EjectAngleOffset = 3.7f; // WD EDIT START [DataField] public Angle? ThrowAngle; /// /// Designates this weapon a naval cannon. All projectiles shot from this weapon will be added to PVS ignore list (see Server.PvsOverrideSystem) /// to ensure their visibility on clients. /// [DataField] public bool ShipWeapon = false; [DataField] public bool ForceShootForward = false; // WD EDIT END } [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! }