Make BatteryBarrelComponent use item slots. (#5591)

This commit is contained in:
Leon Friedrich
2021-12-05 16:23:47 +13:00
committed by GitHub
parent f96b8a8b0f
commit e8b2d0a844
11 changed files with 184 additions and 334 deletions

View File

@@ -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<RevolverBarrelComponent, GetAlternativeVerbsEvent>(AddSpinVerb);
SubscribeLocalEvent<ServerBatteryBarrelComponent, GetAlternativeVerbsEvent>(AddEjectCellVerb);
SubscribeLocalEvent<ServerBatteryBarrelComponent, GetInteractionVerbsEvent>(AddInsertCellVerb);
SubscribeLocalEvent<ServerBatteryBarrelComponent, EntInsertedIntoContainerMessage>(OnCellSlotUpdated);
SubscribeLocalEvent<ServerBatteryBarrelComponent, EntRemovedFromContainerMessage>(OnCellSlotUpdated);
SubscribeLocalEvent<BoltActionBarrelComponent, GetInteractionVerbsEvent>(AddToggleBoltVerb);
@@ -28,6 +30,12 @@ namespace Content.Server.Weapon.Ranged.Barrels
SubscribeLocalEvent<ServerMagazineBarrelComponent, GetAlternativeVerbsEvent>(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<BatteryComponent>() ||
!_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 ||

View File

@@ -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<bool> InteractUsing(InteractUsingEventArgs eventArgs)
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs.User, eventArgs.Using);
}

View File

@@ -25,7 +25,7 @@ namespace Content.Server.Weapon.Ranged.Barrels.Components
/// </summary>
[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<bool> InteractUsing(InteractUsingEventArgs eventArgs)
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs);
}

View File

@@ -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
/// <param name="eventArgs"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
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<bool> InteractUsing(InteractUsingEventArgs eventArgs)
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{
return TryInsertBullet(eventArgs.User, eventArgs.Using);
}

View File

@@ -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<BatteryComponent>();
private ContainerSlot _powerCellContainer = default!;
public BatteryComponent? PowerCell => CellSlot.Item?.GetComponentOrNull<BatteryComponent>();
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<ContainerSlot>(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<ItemSlotsSystem>().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<ItemSlotsSystem>().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<BatteryComponent>())
{
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<ItemComponent>()))
{
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<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{
if (!eventArgs.Using.HasComponent<BatteryComponent>())
{
return false;
}
return TryInsertPowerCell(eventArgs.Using);
}
}
}

View File

@@ -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<bool> InteractUsing(InteractUsingEventArgs eventArgs)
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{
if (CanInsertMagazine(eventArgs.User, eventArgs.Using, quiet: false))
{

View File

@@ -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.)
/// </summary>
#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<bool> InteractUsing(InteractUsingEventArgs eventArgs);
public void ChangeFireSelector(FireRateSelector rateSelector)
{
if ((rateSelector & AllRateSelectors) != 0)