Vending machine changes (#8060)

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Flipp Syder
2022-05-09 19:22:58 -07:00
committed by GitHub
parent 8257635811
commit 8f223586d4
12 changed files with 240 additions and 57 deletions

View File

@@ -7,7 +7,7 @@ using Robust.Server.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
using Content.Server.VendingMachines.systems;
using Content.Server.VendingMachines.Systems;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.VendingMachines
@@ -16,25 +16,34 @@ namespace Content.Server.VendingMachines
public sealed class VendingMachineComponent : SharedVendingMachineComponent
{
public bool Ejecting;
public bool Emagged = false;
public TimeSpan AnimationDuration = TimeSpan.Zero;
[ViewVariables] [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))] public string PackPrototypeId = string.Empty;
[ViewVariables] [DataField("emagPack", customTypeSerializer:typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))] public string EmagPackPrototypeId = string.Empty;
[ViewVariables] [DataField("pack", customTypeSerializer:typeof(PrototypeIdSerializer<VendingMachineInventoryPrototype>))]
public string PackPrototypeId = string.Empty;
public string SpriteName = "";
public bool Broken;
/// <summary>
/// When true, will forcefully throw any object it dispenses
/// </summary>
[DataField("speedLimiter")]
public bool CanShoot = false;
[DataField("soundVend")]
// Grabbed from: https://github.com/discordia-space/CEV-Eris/blob/f702afa271136d093ddeb415423240a2ceb212f0/sound/machines/vending_drop.ogg
public SoundSpecifier SoundVend = new SoundPathSpecifier("/Audio/Machines/machine_vend.ogg");
[DataField("soundDeny")]
// Yoinked from: https://github.com/discordia-space/CEV-Eris/blob/35bbad6764b14e15c03a816e3e89aa1751660ba9/sound/machines/Custom_deny.ogg
public SoundSpecifier SoundDeny = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
[ViewVariables] public BoundUserInterface? UserInterface => Owner.GetUIOrNull(VendingMachineUiKey.Key);
public float NonLimitedEjectForce = 7.5f;
public float NonLimitedEjectRange = 5f;
}
}

View File

@@ -0,0 +1,43 @@
using Content.Server.Wires;
using Content.Shared.VendingMachines;
using Content.Shared.Wires;
namespace Content.Server.VendingMachines;
[DataDefinition]
public sealed class VendingMachineContrabandWireAction : BaseToggleWireAction
{
private readonly Color _color = Color.Green;
private readonly string _text = "MNGR";
public override object? StatusKey { get; } = ContrabandWireKey.StatusKey;
public override object? TimeoutKey { get; } = ContrabandWireKey.TimeoutKey;
public override StatusLightData? GetStatusLightData(Wire wire)
{
var lightState = StatusLightState.Off;
if (IsPowered(wire.Owner) && EntityManager.TryGetComponent(wire.Owner, out VendingMachineComponent vending))
{
lightState = vending.Contraband
? StatusLightState.BlinkingSlow
: StatusLightState.On;
}
return new StatusLightData(
_color,
lightState,
_text);
}
public override void ToggleValue(EntityUid owner, bool setting)
{
if (EntityManager.TryGetComponent(owner, out VendingMachineComponent vending))
{
vending.Contraband = !setting;
}
}
public override bool GetValue(EntityUid owner)
{
return EntityManager.TryGetComponent(owner, out VendingMachineComponent vending) && !vending.Contraband;
}
}

View File

@@ -0,0 +1,68 @@
using Content.Server.VendingMachines.Systems;
using Content.Server.Wires;
using Content.Shared.VendingMachines;
using Content.Shared.Wires;
namespace Content.Server.VendingMachines;
[DataDefinition]
public sealed class VendingMachineEjectItemWireAction : BaseWireAction
{
private VendingMachineSystem _vendingMachineSystem = default!;
private Color _color = Color.Red;
private string _text = "VEND";
public override object? StatusKey { get; } = EjectWireKey.StatusKey;
public override StatusLightData? GetStatusLightData(Wire wire)
{
var lightState = StatusLightState.Off;
if (IsPowered(wire.Owner)
&& EntityManager.TryGetComponent(wire.Owner, out VendingMachineComponent vending))
{
lightState = vending.CanShoot
? StatusLightState.BlinkingFast
: StatusLightState.On;
}
return new StatusLightData(
_color,
lightState,
_text);
}
public override void Initialize()
{
base.Initialize();
_vendingMachineSystem = EntitySystem.Get<VendingMachineSystem>();
}
public override bool Cut(EntityUid user, Wire wire)
{
if (EntityManager.TryGetComponent(wire.Owner, out VendingMachineComponent vending))
{
vending.CanShoot = true;
}
return true;
}
public override bool Mend(EntityUid user, Wire wire)
{
if (EntityManager.TryGetComponent(wire.Owner, out VendingMachineComponent vending))
{
vending.CanShoot = false;
}
return true;
}
public override bool Pulse(EntityUid user, Wire wire)
{
_vendingMachineSystem.EjectRandom(wire.Owner, true);
return true;
}
}

View File

@@ -14,7 +14,7 @@ using Content.Shared.Emag.Systems;
using static Content.Shared.VendingMachines.SharedVendingMachineComponent;
using Content.Shared.Throwing;
namespace Content.Server.VendingMachines.systems
namespace Content.Server.VendingMachines.Systems
{
public sealed class VendingMachineSystem : EntitySystem
{
@@ -52,7 +52,12 @@ namespace Content.Server.VendingMachines.systems
if (!IsPowered(uid, component))
return;
component.UserInterface?.SendMessage(new VendingMachineInventoryMessage(component.Inventory));
var inventory = new List<VendingMachineInventoryEntry>(component.Inventory);
if (component.Emagged) inventory.AddRange(component.EmaggedInventory);
if (component.Contraband) inventory.AddRange(component.ContrabandInventory);
component.UserInterface?.SendMessage(new VendingMachineInventoryMessage(inventory));
}
private void OnInventoryEjectMessage(EntityUid uid, VendingMachineComponent component, VendingMachineEjectMessage args)
@@ -63,7 +68,7 @@ namespace Content.Server.VendingMachines.systems
if (args.Session.AttachedEntity is not { Valid: true } entity || Deleted(entity))
return;
AuthorizedVend(uid, entity, args.ID, component);
AuthorizedVend(uid, entity, args.Type, args.ID, component);
}
private void OnPowerChanged(EntityUid uid, VendingMachineComponent component, PowerChangedEvent args)
@@ -79,10 +84,9 @@ namespace Content.Server.VendingMachines.systems
private void OnEmagged(EntityUid uid, VendingMachineComponent component, GotEmaggedEvent args)
{
if (component.Emagged || component.EmagPackPrototypeId == string.Empty)
if (component.Emagged || component.EmaggedInventory.Count == 0 )
return;
AddVendEntries(component, component.EmagPackPrototypeId);
component.Emagged = true;
args.Handled = true;
}
@@ -121,36 +125,42 @@ namespace Content.Server.VendingMachines.systems
spriteComp.BaseRSIPath = string.Format(vendingMachineRSIPath, vendComponent.SpriteName);
}
}
var inventory = new List<VendingMachineInventoryEntry>();
foreach (var (id, amount) in packPrototype.StartingInventory)
{
if (!_prototypeManager.TryIndex(id, out EntityPrototype? prototype))
{
continue;
}
inventory.Add(new VendingMachineInventoryEntry(id, amount));
}
vendComponent.Inventory = inventory;
AddInventoryFromPrototype(uid, packPrototype.StartingInventory, InventoryType.Regular, vendComponent);
AddInventoryFromPrototype(uid, packPrototype.EmaggedInventory, InventoryType.Emagged, vendComponent);
AddInventoryFromPrototype(uid, packPrototype.ContrabandInventory, InventoryType.Contraband, vendComponent);
}
/// <summary>
/// Add more entries for any reason AFTER initialization (emag, machine upgrades, etc)
/// </summary>
public void AddVendEntries(VendingMachineComponent component, string pack)
private void AddInventoryFromPrototype(EntityUid uid, Dictionary<string, uint>? entries,
InventoryType type,
VendingMachineComponent? component = null)
{
if (!_prototypeManager.TryIndex(pack, out VendingMachineInventoryPrototype? packPrototype))
if (!Resolve(uid, ref component) || entries == null)
{
Logger.Error($"Pack has no valid inventory prototype: {pack}");
return;
}
foreach (var (id, amount) in packPrototype.StartingInventory)
var inventory = new List<VendingMachineInventoryEntry>();
foreach (var (id, amount) in entries)
{
if (!_prototypeManager.TryIndex(id, out EntityPrototype? prototype))
if (_prototypeManager.HasIndex<EntityPrototype>(id))
{
continue;
inventory.Add(new VendingMachineInventoryEntry(type, id, amount));
}
component.Inventory.Add(new VendingMachineInventoryEntry(id, amount));
}
switch (type)
{
case InventoryType.Regular:
component.Inventory.AddRange(inventory);
break;
case InventoryType.Emagged:
component.EmaggedInventory.AddRange(inventory);
break;
case InventoryType.Contraband:
component.ContrabandInventory.AddRange(inventory);
break;
}
}
@@ -171,12 +181,12 @@ namespace Content.Server.VendingMachines.systems
public bool IsAuthorized(EntityUid uid, EntityUid? sender, VendingMachineComponent? vendComponent = null)
{
if (!Resolve(uid, ref vendComponent))
if (!Resolve(uid, ref vendComponent) || sender == null)
return false;
if (TryComp<AccessReaderComponent?>(vendComponent.Owner, out var accessReader))
{
if (sender == null || !_accessReader.IsAllowed(accessReader, sender.Value))
if (!_accessReader.IsAllowed(accessReader, sender.Value) && !vendComponent.Emagged)
{
_popupSystem.PopupEntity(Loc.GetString("vending-machine-component-try-eject-access-denied"), uid, Filter.Pvs(uid));
Deny(uid, vendComponent);
@@ -186,7 +196,7 @@ namespace Content.Server.VendingMachines.systems
return true;
}
public void TryEjectVendorItem(EntityUid uid, string itemId, bool throwItem, VendingMachineComponent? vendComponent = null)
public void TryEjectVendorItem(EntityUid uid, InventoryType type, string itemId, bool throwItem, VendingMachineComponent? vendComponent = null)
{
if (!Resolve(uid, ref vendComponent))
return;
@@ -196,7 +206,14 @@ namespace Content.Server.VendingMachines.systems
return;
}
var entry = vendComponent.Inventory.Find(x => x.ID == itemId);
var entry = type switch
{
InventoryType.Regular => vendComponent.Inventory.Find(x => x.ID == itemId),
InventoryType.Emagged when vendComponent.Emagged => vendComponent.EmaggedInventory.Find(x => x.ID == itemId),
InventoryType.Contraband when vendComponent.Contraband => vendComponent.ContrabandInventory.Find(x => x.ID == itemId),
_ => null
};
if (entry == null)
{
_popupSystem.PopupEntity(Loc.GetString("vending-machine-component-try-eject-invalid-item"), uid, Filter.Pvs(uid));
@@ -211,7 +228,7 @@ namespace Content.Server.VendingMachines.systems
return;
}
if (entry.ID == null)
if (string.IsNullOrEmpty(entry.ID))
return;
if (!TryComp<TransformComponent>(vendComponent.Owner, out var transformComp))
@@ -220,7 +237,7 @@ namespace Content.Server.VendingMachines.systems
// Start Ejecting, and prevent users from ordering while anim playing
vendComponent.Ejecting = true;
entry.Amount--;
vendComponent.UserInterface?.SendMessage(new VendingMachineInventoryMessage(vendComponent.Inventory));
vendComponent.UserInterface?.SendMessage(new VendingMachineInventoryMessage(vendComponent.AllInventory));
TryUpdateVisualState(uid, VendingMachineVisualState.Eject, vendComponent);
vendComponent.Owner.SpawnTimer(vendComponent.AnimationDuration, () =>
{
@@ -237,13 +254,12 @@ namespace Content.Server.VendingMachines.systems
SoundSystem.Play(Filter.Pvs(vendComponent.Owner), vendComponent.SoundVend.GetSound(), vendComponent.Owner, AudioParams.Default.WithVolume(-2f));
}
public void AuthorizedVend(EntityUid uid, EntityUid sender, string itemId, VendingMachineComponent component)
public void AuthorizedVend(EntityUid uid, EntityUid sender, InventoryType type, string itemId, VendingMachineComponent component)
{
if (IsAuthorized(uid, sender, component))
{
TryEjectVendorItem(uid, itemId, component.CanShoot, component);
TryEjectVendorItem(uid, type, itemId, component.CanShoot, component);
}
return;
}
public void TryUpdateVisualState(EntityUid uid, VendingMachineVisualState? state = VendingMachineVisualState.Normal, VendingMachineComponent? vendComponent = null)
@@ -276,13 +292,14 @@ namespace Content.Server.VendingMachines.systems
if (!Resolve(uid, ref vendComponent))
return;
var availableItems = vendComponent.Inventory.Where(x => x.Amount > 0).ToList();
var availableItems = vendComponent.AllInventory.Where(x => x.Amount > 0).ToList();
if (availableItems.Count <= 0)
{
return;
}
TryEjectVendorItem(uid, _random.Pick(availableItems).ID, throwItem, vendComponent);
var item = _random.Pick(availableItems);
TryEjectVendorItem(uid, item.Type, item.ID, throwItem, vendComponent);
}
}
}