From e8b2d0a844d43a4f7f87fe0ffe9e1d810951dba9 Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Sun, 5 Dec 2021 16:23:47 +1300
Subject: [PATCH] Make BatteryBarrelComponent use item slots. (#5591)
---
.../ClientBatteryBarrelComponent.cs | 17 ++
.../Weapon/Ranged/Barrels/BarrelSystem.cs | 48 +---
.../Components/BoltActionBarrelComponent.cs | 6 +-
.../Barrels/Components/PumpBarrelComponent.cs | 6 +-
.../Components/RevolverBarrelComponent.cs | 6 +-
.../ServerBatteryBarrelComponent.cs | 122 ++-------
.../ServerMagazineBarrelComponent.cs | 6 +-
.../Components/ServerRangedBarrelComponent.cs | 10 +-
.../Containers/ItemSlot/ItemSlotsComponent.cs | 19 ++
.../Containers/ItemSlot/ItemSlotsSystem.cs | 26 +-
.../Weapons/Guns/Battery/battery_guns.yml | 252 ++++++------------
11 files changed, 184 insertions(+), 334 deletions(-)
diff --git a/Content.Client/Weapons/Ranged/Barrels/Components/ClientBatteryBarrelComponent.cs b/Content.Client/Weapons/Ranged/Barrels/Components/ClientBatteryBarrelComponent.cs
index f84355b22b..70e2e5c4c2 100644
--- a/Content.Client/Weapons/Ranged/Barrels/Components/ClientBatteryBarrelComponent.cs
+++ b/Content.Client/Weapons/Ranged/Barrels/Components/ClientBatteryBarrelComponent.cs
@@ -1,6 +1,7 @@
using System;
using Content.Client.Items.Components;
using Content.Client.Stylesheets;
+using Content.Shared.Containers.ItemSlots;
using Content.Shared.Weapons.Ranged.Barrels.Components;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
@@ -8,6 +9,7 @@ using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Maths;
+using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using static Robust.Client.UserInterface.Controls.BoxContainer;
@@ -21,6 +23,9 @@ namespace Content.Client.Weapons.Ranged.Barrels.Components
private StatusControl? _statusControl;
+ [DataField("cellSlot", required: true)]
+ public ItemSlot CellSlot = default!;
+
///
/// Count of bullets in the magazine.
///
@@ -30,6 +35,18 @@ namespace Content.Client.Weapons.Ranged.Barrels.Components
[ViewVariables]
public (int count, int max)? MagazineCount { get; private set; }
+ protected override void Initialize()
+ {
+ base.Initialize();
+ EntitySystem.Get().AddItemSlot(OwnerUid, $"{Name}-powercell-container", CellSlot);
+ }
+
+ protected override void OnRemove()
+ {
+ base.OnRemove();
+ EntitySystem.Get().RemoveItemSlot(OwnerUid, CellSlot);
+ }
+
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
{
base.HandleComponentState(curState, nextState);
diff --git a/Content.Server/Weapon/Ranged/Barrels/BarrelSystem.cs b/Content.Server/Weapon/Ranged/Barrels/BarrelSystem.cs
index 7c07749499..c1591926b4 100644
--- a/Content.Server/Weapon/Ranged/Barrels/BarrelSystem.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/BarrelSystem.cs
@@ -3,9 +3,11 @@ using Content.Server.Weapon.Ranged.Barrels.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.Popups;
using Content.Shared.Verbs;
+using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
+using System;
namespace Content.Server.Weapon.Ranged.Barrels
{
@@ -19,8 +21,8 @@ namespace Content.Server.Weapon.Ranged.Barrels
SubscribeLocalEvent(AddSpinVerb);
- SubscribeLocalEvent(AddEjectCellVerb);
- SubscribeLocalEvent(AddInsertCellVerb);
+ SubscribeLocalEvent(OnCellSlotUpdated);
+ SubscribeLocalEvent(OnCellSlotUpdated);
SubscribeLocalEvent(AddToggleBoltVerb);
@@ -28,6 +30,12 @@ namespace Content.Server.Weapon.Ranged.Barrels
SubscribeLocalEvent(AddEjectMagazineVerb);
}
+ private void OnCellSlotUpdated(EntityUid uid, ServerBatteryBarrelComponent component, ContainerModifiedMessage args)
+ {
+ if (args.Container.ID == component.CellSlot.ID)
+ component.UpdateAppearance();
+ }
+
private void AddSpinVerb(EntityUid uid, RevolverBarrelComponent component, GetAlternativeVerbsEvent args)
{
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
@@ -62,42 +70,6 @@ namespace Content.Server.Weapon.Ranged.Barrels
args.Verbs.Add(verb);
}
- // TODO VERBS EJECTABLES Standardize eject/insert verbs into a single system?
- // Really, why isn't this just PowerCellSlotComponent?
- private void AddEjectCellVerb(EntityUid uid, ServerBatteryBarrelComponent component, GetAlternativeVerbsEvent args)
- {
- if (args.Hands == null ||
- !args.CanAccess ||
- !args.CanInteract ||
- !component.PowerCellRemovable ||
- component.PowerCell == null ||
- !_actionBlockerSystem.CanPickup(args.User.Uid))
- return;
-
- Verb verb = new();
- verb.Text = component.PowerCell.Owner.Name;
- verb.Category = VerbCategory.Eject;
- verb.Act = () => component.TryEjectCell(args.User);
- args.Verbs.Add(verb);
- }
-
- private void AddInsertCellVerb(EntityUid uid, ServerBatteryBarrelComponent component, GetInteractionVerbsEvent args)
- {
- if (args.Using == null ||
- !args.CanAccess ||
- !args.CanInteract ||
- component.PowerCell != null ||
- !args.Using.HasComponent() ||
- !_actionBlockerSystem.CanDrop(args.User.Uid))
- return;
-
- Verb verb = new();
- verb.Text = args.Using.Name;
- verb.Category = VerbCategory.Insert;
- verb.Act = () => component.TryInsertPowerCell(args.Using);
- args.Verbs.Add(verb);
- }
-
private void AddEjectMagazineVerb(EntityUid uid, ServerMagazineBarrelComponent component, GetAlternativeVerbsEvent args)
{
if (args.Hands == null ||
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/BoltActionBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/BoltActionBarrelComponent.cs
index a59ea86059..1023b1da09 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/BoltActionBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/BoltActionBarrelComponent.cs
@@ -26,7 +26,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
[RegisterComponent]
[NetworkedComponent()]
#pragma warning disable 618
- public sealed class BoltActionBarrelComponent : ServerRangedBarrelComponent, IMapInit, IExamine
+ public sealed class BoltActionBarrelComponent : ServerRangedBarrelComponent, IUse, IInteractUsing, IMapInit, IExamine
#pragma warning restore 618
{
// Originally I had this logic shared with PumpBarrel and used a couple of variables to control things
@@ -267,7 +267,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
return false;
}
- public override bool UseEntity(UseEntityEventArgs eventArgs)
+ public bool UseEntity(UseEntityEventArgs eventArgs)
{
if (BoltOpen)
{
@@ -281,7 +281,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
return true;
}
- public override async Task InteractUsing(InteractUsingEventArgs eventArgs)
+ public async Task InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs.User, eventArgs.Using);
}
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/PumpBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/PumpBarrelComponent.cs
index 5fba188d50..c53f50c58a 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/PumpBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/PumpBarrelComponent.cs
@@ -25,7 +25,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
///
[RegisterComponent]
[NetworkedComponent()]
- public sealed class PumpBarrelComponent : ServerRangedBarrelComponent, IMapInit, ISerializationHooks
+ public sealed class PumpBarrelComponent : ServerRangedBarrelComponent, IUse, IInteractUsing, IMapInit, ISerializationHooks
{
public override string Name => "PumpBarrel";
@@ -223,13 +223,13 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
return false;
}
- public override bool UseEntity(UseEntityEventArgs eventArgs)
+ public bool UseEntity(UseEntityEventArgs eventArgs)
{
Cycle(true);
return true;
}
- public override async Task InteractUsing(InteractUsingEventArgs eventArgs)
+ public async Task InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs);
}
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/RevolverBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/RevolverBarrelComponent.cs
index bb74085113..c6f4735ada 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/RevolverBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/RevolverBarrelComponent.cs
@@ -23,7 +23,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
{
[RegisterComponent]
[NetworkedComponent()]
- public sealed class RevolverBarrelComponent : ServerRangedBarrelComponent, ISerializationHooks
+ public sealed class RevolverBarrelComponent : ServerRangedBarrelComponent, IUse, IInteractUsing, ISerializationHooks
{
[Dependency] private readonly IRobustRandom _random = default!;
@@ -253,7 +253,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
///
///
///
- public override bool UseEntity(UseEntityEventArgs eventArgs)
+ public bool UseEntity(UseEntityEventArgs eventArgs)
{
EjectAllSlots();
Dirty();
@@ -261,7 +261,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
return true;
}
- public override async Task InteractUsing(InteractUsingEventArgs eventArgs)
+ public async Task InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs.User, eventArgs.Using);
}
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs
index 71a7ccab61..256d3732b6 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/ServerBatteryBarrelComponent.cs
@@ -1,18 +1,12 @@
using System;
-using System.Threading.Tasks;
-using Content.Server.Hands.Components;
-using Content.Server.Items;
using Content.Server.Power.Components;
using Content.Server.Projectiles.Components;
-using Content.Shared.Interaction;
-using Content.Shared.Sound;
+using Content.Shared.Containers.ItemSlots;
using Content.Shared.Weapons.Ranged.Barrels.Components;
-using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
-using Robust.Shared.Player;
using Robust.Shared.Players;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
@@ -25,6 +19,9 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
{
public override string Name => "BatteryBarrel";
+ [DataField("cellSlot", required: true)]
+ public ItemSlot CellSlot = new();
+
// The minimum change we need before we can fire
[DataField("lowerChargeLimit")]
[ViewVariables] private float _lowerChargeLimit = 10;
@@ -34,20 +31,14 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
[DataField("ammoPrototype")]
[ViewVariables] private string? _ammoPrototype;
- [ViewVariables] public IEntity? PowerCellEntity => _powerCellContainer.ContainedEntity;
- public BatteryComponent? PowerCell => _powerCellContainer.ContainedEntity?.GetComponentOrNull();
- private ContainerSlot _powerCellContainer = default!;
+ public BatteryComponent? PowerCell => CellSlot.Item?.GetComponentOrNull();
private ContainerSlot _ammoContainer = default!;
- [DataField("powerCellPrototype")]
- private string? _powerCellPrototype = default;
- [DataField("powerCellRemovable")]
- [ViewVariables] public bool PowerCellRemovable = default;
public override int ShotsLeft
{
get
{
- var powerCell = _powerCellContainer.ContainedEntity;
+ var powerCell = CellSlot.Item;
if (powerCell == null)
{
@@ -62,7 +53,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
{
get
{
- var powerCell = _powerCellContainer.ContainedEntity;
+ var powerCell = CellSlot.Item;
if (powerCell == null)
{
@@ -75,12 +66,6 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
private AppearanceComponent? _appearanceComponent;
- // Sounds
- [DataField("soundPowerCellInsert", required: true)]
- private SoundSpecifier _soundPowerCellInsert = default!;
- [DataField("soundPowerCellEject", required: true)]
- private SoundSpecifier _soundPowerCellEject = default!;
-
public override ComponentState GetComponentState()
{
(int, int)? count = (ShotsLeft, Capacity);
@@ -93,12 +78,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
protected override void Initialize()
{
base.Initialize();
- _powerCellContainer = ContainerHelpers.EnsureContainer(Owner, $"{Name}-powercell-container", out var existing);
- if (!existing && _powerCellPrototype != null)
- {
- var powerCellEntity = Owner.EntityManager.SpawnEntity(_powerCellPrototype, Owner.Transform.Coordinates);
- _powerCellContainer.Insert(powerCellEntity);
- }
+ EntitySystem.Get().AddItemSlot(OwnerUid, $"{Name}-powercell-container", CellSlot);
if (_ammoPrototype != null)
{
@@ -112,6 +92,12 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
Dirty();
}
+ protected override void OnRemove()
+ {
+ base.OnRemove();
+ EntitySystem.Get().RemoveItemSlot(OwnerUid, CellSlot);
+ }
+
protected override void Startup()
{
base.Startup();
@@ -120,7 +106,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
public void UpdateAppearance()
{
- _appearanceComponent?.SetData(MagazineBarrelVisuals.MagLoaded, _powerCellContainer.ContainedEntity != null);
+ _appearanceComponent?.SetData(MagazineBarrelVisuals.MagLoaded, CellSlot.HasItem);
_appearanceComponent?.SetData(AmmoVisuals.AmmoCount, ShotsLeft);
_appearanceComponent?.SetData(AmmoVisuals.AmmoMax, Capacity);
Dirty();
@@ -142,7 +128,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
public override IEntity? TakeProjectile(EntityCoordinates spawnAt)
{
- var powerCellEntity = _powerCellContainer.ContainedEntity;
+ var powerCellEntity = CellSlot.Item;
if (powerCellEntity == null)
{
@@ -197,81 +183,5 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
UpdateAppearance();
return entity;
}
-
- public bool TryInsertPowerCell(IEntity entity)
- {
- if (_powerCellContainer.ContainedEntity != null)
- {
- return false;
- }
-
- if (!entity.HasComponent())
- {
- return false;
- }
-
- SoundSystem.Play(Filter.Pvs(Owner), _soundPowerCellInsert.GetSound(), Owner, AudioParams.Default.WithVolume(-2));
-
- _powerCellContainer.Insert(entity);
-
- Dirty();
- UpdateAppearance();
- return true;
- }
-
- public override bool UseEntity(UseEntityEventArgs eventArgs)
- {
- if (!PowerCellRemovable)
- {
- return false;
- }
-
- if (PowerCellEntity == null)
- {
- return false;
- }
-
- return TryEjectCell(eventArgs.User);
- }
-
- public bool TryEjectCell(IEntity user)
- {
- if (PowerCell == null || !PowerCellRemovable)
- {
- return false;
- }
-
- if (!user.TryGetComponent(out HandsComponent? hands))
- {
- return false;
- }
-
- var cell = PowerCell;
- if (!_powerCellContainer.Remove(cell.Owner))
- {
- return false;
- }
-
- Dirty();
- UpdateAppearance();
-
- if (!hands.PutInHand(cell.Owner.GetComponent()))
- {
- cell.Owner.Transform.Coordinates = user.Transform.Coordinates;
- }
-
- SoundSystem.Play(Filter.Pvs(Owner), _soundPowerCellEject.GetSound(), Owner, AudioParams.Default.WithVolume(-2));
- return true;
- }
-
- public override async Task InteractUsing(InteractUsingEventArgs eventArgs)
- {
- if (!eventArgs.Using.HasComponent())
- {
- return false;
- }
-
- return TryInsertPowerCell(eventArgs.Using);
- }
}
}
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/ServerMagazineBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/ServerMagazineBarrelComponent.cs
index 67fd481c56..e7c055bb29 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/ServerMagazineBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/ServerMagazineBarrelComponent.cs
@@ -27,7 +27,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
[RegisterComponent]
[NetworkedComponent()]
#pragma warning disable 618
- public sealed class ServerMagazineBarrelComponent : ServerRangedBarrelComponent, IExamine
+ public sealed class ServerMagazineBarrelComponent : ServerRangedBarrelComponent, IUse, IInteractUsing, IExamine
#pragma warning restore 618
{
public override string Name => "MagazineBarrel";
@@ -248,7 +248,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
_appearanceComponent?.SetData(AmmoVisuals.AmmoMax, Capacity);
}
- public override bool UseEntity(UseEntityEventArgs eventArgs)
+ public bool UseEntity(UseEntityEventArgs eventArgs)
{
// Behavior:
// If bolt open just close it
@@ -393,7 +393,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
UpdateAppearance();
}
- public override async Task InteractUsing(InteractUsingEventArgs eventArgs)
+ public async Task InteractUsing(InteractUsingEventArgs eventArgs)
{
if (CanInsertMagazine(eventArgs.User, eventArgs.Using, quiet: false))
{
diff --git a/Content.Server/Weapon/Ranged/Barrels/Components/ServerRangedBarrelComponent.cs b/Content.Server/Weapon/Ranged/Barrels/Components/ServerRangedBarrelComponent.cs
index 2ed5f793da..208ec83e33 100644
--- a/Content.Server/Weapon/Ranged/Barrels/Components/ServerRangedBarrelComponent.cs
+++ b/Content.Server/Weapon/Ranged/Barrels/Components/ServerRangedBarrelComponent.cs
@@ -38,7 +38,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
/// Only difference between them is how they retrieve a projectile to shoot (battery, magazine, etc.)
///
#pragma warning disable 618
- public abstract class ServerRangedBarrelComponent : SharedRangedBarrelComponent, IUse, IInteractUsing, IExamine, ISerializationHooks
+ public abstract class ServerRangedBarrelComponent : SharedRangedBarrelComponent, IExamine, ISerializationHooks
#pragma warning restore 618
{
// There's still some of py01 and PJB's work left over, especially in underlying shooting logic,
@@ -135,9 +135,9 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
}
}
- protected override void OnAdd()
+ protected override void Initialize()
{
- base.OnAdd();
+ base.Initialize();
Owner.EnsureComponentWarn(out ServerRangedWeaponComponent rangedWeaponComponent);
@@ -169,10 +169,6 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
return angle;
}
- public abstract bool UseEntity(UseEntityEventArgs eventArgs);
-
- public abstract Task InteractUsing(InteractUsingEventArgs eventArgs);
-
public void ChangeFireSelector(FireRateSelector rateSelector)
{
if ((rateSelector & AllRateSelectors) != 0)
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
index 601759450a..9410b748c6 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsComponent.cs
@@ -1,6 +1,7 @@
using Content.Shared.Sound;
using Content.Shared.Whitelist;
using Robust.Shared.Analyzers;
+using Robust.Shared.Audio;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.Prototypes;
@@ -81,6 +82,12 @@ namespace Content.Shared.Containers.ItemSlots
public SoundSpecifier? EjectSound;
// maybe default to /Audio/Machines/id_swipe.ogg?
+ ///
+ /// Options used for playing the insert/eject sounds.
+ ///
+ [DataField("soundOptions")]
+ public AudioParams SoundOptions = AudioParams.Default;
+
///
/// The name of this item slot. This will be shown to the user in the verb menu.
///
@@ -116,6 +123,18 @@ namespace Content.Shared.Containers.ItemSlots
[DataField("ejectOnInteract")]
public bool EjectOnInteract = false;
+ ///
+ /// If true, and if this slot is attached to an item, then it will attempt to eject slot when to the slot is
+ /// used in the user's hands.
+ ///
+ ///
+ /// Desirable for things like ranged weapons ('Z' to eject), but not desirable for others (e.g., PDA uses
+ /// 'Z' to open UI). Unlike , this will not make any changes to the context
+ /// menu, nor will it disable alt-click interactions.
+ ///
+ [DataField("ejectOnUse")]
+ public bool EjectOnUse = false;
+
///
/// Override the insert verb text. Defaults to [insert category] -> [item-name]. If not null, the verb will
/// not be given a category.
diff --git a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
index 7150f409e0..881ffab042 100644
--- a/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
+++ b/Content.Shared/Containers/ItemSlot/ItemSlotsSystem.cs
@@ -34,6 +34,7 @@ namespace Content.Shared.Containers.ItemSlots
SubscribeLocalEvent(OnInteractUsing);
SubscribeLocalEvent(OnInteractHand);
+ SubscribeLocalEvent(OnUseInHand);
SubscribeLocalEvent(AddEjectVerbs);
SubscribeLocalEvent(AddInteractionVerbsVerbs);
@@ -125,6 +126,25 @@ namespace Content.Shared.Containers.ItemSlots
}
}
+ ///
+ /// Attempt to eject an item from the first valid item slot.
+ ///
+ private void OnUseInHand(EntityUid uid, ItemSlotsComponent itemSlots, UseInHandEvent args)
+ {
+ if (args.Handled)
+ return;
+
+ foreach (var slot in itemSlots.Slots.Values)
+ {
+ if (slot.Locked || !slot.EjectOnUse || slot.Item == null)
+ continue;
+
+ args.Handled = true;
+ TryEjectToHands(uid, slot, args.UserUid);
+ break;
+ }
+ }
+
///
/// Tries to insert a held item in any fitting item slot. If a valid slot already contains an item, it will
/// swap it out and place the old one in the user's hand.
@@ -172,7 +192,7 @@ namespace Content.Shared.Containers.ItemSlots
// ContainerSlot automatically raises a directed EntInsertedIntoContainerMessage
if (slot.InsertSound != null)
- SoundSystem.Play(Filter.Pvs(uid), slot.InsertSound.GetSound(), uid);
+ SoundSystem.Play(Filter.Pvs(uid), slot.InsertSound.GetSound(), uid, slot.SoundOptions);
}
///
@@ -267,7 +287,7 @@ namespace Content.Shared.Containers.ItemSlots
// ContainerSlot automatically raises a directed EntRemovedFromContainerMessage
if (slot.EjectSound != null)
- SoundSystem.Play(Filter.Pvs(uid), slot.EjectSound.GetSound(), uid);
+ SoundSystem.Play(Filter.Pvs(uid), slot.EjectSound.GetSound(), uid, slot.SoundOptions);
}
///
@@ -317,7 +337,7 @@ namespace Content.Shared.Containers.ItemSlots
return false;
if (user != null && EntityManager.TryGetComponent(user.Value, out SharedHandsComponent? hands))
- hands.TryPutInAnyHand(item);
+ hands.TryPutInActiveHandOrAny(item);
return true;
}
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
index 3943ce4fa3..3af39fcf6b 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml
@@ -1,6 +1,41 @@
+- type: entity
+ id: BatteryGunBase
+ parent: BaseItem
+ abstract: true
+ components:
+ - type: RangedWeapon
+ - type: BatteryBarrel
+ fireRate: 2
+ minAngle: 0
+ maxAngle: 45
+ angleIncrease: 15
+ angleDecay: 45
+ ammoPrototype: RedLaser
+ currentSelector: Single
+ allSelectors:
+ - Single
+ soundGunshot:
+ path: /Audio/Weapons/Guns/Gunshots/laser.ogg
+ cellSlot:
+ ejectOnUse: true
+ insertSound: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
+ ejectSound: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ soundOptions:
+ volume: -2
+ startingItem: PowerCellSmallStandard
+ whitelist:
+ components:
+ - Battery
+ - type: Appearance
+ visuals:
+ - type: MagVisualizer
+ magState: mag
+ steps: 5
+ zeroVisible: false
+
- type: entity
name: retro laser gun
- parent: BaseItem
+ parent: BatteryGunBase
id: LaserGun
description: A weapon using light amplified by the stimulated emission of radiation.
components:
@@ -19,23 +54,7 @@
- type: RangedWeapon
- type: BatteryBarrel
minAngle: 10
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- powerCellPrototype: PowerCellSmallStandard
- powerCellRemovable: true
fireCost: 40
- ammoPrototype: RedLaser
- soundGunshot:
- path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- type: Appearance
visuals:
- type: MagVisualizer
@@ -45,7 +64,7 @@
- type: entity
name: makeshift laser gun
- parent: BaseItem
+ parent: BatteryGunBase
id: MakeshiftLaser
description: Better pray it won't burn your hands off.
components:
@@ -61,36 +80,12 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/makeshift.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- minAngle: 0
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- powerCellPrototype: PowerCellSmallStandard
- powerCellRemovable: true
fireCost: 40
- ammoPrototype: RedLaser
- soundGunshot:
- path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- - type: Appearance
- visuals:
- - type: MagVisualizer
- magState: mag
- steps: 5
- zeroVisible: false
- type: entity
name: svalinn laser pistol
- parent: BaseItem
+ parent: BatteryGunBase
id: LaserPistolSvalinn
description: A cheap and widely used laser pistol.
components:
@@ -106,36 +101,12 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/svalinn.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- minAngle: 0
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- powerCellPrototype: PowerCellSmallStandard
- powerCellRemovable: true
fireCost: 20
- ammoPrototype: RedLaser
- soundGunshot:
- path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- - type: Appearance
- visuals:
- - type: MagVisualizer
- magState: mag
- steps: 5
- zeroVisible: false
- type: entity
name: cog laser carbine
- parent: BaseItem
+ parent: BatteryGunBase
id: LaserRifleCog
description: Favoured by Nanotrasen Security for being cheap and easy to use.
components:
@@ -151,36 +122,12 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/cog.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- minAngle: 0
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- powerCellPrototype: PowerCellSmallStandard
- powerCellRemovable: true
fireCost: 10
- ammoPrototype: RedLaser
- soundGunshot:
- path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- - type: Appearance
- visuals:
- - type: MagVisualizer
- magState: mag
- steps: 5
- zeroVisible: false
- type: entity
name: laser cannon
- parent: BaseItem
+ parent: BatteryGunBase
id: LaserCannon
description: A heavy duty, high powered laser weapon.
components:
@@ -196,36 +143,25 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/laser_cannon.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- minAngle: 0
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- powerCellPrototype: PowerCellSmallSuper
- powerCellRemovable: true
fireCost: 600
ammoPrototype: RedHeavyLaser
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser_cannon.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- - type: Appearance
- visuals:
- - type: MagVisualizer
- magState: mag
- steps: 5
- zeroVisible: false
+ cellSlot:
+ ejectOnUse: true
+ insertSound: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
+ ejectSound: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ soundOptions:
+ volume: -2
+ startingItem: PowerCellSmallSuper
+ whitelist:
+ components:
+ - Battery
- type: entity
name: x-ray cannon
- parent: BaseItem
+ parent: BatteryGunBase
id: XrayCannon
description: An experimental weapon that uses concentrated x-ray energy against its target.
components:
@@ -241,26 +177,21 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/xray.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
- minAngle: 0
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- powerCellPrototype: PowerCellSmallSuper
- powerCellRemovable: true
fireCost: 600
ammoPrototype: XrayLaser
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/laser3.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ cellSlot:
+ ejectOnUse: true
+ insertSound: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
+ ejectSound: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ soundOptions:
+ volume: -2
+ startingItem: PowerCellSmallSuper
+ whitelist:
+ components:
+ - Battery
- type: Appearance
visuals:
- type: MagVisualizer
@@ -270,7 +201,7 @@
- type: entity
name: taser
- parent: BaseItem
+ parent: BatteryGunBase
id: TaserGun
description: A low-capacity, energy-based stun gun used by security teams to subdue targets at range.
components:
@@ -293,26 +224,23 @@
Slots:
- Belt
HeldPrefix: taser4
- - type: RangedWeapon
- type: BatteryBarrel
- currentSelector: Single
- allSelectors:
- - Single
- fireRate: 2
minAngle: 5
- maxAngle: 45
angleIncrease: 20
- angleDecay: 15
- powerCellPrototype: PowerCellSmallStandard
- powerCellRemovable: false
fireCost: 80
ammoPrototype: BulletTaser
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/taser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ cellSlot:
+ insertSound: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
+ ejectSound: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ soundOptions:
+ volume: -2
+ locked: true
+ startingItem: PowerCellSmallStandard
+ whitelist:
+ components:
+ - Battery
- type: Appearance
visuals:
- type: MagVisualizer
@@ -322,7 +250,7 @@
- type: entity
name: laser gun
- parent: BaseItem
+ parent: BatteryGunBase
id: LaserSecGun
description: A laser gun.
components:
@@ -338,28 +266,16 @@
- type: Item
size: 24
sprite: Objects/Weapons/Guns/Battery/laser_gun.rsi
- - type: RangedWeapon
- type: BatteryBarrel
- minAngle: 10
- maxAngle: 45
- angleIncrease: 15
- angleDecay: 45
- currentSelector: Single
- allSelectors:
- - Single
+ minAngle: 1
fireRate: 6
- powerCellPrototype: PowerCellMediumStandard
- powerCellRemovable: true
- ammoPrototype: RedLaser
- soundGunshot:
- path: /Audio/Weapons/Guns/Gunshots/laser.ogg
- soundPowerCellInsert:
- path: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
- soundPowerCellEject:
- path: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
- - type: Appearance
- visuals:
- - type: MagVisualizer
- magState: mag
- steps: 5
- zeroVisible: false
+ cellSlot:
+ ejectOnUse: true
+ insertSound: /Audio/Weapons/Guns/MagIn/revolver_magin.ogg
+ ejectSound: /Audio/Weapons/Guns/MagOut/revolver_magout.ogg
+ soundOptions:
+ volume: -2
+ startingItem: PowerCellMediumStandard
+ whitelist:
+ components:
+ - Battery