]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add pick random system (#15409)
authordeltanedas <39013340+deltanedas@users.noreply.github.com>
Sat, 29 Apr 2023 11:39:08 +0000 (11:39 +0000)
committerGitHub <noreply@github.com>
Sat, 29 Apr 2023 11:39:08 +0000 (21:39 +1000)
Co-authored-by: deltanedas <@deltanedas:kde.org>
Content.Server/Storage/Components/PickRandomComponent.cs [new file with mode: 0644]
Content.Server/Storage/EntitySystems/PickRandomSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/storage/components/pick-random-component.ftl [new file with mode: 0644]

diff --git a/Content.Server/Storage/Components/PickRandomComponent.cs b/Content.Server/Storage/Components/PickRandomComponent.cs
new file mode 100644 (file)
index 0000000..1046c55
--- /dev/null
@@ -0,0 +1,31 @@
+using Content.Server.Storage.EntitySystems;
+using Content.Shared.Whitelist;
+
+namespace Content.Server.Storage.Components;
+
+/// <summary>
+/// Adds a verb to pick a random item from a container.
+/// Only picks items that match the whitelist.
+/// </summary>
+[RegisterComponent]
+[Access(typeof(PickRandomSystem))]
+public sealed class PickRandomComponent : Component
+{
+    /// <summary>
+    /// Whitelist for potential picked items.
+    /// </summary>
+    [DataField("whitelist"), ViewVariables(VVAccess.ReadWrite)]
+    public EntityWhitelist? Whitelist;
+
+    /// <summary>
+    /// Locale id for the pick verb text.
+    /// </summary>
+    [DataField("verbText"), ViewVariables(VVAccess.ReadWrite)]
+    public string VerbText = "comp-pick-random-verb-text";
+
+    /// <summary>
+    /// Locale id for the empty storage message.
+    /// </summary>
+    [DataField("emptyText"), ViewVariables(VVAccess.ReadWrite)]
+    public string EmptyText = "comp-pick-random-empty";
+}
diff --git a/Content.Server/Storage/EntitySystems/PickRandomSystem.cs b/Content.Server/Storage/EntitySystems/PickRandomSystem.cs
new file mode 100644 (file)
index 0000000..eb48829
--- /dev/null
@@ -0,0 +1,61 @@
+using Content.Server.Storage.Components;
+using Content.Shared.Database;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Verbs;
+using Robust.Shared.Containers;
+using Robust.Shared.Random;
+using System.Linq;
+
+namespace Content.Server.Storage.EntitySystems;
+
+// TODO: move this to shared for verb prediction if/when storage is in shared
+public sealed class PickRandomSystem : EntitySystem
+{
+    [Dependency] private readonly SharedContainerSystem _container = default!;
+    [Dependency] private readonly SharedHandsSystem _hands = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<PickRandomComponent, GetVerbsEvent<AlternativeVerb>>(OnGetAlternativeVerbs);
+    }
+
+    private void OnGetAlternativeVerbs(EntityUid uid, PickRandomComponent comp, GetVerbsEvent<AlternativeVerb> args)
+    {
+        if (!args.CanAccess || !args.CanInteract || !TryComp<ServerStorageComponent>(uid, out var storage))
+            return;
+
+        var user = args.User;
+
+        // alt-click / alt-z to pick an item
+        args.Verbs.Add(new AlternativeVerb
+        {
+            Act = (() => {
+                TryPick(uid, comp, storage, user);
+            }),
+            Impact = LogImpact.Low,
+            Text = Loc.GetString(comp.VerbText),
+            Disabled = !(storage.StoredEntities?.Any(item => comp.Whitelist?.IsValid(item, EntityManager) ?? true) ?? false),
+            Message = Loc.GetString(comp.EmptyText, ("storage", uid))
+        });
+    }
+
+    private void TryPick(EntityUid uid, PickRandomComponent comp, ServerStorageComponent storage, EntityUid user)
+    {
+        if (storage.StoredEntities == null)
+            return;
+
+        var entities = storage.StoredEntities.Where(item => comp.Whitelist?.IsValid(item, EntityManager) ?? true);
+        if (!entities.Any())
+            return;
+
+        var picked = _random.Pick(entities.ToList());
+        // if it fails to go into a hand of the user, will be on the storage
+        _container.AttachParentToContainerOrGrid(Transform(picked));
+
+        // TODO: try to put in hands, failing that put it on the storage
+        _hands.TryPickupAnyHand(user, picked);
+    }
+}
diff --git a/Resources/Locale/en-US/storage/components/pick-random-component.ftl b/Resources/Locale/en-US/storage/components/pick-random-component.ftl
new file mode 100644 (file)
index 0000000..a3e72a0
--- /dev/null
@@ -0,0 +1,2 @@
+comp-pick-random-empty = {CAPITALIZE(THE($storage))} is empty!
+comp-pick-random-verb-text = Pick item