using System; using Content.Server.Weapon.Ranged.Ammunition.Components; using Content.Shared.Sound; using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.IoC; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.ViewVariables; namespace Content.Server.Weapon.Ranged.Barrels.Components { [RegisterComponent, NetworkedComponent, ComponentReference(typeof(ServerRangedBarrelComponent))] public sealed class MagazineBarrelComponent : ServerRangedBarrelComponent { [Dependency] private readonly IEntityManager _entities = default!; [ViewVariables] public ContainerSlot ChamberContainer = default!; [ViewVariables] public bool HasMagazine => MagazineContainer.ContainedEntity != null; public ContainerSlot MagazineContainer = default!; [ViewVariables] public MagazineType MagazineTypes => _magazineTypes; [DataField("magazineTypes")] private MagazineType _magazineTypes = default; [ViewVariables] public BallisticCaliber Caliber => _caliber; [DataField("caliber")] private BallisticCaliber _caliber = BallisticCaliber.Unspecified; public override int ShotsLeft { get { var count = 0; if (ChamberContainer.ContainedEntity != null) { count++; } if (MagazineContainer.ContainedEntity is {Valid: true} magazine) { count += _entities.GetComponent(magazine).ShotsLeft; } return count; } } public override int Capacity { get { // Chamber var count = 1; if (MagazineContainer.ContainedEntity is {Valid: true} magazine) { count += _entities.GetComponent(magazine).Capacity; } return count; } } [DataField("magFillPrototype", customTypeSerializer:typeof(PrototypeIdSerializer))] public string? MagFillPrototype; public bool BoltOpen { get => _boltOpen; set { if (_boltOpen == value) { return; } var gunSystem = EntitySystem.Get(); if (value) { gunSystem.TryEjectChamber(this); SoundSystem.Play(Filter.Pvs(Owner), SoundBoltOpen.GetSound(), Owner, AudioParams.Default.WithVolume(-2)); } else { gunSystem.TryFeedChamber(this); SoundSystem.Play(Filter.Pvs(Owner), SoundBoltClosed.GetSound(), Owner, AudioParams.Default.WithVolume(-2)); } _boltOpen = value; gunSystem.UpdateMagazineAppearance(this); Dirty(_entities); } } private bool _boltOpen = true; [DataField("autoEjectMag")] public bool AutoEjectMag; // If the bolt needs to be open before we can insert / remove the mag (i.e. for LMGs) public bool MagNeedsOpenBolt => _magNeedsOpenBolt; [DataField("magNeedsOpenBolt")] private bool _magNeedsOpenBolt = default; // Sounds [DataField("soundBoltOpen", required: true)] public SoundSpecifier SoundBoltOpen = default!; [DataField("soundBoltClosed", required: true)] public SoundSpecifier SoundBoltClosed = default!; [DataField("soundRack", required: true)] public SoundSpecifier SoundRack = default!; [DataField("soundMagInsert", required: true)] public SoundSpecifier SoundMagInsert = default!; [DataField("soundMagEject", required: true)] public SoundSpecifier SoundMagEject = default!; [DataField("soundAutoEject")] public SoundSpecifier SoundAutoEject = new SoundPathSpecifier("/Audio/Weapons/Guns/EmptyAlarm/smg_empty_alarm.ogg"); } [Flags] public enum MagazineType { Unspecified = 0, LPistol = 1 << 0, // Placeholder? Pistol = 1 << 1, HCPistol = 1 << 2, Smg = 1 << 3, SmgTopMounted = 1 << 4, Rifle = 1 << 5, IH = 1 << 6, // Placeholder? Box = 1 << 7, Pan = 1 << 8, Dart = 1 << 9, // Placeholder CalicoTopMounted = 1 << 10, } }