diff --git a/Content.Client/Weapons/Ranged/Systems/GunSystem.ChamberMagazine.cs b/Content.Client/Weapons/Ranged/Systems/GunSystem.ChamberMagazine.cs index 13e64d5393..0f1595010f 100644 --- a/Content.Client/Weapons/Ranged/Systems/GunSystem.ChamberMagazine.cs +++ b/Content.Client/Weapons/Ranged/Systems/GunSystem.ChamberMagazine.cs @@ -1,7 +1,9 @@ -using Content.Shared.Examine; +using Content.Client.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged; using Content.Shared.Weapons.Ranged.Components; using Content.Shared.Weapons.Ranged.Events; +using Content.Shared.Weapons.Ranged.Systems; +using Robust.Client.GameObjects; using Robust.Shared.Containers; namespace Content.Client.Weapons.Ranged.Systems; @@ -13,6 +15,27 @@ public sealed partial class GunSystem base.InitializeChamberMagazine(); SubscribeLocalEvent(OnChamberMagazineCounter); SubscribeLocalEvent(OnChamberMagazineAmmoUpdate); + SubscribeLocalEvent(OnChamberMagazineAppearance); + } + + private void OnChamberMagazineAppearance(EntityUid uid, ChamberMagazineAmmoProviderComponent component, ref AppearanceChangeEvent args) + { + if (args.Sprite == null || + !args.Sprite.LayerMapTryGet(GunVisualLayers.Base, out var boltLayer) || + !Appearance.TryGetData(uid, AmmoVisuals.BoltClosed, out bool boltClosed)) + { + return; + } + + // Maybe re-using base layer for this will bite me someday but screw you future sloth. + if (boltClosed) + { + args.Sprite.LayerSetState(boltLayer, "base"); + } + else + { + args.Sprite.LayerSetState(boltLayer, "bolt-open"); + } } protected override void OnMagazineSlotChange(EntityUid uid, MagazineAmmoProviderComponent component, ContainerModifiedMessage args) diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 55fd7b5f8d..4a35e64c6c 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -174,7 +174,7 @@ public sealed partial class GunSystem : SharedGunSystem if (!cartridge.DeleteOnSpawn && !Containers.IsEntityInContainer(ent!.Value)) EjectCartridge(ent.Value, angle); - Dirty(cartridge); + Dirty(ent!.Value, cartridge); break; // Ammo shoots itself case AmmoComponent newAmmo: diff --git a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs index 7b6a345f8b..679b0df782 100644 --- a/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/BallisticAmmoProviderComponent.cs @@ -39,21 +39,11 @@ public sealed partial class BallisticAmmoProviderComponent : Component public List Entities = new(); /// - /// Will the ammoprovider automatically cycle through rounds or does it need doing manually. - /// - [ViewVariables(VVAccess.ReadWrite), DataField("autoCycle")] - public bool AutoCycle = true; - - /// - /// Is the gun ready to shoot; if AutoCycle is true then this will always stay true and not need to be manually done. - /// - [ViewVariables(VVAccess.ReadWrite), DataField("cycled")] - [AutoNetworkedField] - public bool Cycled = true; - - /// - /// Is the magazine allowed to be cycled + /// Is the magazine allowed to be manually cycled to eject a cartridge. /// + /// + /// Set to false for entities like turrets to avoid users being able to cycle them. + /// [ViewVariables(VVAccess.ReadWrite), DataField("cycleable")] [AutoNetworkedField] public bool Cycleable = true; diff --git a/Content.Shared/Weapons/Ranged/Components/ChamberMagazineAmmoProviderComponent.cs b/Content.Shared/Weapons/Ranged/Components/ChamberMagazineAmmoProviderComponent.cs index 10fcb6ddd6..e64ec0d68d 100644 --- a/Content.Shared/Weapons/Ranged/Components/ChamberMagazineAmmoProviderComponent.cs +++ b/Content.Shared/Weapons/Ranged/Components/ChamberMagazineAmmoProviderComponent.cs @@ -1,7 +1,31 @@ +using Robust.Shared.Audio; + namespace Content.Shared.Weapons.Ranged.Components; /// /// Chamber + mags in one package. If you need just magazine then use /// -[RegisterComponent] -public sealed class ChamberMagazineAmmoProviderComponent : MagazineAmmoProviderComponent {} +[RegisterComponent, AutoGenerateComponentState] +public sealed partial class ChamberMagazineAmmoProviderComponent : MagazineAmmoProviderComponent +{ + /// + /// If the gun has a bolt and whether that bolt is closed. Firing is impossible + /// + [ViewVariables(VVAccess.ReadWrite), DataField("boltClosed"), AutoNetworkedField] + public bool? BoltClosed = false; + + /// + /// Does the gun automatically open and close the bolt upon shooting. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("autoCycle"), AutoNetworkedField] + public bool AutoCycle = true; + + [ViewVariables(VVAccess.ReadWrite), DataField("soundBoltClosed"), AutoNetworkedField] + public SoundSpecifier? BoltClosedSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Bolt/rifle_bolt_closed.ogg"); + + [ViewVariables(VVAccess.ReadWrite), DataField("soundBoltOpened"), AutoNetworkedField] + public SoundSpecifier? BoltOpenedSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Bolt/rifle_bolt_open.ogg"); + + [ViewVariables(VVAccess.ReadWrite), DataField("soundRack"), AutoNetworkedField] + public SoundSpecifier? RackSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Cock/ltrifle_cock.ogg"); +} diff --git a/Content.Shared/Weapons/Ranged/Events/TakeAmmoEvent.cs b/Content.Shared/Weapons/Ranged/Events/TakeAmmoEvent.cs index a28816d8e2..50cd7871d6 100644 --- a/Content.Shared/Weapons/Ranged/Events/TakeAmmoEvent.cs +++ b/Content.Shared/Weapons/Ranged/Events/TakeAmmoEvent.cs @@ -11,6 +11,11 @@ public sealed class TakeAmmoEvent : EntityEventArgs public readonly int Shots; public List<(EntityUid? Entity, IShootable Shootable)> Ammo; + /// + /// If no ammo returned what is the reason for it? + /// + public string? Reason; + /// /// Coordinates to spawn the ammo at. /// diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs index c232264b5c..b0f8ae15d6 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Ballistic.cs @@ -132,12 +132,17 @@ public abstract partial class SharedGunSystem { if (!args.CanAccess || !args.CanInteract || args.Hands == null || !component.Cycleable) return; - args.Verbs.Add(new Verb() + + if (component.Cycleable) { - Text = Loc.GetString("gun-ballistic-cycle"), - Disabled = GetBallisticShots(component) == 0, - Act = () => ManualCycle(uid, component, Transform(uid).MapPosition, args.User), - }); + args.Verbs.Add(new Verb() + { + Text = Loc.GetString("gun-ballistic-cycle"), + Disabled = GetBallisticShots(component) == 0, + Act = () => ManualCycle(uid, component, Transform(uid).MapPosition, args.User), + }); + + } } private void OnBallisticExamine(EntityUid uid, BallisticAmmoProviderComponent component, ExaminedEvent args) @@ -165,8 +170,6 @@ public abstract partial class SharedGunSystem Audio.PlayPredicted(component.SoundRack, uid, user); var shots = GetBallisticShots(component); - component.Cycled = true; - Cycle(uid, component, coordinates); var text = Loc.GetString(shots == 0 ? "gun-ballistic-cycled-empty" : "gun-ballistic-cycled"); @@ -181,6 +184,9 @@ public abstract partial class SharedGunSystem private void OnBallisticInit(EntityUid uid, BallisticAmmoProviderComponent component, ComponentInit args) { component.Container = Containers.EnsureContainer(uid, "ballistic-ammo"); + // TODO: This is called twice though we need to support loading appearance data (and we need to call it on MapInit + // to ensure it's correct). + UpdateBallisticAppearance(uid, component); } private void OnBallisticMapInit(EntityUid uid, BallisticAmmoProviderComponent component, MapInitEvent args) @@ -190,6 +196,7 @@ public abstract partial class SharedGunSystem if (component.FillProto != null) { component.UnspawnedCount = Math.Max(0, component.Capacity - component.Container.ContainedEntities.Count); + UpdateBallisticAppearance(uid, component); Dirty(uid, component); } } @@ -203,9 +210,6 @@ public abstract partial class SharedGunSystem { for (var i = 0; i < args.Shots; i++) { - if (!component.Cycled) - break; - EntityUid entity; if (component.Entities.Count > 0) @@ -213,14 +217,6 @@ public abstract partial class SharedGunSystem entity = component.Entities[^1]; args.Ammo.Add((entity, EnsureComp(entity))); - - // Leave the entity as is if it doesn't auto cycle - // TODO: Suss this out with NewAmmoComponent as I don't think it gets removed from container properly - if (!component.AutoCycle) - { - return; - } - component.Entities.RemoveAt(component.Entities.Count - 1); component.Container.Remove(entity); } @@ -229,25 +225,6 @@ public abstract partial class SharedGunSystem component.UnspawnedCount--; entity = Spawn(component.FillProto, args.Coordinates); args.Ammo.Add((entity, EnsureComp(entity))); - - // Put it back in if it doesn't auto-cycle - if (HasComp(entity) && !component.AutoCycle) - { - if (!entity.IsClientSide()) - { - component.Entities.Add(entity); - component.Container.Insert(entity); - } - else - { - component.UnspawnedCount++; - } - } - } - - if (!component.AutoCycle) - { - component.Cycled = false; } } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs index 84c65eca95..17c32f639a 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.ChamberMagazine.cs @@ -1,5 +1,7 @@ using System.Diagnostics.CodeAnalysis; +using Content.Shared.Containers.ItemSlots; using Content.Shared.Examine; +using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Verbs; using Content.Shared.Weapons.Ranged.Components; @@ -14,21 +16,244 @@ public abstract partial class SharedGunSystem protected virtual void InitializeChamberMagazine() { + SubscribeLocalEvent(OnChamberStartup); SubscribeLocalEvent(OnChamberMagazineTakeAmmo); SubscribeLocalEvent(OnChamberAmmoCount); + + /* + * Open and close bolts are separate verbs. + * Racking does both in one hit and has a different sound (to avoid RSI + sounds cooler). + */ + + SubscribeLocalEvent>(OnChamberVerb); + SubscribeLocalEvent>(OnChamberActivationVerb); + SubscribeLocalEvent>(OnChamberInteractionVerb); SubscribeLocalEvent>(OnMagazineVerb); + + SubscribeLocalEvent(OnChamberActivate); + SubscribeLocalEvent(OnChamberUse); + SubscribeLocalEvent(OnMagazineSlotChange); SubscribeLocalEvent(OnMagazineSlotChange); - SubscribeLocalEvent(OnMagazineUse); SubscribeLocalEvent(OnChamberMagazineExamine); } + private void OnChamberStartup(EntityUid uid, ChamberMagazineAmmoProviderComponent component, ComponentStartup args) + { + // Appearance data doesn't get serialized and want to make sure this is correct on spawn (regardless of MapInit) so. + if (component.BoltClosed != null) + { + Appearance.SetData(uid, AmmoVisuals.BoltClosed, component.BoltClosed.Value); + } + } + + private void OnChamberVerb(EntityUid uid, ChamberMagazineAmmoProviderComponent component, GetVerbsEvent args) + { + if (component.BoltClosed != null) + { + args.Verbs.Add(new Verb() + { + Text = component.BoltClosed.Value ? Loc.GetString("gun-chamber-bolt-open") : Loc.GetString("gun-chamber-bolt-close"), + Act = () => ToggleBolt(uid, component, args.User), + }); + } + } + + private void OnChamberActivate(EntityUid uid, ChamberMagazineAmmoProviderComponent component, ActivateInWorldEvent args) + { + if (args.Handled || component.BoltClosed == null) + return; + + args.Handled = true; + ToggleBolt(uid, component, args.User); + } + + private void OnChamberUse(EntityUid uid, ChamberMagazineAmmoProviderComponent component, UseInHandEvent args) + { + if (args.Handled || component.BoltClosed == null) + return; + + args.Handled = true; + UseChambered(uid, component, args.User); + } + + private void OnChamberActivationVerb(EntityUid uid, ChamberMagazineAmmoProviderComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || component.BoltClosed == null) + return; + + args.Verbs.Add(new ActivationVerb() + { + Text = Loc.GetString("gun-chamber-rack"), + Act = () => + { + UseChambered(uid, component, args.User); + } + }); + } + + private void UseChambered(EntityUid uid, ChamberMagazineAmmoProviderComponent component, EntityUid? user = null) + { + if (component.BoltClosed == null || !component.BoltClosed.Value) + return; + + if (TryTakeChamberEntity(uid, out var chamberEnt)) + { + if (_netManager.IsServer) + { + EjectCartridge(chamberEnt.Value); + } + else + { + // Similar to below just due to prediction. + TransformSystem.DetachParentToNull(chamberEnt.Value, Transform(chamberEnt.Value)); + } + } + + CycleCartridge(uid, component, user); + + if (component.BoltClosed.Value) + { + Audio.PlayPredicted(component.RackSound, uid, user); + } + } + + private void OnChamberInteractionVerb(EntityUid uid, ChamberMagazineAmmoProviderComponent component, GetVerbsEvent args) + { + if (!args.CanAccess || !args.CanInteract || component.BoltClosed == null) + return; + + args.Verbs.Add(new InteractionVerb() + { + Text = component.BoltClosed.Value ? Loc.GetString("gun-chamber-bolt-open") : Loc.GetString("gun-chamber-bolt-close"), + Act = () => + { + // Just toggling might be more user friendly instead of trying to set to whatever they think? + ToggleBolt(uid, component, args.User); + } + }); + } + + public void SetBoltClosed(EntityUid uid, ChamberMagazineAmmoProviderComponent component, bool value, EntityUid? user = null, AppearanceComponent? appearance = null, ItemSlotsComponent? slots = null) + { + if (component.BoltClosed == null || value == component.BoltClosed) + return; + + Resolve(uid, ref appearance, ref slots, false); + Appearance.SetData(uid, AmmoVisuals.BoltClosed, value, appearance); + + if (value) + { + CycleCartridge(uid, component, user, appearance); + + if (user != null) + PopupSystem.PopupClient(Loc.GetString("gun-chamber-bolt-closed"), uid, user.Value); + + if (slots != null) + { + _slots.SetLock(uid, ChamberSlot, true, slots); + } + + Audio.PlayPredicted(component.BoltClosedSound, uid, user); + } + else + { + if (TryTakeChamberEntity(uid, out var chambered)) + { + if (_netManager.IsServer) + { + EjectCartridge(chambered.Value); + } + else + { + // Prediction moment + // The problem is client will dump the cartridge on the ground and the new server state + // won't correspond due to randomness so looks weird + // but we also need to always take it from the chamber or else ammocount won't be correct. + TransformSystem.DetachParentToNull(chambered.Value, Transform(chambered.Value)); + } + + UpdateAmmoCount(uid); + } + + if (user != null) + PopupSystem.PopupClient(Loc.GetString("gun-chamber-bolt-opened"), uid, user.Value); + + if (slots != null) + { + _slots.SetLock(uid, ChamberSlot, false, slots); + } + + Audio.PlayPredicted(component.BoltOpenedSound, uid, user); + } + + component.BoltClosed = value; + Dirty(uid, component); + } + + /// + /// Tries to take ammo from the magazine and insert into the chamber. + /// + private void CycleCartridge(EntityUid uid, ChamberMagazineAmmoProviderComponent component, EntityUid? user = null, AppearanceComponent? appearance = null) + { + // Try to put a new round in if possible. + var magEnt = GetMagazineEntity(uid); + + // Similar to what takeammo does though that uses an optimised version where + // multiple bullets may be fired in a single tick. + if (magEnt != null) + { + var relayedArgs = new TakeAmmoEvent(1, + new List<(EntityUid? Entity, IShootable Shootable)>(), + Transform(uid).Coordinates, + user); + RaiseLocalEvent(magEnt.Value, relayedArgs); + + if (relayedArgs.Ammo.Count > 0) + { + var newChamberEnt = relayedArgs.Ammo[0].Entity; + TryInsertChamber(uid, newChamberEnt!.Value); + var ammoEv = new GetAmmoCountEvent(); + RaiseLocalEvent(magEnt.Value, ref ammoEv); + FinaliseMagazineTakeAmmo(uid, component, ammoEv.Count, ammoEv.Capacity, user, appearance); + UpdateAmmoCount(uid); + + // Clientside reconciliation things + if (_netManager.IsClient) + { + foreach (var (ent, _) in relayedArgs.Ammo) + { + Del(ent!.Value); + } + } + } + else + { + UpdateAmmoCount(uid); + } + } + } + + public void ToggleBolt(EntityUid uid, ChamberMagazineAmmoProviderComponent component, EntityUid? user = null) + { + if (component.BoltClosed == null) + return; + + SetBoltClosed(uid, component, !component.BoltClosed.Value, user); + } + private void OnChamberMagazineExamine(EntityUid uid, ChamberMagazineAmmoProviderComponent component, ExaminedEvent args) { if (!args.IsInDetailsRange) return; var (count, _) = GetChamberMagazineCountCapacity(uid, component); + + if (component.BoltClosed != null) + { + args.PushMarkup(Loc.GetString("gun-chamber-bolt", ("bolt", component.BoltClosed), ("color", component.BoltClosed.Value ? Color.FromHex("#94e1f2") : Color.FromHex("#f29d94")))); + } + args.PushMarkup(Loc.GetString("gun-magazine-examine", ("color", AmmoExamineColor), ("count", count))); } @@ -88,52 +313,80 @@ public abstract partial class SharedGunSystem private void OnChamberMagazineTakeAmmo(EntityUid uid, ChamberMagazineAmmoProviderComponent component, TakeAmmoEvent args) { + if (component.BoltClosed == false) + { + args.Reason = Loc.GetString("gun-chamber-bolt-ammo"); + return; + } + // So chamber logic is kinda sussier than the others // Essentially we want to treat the chamber as a potentially free slot and then the mag as the remaining slots // i.e. if we shoot 3 times, then we use the chamber once (regardless if it's empty or not) and 2 from the mag // We move the n + 1 shot into the chamber as we essentially treat it like a stack. TryComp(uid, out var appearance); - if (TryTakeChamberEntity(uid, out var chamberEnt)) + EntityUid? chamberEnt; + + // Normal behaviour for guns. + if (component.AutoCycle) { + if (TryTakeChamberEntity(uid, out chamberEnt)) + { + args.Ammo.Add((chamberEnt.Value, EnsureComp(chamberEnt.Value))); + } + // No ammo returned. + else + { + return; + } + + var magEnt = GetMagazineEntity(uid); + + // Pass an event to the magazine to get more (to refill chamber or for shooting). + if (magEnt != null) + { + // We pass in Shots not Shots - 1 as we'll take the last entity and move it into the chamber. + var relayedArgs = new TakeAmmoEvent(args.Shots, new List<(EntityUid? Entity, IShootable Shootable)>(), args.Coordinates, args.User); + RaiseLocalEvent(magEnt.Value, relayedArgs); + + // Put in the nth slot back into the chamber + // Rest of the ammo gets shot + if (relayedArgs.Ammo.Count > 0) + { + var newChamberEnt = relayedArgs.Ammo[^1].Entity; + TryInsertChamber(uid, newChamberEnt!.Value); + } + + // Anything above the chamber-refill amount gets fired. + for (var i = 0; i < relayedArgs.Ammo.Count - 1; i++) + { + args.Ammo.Add(relayedArgs.Ammo[i]); + } + + // If no more ammo then open bolt. + if (relayedArgs.Ammo.Count == 0) + { + SetBoltClosed(uid, component, false, user: args.User, appearance: appearance); + } + } + else + { + Appearance.SetData(uid, AmmoVisuals.MagLoaded, false, appearance); + return; + } + + var ammoEv = new GetAmmoCountEvent(); + RaiseLocalEvent(magEnt.Value, ref ammoEv); + + FinaliseMagazineTakeAmmo(uid, component, ammoEv.Count, ammoEv.Capacity, args.User, appearance); + } + // If gun doesn't autocycle (e.g. bolt-action weapons) then we leave the chambered entity in there but still return it. + else if (Containers.TryGetContainer(uid, ChamberSlot, out var container) && + container is ContainerSlot { ContainedEntity: not null } slot) + { + // Shooting code won't eject it if it's still contained. + chamberEnt = slot.ContainedEntity; args.Ammo.Add((chamberEnt.Value, EnsureComp(chamberEnt.Value))); } - - var magEnt = GetMagazineEntity(uid); - - // Pass an event to the magazine to get more (to refill chamber or for shooting). - if (magEnt != null) - { - // We pass in Shots not Shots - 1 as we'll take the last entity and move it into the chamber. - var relayedArgs = new TakeAmmoEvent(args.Shots, new List<(EntityUid? Entity, IShootable Shootable)>(), args.Coordinates, args.User); - RaiseLocalEvent(magEnt.Value, relayedArgs); - - // Put in the nth slot back into the chamber - // Rest of the ammo gets shot - if (relayedArgs.Ammo.Count > 0) - { - var newChamberEnt = relayedArgs.Ammo[^1].Entity; - TryInsertChamber(uid, newChamberEnt!.Value); - } - - // Anything above the chamber-refill amount gets fired. - for (var i = 0; i < relayedArgs.Ammo.Count - 1; i++) - { - args.Ammo.Add(relayedArgs.Ammo[i]); - } - } - else - { - Appearance.SetData(uid, AmmoVisuals.MagLoaded, false, appearance); - return; - } - - var count = chamberEnt != null ? 1 : 0; - const int capacity = 1; - - var ammoEv = new GetAmmoCountEvent(); - RaiseLocalEvent(magEnt.Value, ref ammoEv); - - FinaliseMagazineTakeAmmo(uid, component, args, count + ammoEv.Count, capacity + ammoEv.Capacity, appearance); } } diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs index 669c49aefa..0f2a631644 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Clothing.cs @@ -32,7 +32,7 @@ public partial class SharedGunSystem private bool TryGetClothingSlotEntity(EntityUid uid, ClothingSlotAmmoProviderComponent component, [NotNullWhen(true)] out EntityUid? slotEntity) { slotEntity = null; - if (!_container.TryGetContainingContainer(uid, out var container)) + if (!Containers.TryGetContainingContainer(uid, out var container)) return false; var user = container.Owner; diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Container.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Container.cs index 23e2d94e1f..999d5379a2 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Container.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Container.cs @@ -8,9 +8,6 @@ namespace Content.Shared.Weapons.Ranged.Systems; public partial class SharedGunSystem { - [Dependency] private readonly INetManager _netMan = default!; - [Dependency] private readonly SharedContainerSystem _container = default!; - private void InitializeContainer() { SubscribeLocalEvent(OnContainerTakeAmmo); @@ -20,7 +17,7 @@ public partial class SharedGunSystem private void OnContainerTakeAmmo(EntityUid uid, ContainerAmmoProviderComponent component, TakeAmmoEvent args) { component.ProviderUid ??= uid; - if (!_container.TryGetContainer(component.ProviderUid.Value, component.Container, out var container)) + if (!Containers.TryGetContainer(component.ProviderUid.Value, component.Container, out var container)) return; for (var i = 0; i < args.Shots; i++) @@ -30,7 +27,7 @@ public partial class SharedGunSystem var ent = container.ContainedEntities[0]; - if (_netMan.IsServer) + if (_netManager.IsServer) container.Remove(ent); args.Ammo.Add((ent, EnsureComp(ent))); @@ -40,7 +37,7 @@ public partial class SharedGunSystem private void OnContainerAmmoCount(EntityUid uid, ContainerAmmoProviderComponent component, ref GetAmmoCountEvent args) { component.ProviderUid ??= uid; - if (!_container.TryGetContainer(component.ProviderUid.Value, component.Container, out var container)) + if (!Containers.TryGetContainer(component.ProviderUid.Value, component.Container, out var container)) { args.Capacity = 0; args.Count = 0; diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Magazine.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Magazine.cs index a0375e3b4a..57db1d2b9c 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Magazine.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.Magazine.cs @@ -66,7 +66,13 @@ public abstract partial class SharedGunSystem if (!TryComp(uid, out var appearance)) return; - Appearance.SetData(uid, AmmoVisuals.MagLoaded, GetMagazineEntity(uid) != null, appearance); + var magEnt = GetMagazineEntity(uid); + Appearance.SetData(uid, AmmoVisuals.MagLoaded, magEnt != null, appearance); + + if (magEnt != null) + { + UpdateMagazineAppearance(uid, component, magEnt.Value); + } } protected (int, int) GetMagazineCountCapacity(EntityUid uid, MagazineAmmoProviderComponent component) @@ -124,16 +130,16 @@ public abstract partial class SharedGunSystem var ammoEv = new GetAmmoCountEvent(); RaiseLocalEvent(magEntity.Value, ref ammoEv); - FinaliseMagazineTakeAmmo(uid, component, args, ammoEv.Count, ammoEv.Capacity, appearance); + FinaliseMagazineTakeAmmo(uid, component, ammoEv.Count, ammoEv.Capacity, args.User, appearance); } - private void FinaliseMagazineTakeAmmo(EntityUid uid, MagazineAmmoProviderComponent component, TakeAmmoEvent args, int count, int capacity, AppearanceComponent? appearance) + private void FinaliseMagazineTakeAmmo(EntityUid uid, MagazineAmmoProviderComponent component, int count, int capacity, EntityUid? user, AppearanceComponent? appearance) { // If no ammo then check for autoeject - if (component.AutoEject && args.Ammo.Count == 0) + if (component.AutoEject && count == 0) { EjectMagazine(uid, component); - Audio.PlayPredicted(component.SoundAutoEject, uid, args.User); + Audio.PlayPredicted(component.SoundAutoEject, uid, user); } UpdateMagazineAppearance(uid, appearance, true, count, capacity); @@ -146,12 +152,6 @@ public abstract partial class SharedGunSystem var count = 0; var capacity = 0; - if (component is ChamberMagazineAmmoProviderComponent chamber) - { - count = GetChamberEntity(uid) != null ? 1 : 0; - capacity = 1; - } - if (TryComp(magEnt, out var magAppearance)) { Appearance.TryGetData(magEnt, AmmoVisuals.AmmoCount, out var addCount, magAppearance); diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index c72deb5956..cbf48432f9 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -307,6 +307,11 @@ public abstract partial class SharedGunSystem : EntitySystem // If they're firing an existing clip then don't play anything. if (shots > 0) { + if (ev.Reason != null) + { + PopupSystem.PopupClient(ev.Reason, gunUid, user); + } + // Don't spam safety sounds at gun fire rate, play it at a reduced rate. // May cause prediction issues? Needs more tweaking gun.NextFire = TimeSpan.FromSeconds(Math.Max(lastFire.TotalSeconds + SafetyNextFire, gun.NextFire.TotalSeconds)); @@ -467,4 +472,5 @@ public enum AmmoVisuals : byte AmmoMax, HasAmmo, // used for generic visualizers. c# stuff can just check ammocount != 0 MagLoaded, + BoltClosed, } diff --git a/Content.Shared/Wieldable/WieldableSystem.cs b/Content.Shared/Wieldable/WieldableSystem.cs index 31e462c6af..952ce3a378 100644 --- a/Content.Shared/Wieldable/WieldableSystem.cs +++ b/Content.Shared/Wieldable/WieldableSystem.cs @@ -111,6 +111,9 @@ public sealed class WieldableSystem : EntitySystem { if (args.Handled) return; + + args.Handled = true; + if(!component.Wielded) AttemptWield(uid, component, args.User); else diff --git a/Resources/Locale/en-US/weapons/ranged/gun.ftl b/Resources/Locale/en-US/weapons/ranged/gun.ftl index b1e75acf0c..5982934215 100644 --- a/Resources/Locale/en-US/weapons/ranged/gun.ftl +++ b/Resources/Locale/en-US/weapons/ranged/gun.ftl @@ -26,6 +26,15 @@ gun-cartridge-unspent = It is [color=lime]not spent[/color]. # BatteryAmmoProvider gun-battery-examine = It has enough charge for [color={$color}]{$count}[/color] shots. +# CartridgeAmmoProvider +gun-chamber-bolt-ammo = Gun not bolted +gun-chamber-bolt = The bolt is [color={$color}]{$bolt}[/color]. +gun-chamber-bolt-closed = Closed bolt +gun-chamber-bolt-opened = Opened bolt +gun-chamber-bolt-close = Close bolt +gun-chamber-bolt-open = Open bolt +gun-chamber-rack = Rack + # MagazineAmmoProvider gun-magazine-examine = It has [color={$color}]{$count}[/color] shots remaining. diff --git a/Resources/Prototypes/Entities/Debugging/debug_sweps.yml b/Resources/Prototypes/Entities/Debugging/debug_sweps.yml index 27546e4c58..862735ab13 100644 --- a/Resources/Prototypes/Entities/Debugging/debug_sweps.yml +++ b/Resources/Prototypes/Entities/Debugging/debug_sweps.yml @@ -10,6 +10,7 @@ - Debug - type: Sprite sprite: Objects/Weapons/Guns/Pistols/debug.rsi + state: icon - type: Clothing sprite: Objects/Weapons/Guns/Pistols/debug.rsi - type: Gun diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml index f83e6420ed..1d16d308e4 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml @@ -31,6 +31,8 @@ soundEmpty: path: /Audio/Weapons/Guns/Empty/lmg_empty.ogg - type: ChamberMagazineAmmoProvider + soundRack: + path: /Audio/Weapons/Guns/Cock/lmg_cock.ogg - type: AmmoCounter - type: ItemSlots slots: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml index 4be8f44de1..3796ac92b8 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -45,7 +45,6 @@ whitelist: tags: - Grenade - autoCycle: false capacity: 3 proto: GrenadeFrag soundInsert: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml index ae7e02444a..ff098b32f9 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml @@ -28,6 +28,8 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/pistol.ogg - type: ChamberMagazineAmmoProvider + soundRack: + path: /Audio/Weapons/Guns/Cock/pistol_cock.ogg - type: ItemSlots slots: gun_magazine: @@ -108,6 +110,8 @@ map: ["enum.GunVisualLayers.Mag"] - type: Clothing sprite: Objects/Weapons/Guns/Pistols/cobra.rsi + - type: ChamberMagazineAmmoProvider + boltClosed: null - type: Gun fireRate: 4 soundGunshot: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml index c35c49da95..114573c087 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml @@ -23,6 +23,8 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/batrifle.ogg - type: ChamberMagazineAmmoProvider + soundRack: + path: /Audio/Weapons/Guns/Cock/sf_rifle_cock.ogg - type: ItemSlots slots: gun_magazine: @@ -66,6 +68,8 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/rifle2.ogg - type: ChamberMagazineAmmoProvider + soundRack: + path: /Audio/Weapons/Guns/Cock/ltrifle_cock.ogg - type: ItemSlots slots: gun_magazine: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml index 7d572d49e6..e423c09841 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml @@ -28,6 +28,8 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/smg.ogg - type: ChamberMagazineAmmoProvider + soundRack: + path: /Audio/Weapons/Guns/Cock/smg_cock.ogg - type: ItemSlots slots: gun_magazine: @@ -95,7 +97,7 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/c-20r.ogg - type: ChamberMagazineAmmoProvider - # autoEject: true # Do not set this until the PVS prediction issue is resolved + autoEject: true - type: MagazineVisuals magState: mag steps: 6 @@ -216,6 +218,8 @@ shader: unshaded - type: Clothing sprite: Objects/Weapons/Guns/SMGs/wt550.rsi + - type: ChamberMagazineAmmoProvider + boltClosed: null - type: Gun fireRate: 5 selectedMode: FullAuto diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 4197905714..4bee243d57 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -29,7 +29,6 @@ soundEmpty: path: /Audio/Weapons/Guns/Empty/empty.ogg - type: BallisticAmmoProvider - autoCycle: false whitelist: tags: - ShellShotgun @@ -266,4 +265,4 @@ id: WeaponShotgunImprovisedLoaded components: - type: BallisticAmmoProvider - proto: ShellShotgunImprovised \ No newline at end of file + proto: ShellShotgunImprovised diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml index 213e5d4155..63a06c266d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml @@ -25,7 +25,6 @@ soundGunshot: path: /Audio/Weapons/Guns/Gunshots/sniper.ogg - type: BallisticAmmoProvider - autoCycle: false capacity: 10 proto: CartridgeLightRifle whitelist: diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml index 9fb02f7bed..b2ad3ff702 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/turrets.yml @@ -156,7 +156,6 @@ - type: BallisticAmmoProvider proto: CartridgePistol capacity: 50 - cycleable: false - type: Construction deconstructionTarget: null graph: WeaponTurretSyndicateDisposable diff --git a/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/bolt-open.png new file mode 100644 index 0000000000..7a3df10c8b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/meta.json index d6806ab228..7dc67f28bd 100644 --- a/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/LMGs/l6.rsi/meta.json @@ -6,44 +6,47 @@ "x": 32, "y": 32 }, - "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "mag-1" - }, - { - "name": "mag-2" - }, - { - "name": "mag-3" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "wielded-inhand-left", - "directions": 4 - }, - { - "name": "wielded-inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } - ] + "states": [ + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "mag-1" + }, + { + "name": "mag-2" + }, + { + "name": "mag-3" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "wielded-inhand-left", + "directions": 4 + }, + { + "name": "wielded-inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } + ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/bolt-open.png new file mode 100644 index 0000000000..1bd788874b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/meta.json index dab75b56c6..b7d464cbb7 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/bolt-open.png new file mode 100644 index 0000000000..2d1d1d0205 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/meta.json index 1afe5f6ad6..707c54c0bb 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Pistols/mk58.rsi/meta.json @@ -13,6 +13,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "mag-0" }, diff --git a/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/bolt-open.png new file mode 100644 index 0000000000..d1fe874ec7 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/meta.json index b2cdaede10..b611235f4d 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Pistols/viper.rsi/meta.json @@ -13,6 +13,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "mag-0" }, @@ -27,9 +30,9 @@ "name": "inhand-right", "directions": 4 }, - { - "name": "equipped-BELT", - "directions": 4 - } + { + "name": "equipped-BELT", + "directions": 4 + } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/bolt-open.png new file mode 100644 index 0000000000..8cb0656e68 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/meta.json index a22d42c872..f24ef91bcf 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Revolvers/inspector.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/bolt-open.png new file mode 100644 index 0000000000..f38ef5b369 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/meta.json index a22d42c872..f24ef91bcf 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Revolvers/mateba.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/bolt-open.png new file mode 100644 index 0000000000..3e021f2ccb Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/meta.json index 13dd3228e9..504a793820 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Revolvers/pirate_revolver.rsi/meta.json @@ -6,21 +6,24 @@ "x": 32, "y": 32 }, - "states": [ - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "icon" - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BELT", - "directions": 4 - } - ] + "states": [ + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "icon" + }, + { + "name": "bolt-open" + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BELT", + "directions": 4 + } + ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/bolt-open.png new file mode 100644 index 0000000000..15c38dcf5b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/meta.json index 30136fa39b..781b1e11b5 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Revolvers/python.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/bolt-open.png new file mode 100644 index 0000000000..f1c3d60963 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/meta.json index 6749a5ecca..5f57a1e7a6 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Rifles/ak.rsi/meta.json @@ -13,6 +13,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "mag-0" }, diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png new file mode 100644 index 0000000000..477b65066e Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json index 596211bc7f..9c6c4cdeab 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Rifles/carbine.rsi/meta.json @@ -7,26 +7,29 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/bolt-open.png new file mode 100644 index 0000000000..0781d7099b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/meta.json index 1658afae5d..bfcf15bd15 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Rifles/lecter.rsi/meta.json @@ -13,6 +13,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "mag-0" }, diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/bolt-open.png new file mode 100644 index 0000000000..0f083b8afb Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/meta.json index ea2a077cb4..31389e9102 100644 --- a/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/SMGs/atreides.rsi/meta.json @@ -7,29 +7,32 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "suppressor" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "suppressor" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/bolt-open.png new file mode 100644 index 0000000000..ee7f561033 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/meta.json index 46fe76f054..979ecfc388 100644 --- a/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/meta.json @@ -7,44 +7,47 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "mag-1" - }, - { - "name": "mag-2" - }, - { - "name": "mag-3" - }, - { - "name": "mag-4" - }, - { - "name": "mag-5" - }, - { - "name": "suppressor" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "mag-1" + }, + { + "name": "mag-2" + }, + { + "name": "mag-3" + }, + { + "name": "mag-4" + }, + { + "name": "mag-5" + }, + { + "name": "suppressor" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/bolt-open.png new file mode 100644 index 0000000000..f534d46c0b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/meta.json index 1f802b3647..1109258b60 100644 --- a/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/SMGs/drozd.rsi/meta.json @@ -13,6 +13,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "mag-0" }, diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/bolt-open.png new file mode 100644 index 0000000000..f616d25f87 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/meta.json index 79ab6b4bd4..099ca8bc55 100644 --- a/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/SMGs/vector.rsi/meta.json @@ -7,26 +7,29 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/bolt-open.png new file mode 100644 index 0000000000..be83522b3c Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/meta.json index 5c9dfff9ea..f55fd2db20 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/blunderbuss.rsi/meta.json @@ -6,17 +6,20 @@ "x": 32, "y": 32 }, - "states": [ - { - "name": "icon" - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "inhand-left", - "directions": 4 - } - ] + "states": [ + { + "name": "icon" + }, + { + "name": "bolt-open" + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + } + ] } diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/bolt-open.png new file mode 100644 index 0000000000..8d9e472946 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/meta.json index 3358222de3..fe7b4c0449 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/bulldog.rsi/meta.json @@ -7,26 +7,29 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "base" - }, - { - "name": "mag-0" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "base" + }, + { + "name": "bolt-open" + }, + { + "name": "mag-0" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/bolt-open.png new file mode 100644 index 0000000000..dcbe062978 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/meta.json index 24607e6aaf..33e5cae834 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/db_shotgun.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/bolt-open.png new file mode 100644 index 0000000000..c794549c55 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/meta.json index 840b7790ff..2aed9f90d0 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/enforcer.rsi/meta.json @@ -7,20 +7,23 @@ "y": 32 }, "states": [ - { - "name": "icon" - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "equipped-BACKPACK", - "directions": 4 - } + { + "name": "icon" + }, + { + "name": "bolt-open" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BACKPACK", + "directions": 4 + } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/bolt-open.png new file mode 100644 index 0000000000..93f2b28fcd Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/meta.json index 54635ca513..6358c26299 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/flaregun.rsi/meta.json @@ -6,21 +6,24 @@ "x": 32, "y": 32 }, - "states": [ - { - "name": "icon" - }, - { - "name": "inhand-right", - "directions": 4 - }, - { - "name": "inhand-left", - "directions": 4 - }, - { - "name": "equipped-BELT", - "directions": 4 - } - ] -} \ No newline at end of file + "states": [ + { + "name": "icon" + }, + { + "name": "bolt-open" + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "equipped-BELT", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/bolt-open.png new file mode 100644 index 0000000000..39ce0a760b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/meta.json index c1d9eabe38..4e592b59a4 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/hm_pistol.rsi/meta.json @@ -11,6 +11,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/bolt-open.png new file mode 100644 index 0000000000..cf99a2c2d5 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/meta.json index 6931d0fd3d..2839d6e45d 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/pump.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/bolt-open.png new file mode 100644 index 0000000000..f4b03e4603 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/meta.json index 677cb71adf..04f71999e1 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Shotguns/sawn.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "icon" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/bolt-open.png new file mode 100644 index 0000000000..ac2ebfe1cf Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/meta.json index 81e977c298..a959ed58f6 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4 diff --git a/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/bolt-open.png b/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/bolt-open.png new file mode 100644 index 0000000000..28fc5ba1c1 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/bolt-open.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/meta.json index a46eb7d96d..ffe748ea8d 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Snipers/heavy_sniper.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "base" }, + { + "name": "bolt-open" + }, { "name": "inhand-left", "directions": 4