Add pick random system (#15409)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-04-29 11:39:08 +00:00
committed by GitHub
parent 3e5e48c98b
commit db28073530
3 changed files with 94 additions and 0 deletions

View File

@@ -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";
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,2 @@
comp-pick-random-empty = {CAPITALIZE(THE($storage))} is empty!
comp-pick-random-verb-text = Pick item