DetGadget Hat Revitalization (#35438)

* DetGadget Hat

* uh... half-assed item description

* Reduce hat range to one tile, you have to stand on someone to steal their hat items

* Fix Integration Errors

* Only the wearer can access voice commands

* init work - handscomp is unable to be pulled

* second bit of progress

* basic working implementation

* nuke storageslots and add adminlogging

* disallow trolling nukies or hiding objective items

* remove unnecessary tags additions

* finish nuking unused tags

* death to yamllinter

* int tests be damned

* milon is a furry

* address review

* upd desc

* address reviews part 2

* address more reviews

* remove unused refs

* fix order of dependencies

* add ShowVerb to SharedStorageSystem.cs

This will allow or disallow showing the "Open Storage" verb if defined on the component.

* orks is a nerd

* add proper locale, fix adminlogging

* orks is a nerd 2

---------

Co-authored-by: Coenx-flex <coengmurray@gmail.com>
This commit is contained in:
ArtisticRoomba
2025-03-01 10:03:27 -08:00
committed by GitHub
parent 10c868011e
commit deea33a36a
8 changed files with 170 additions and 2 deletions

View File

@@ -0,0 +1,98 @@
using Content.Server.Hands.Systems;
using Content.Server.Storage.EntitySystems;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Content.Shared.Hands.Components;
using Content.Shared.Inventory;
using Content.Shared.Popups;
using Content.Shared.Storage;
using Robust.Server.Containers;
namespace Content.Server.VoiceTrigger;
/// <summary>
/// Allows storages to be manipulated using voice commands.
/// </summary>
public sealed class StorageVoiceControlSystem : EntitySystem
{
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly HandsSystem _hands = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly StorageSystem _storage = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StorageVoiceControlComponent, VoiceTriggeredEvent>(VoiceTriggered);
}
private void VoiceTriggered(Entity<StorageVoiceControlComponent> ent, ref VoiceTriggeredEvent args)
{
// Check if the component has any slot restrictions via AllowedSlots
// If it has slot restrictions, check if the item is in a slot that is allowed
if (ent.Comp.AllowedSlots != null && _inventory.TryGetContainingSlot(ent.Owner, out var itemSlot) &&
(itemSlot.SlotFlags & ent.Comp.AllowedSlots) == 0)
return;
// Don't do anything if there is no message
if (args.Message == null)
return;
// Get the storage component
if (!TryComp<StorageComponent>(ent, out var storage))
return;
// Get the hands component
if (!TryComp<HandsComponent>(args.Source, out var hands))
return;
// If the player has something in their hands, try to insert it into the storage
if (hands.ActiveHand != null && hands.ActiveHand.HeldEntity.HasValue)
{
// Disallow insertion and provide a reason why if the person decides to insert the item into itself
if (ent.Owner.Equals(hands.ActiveHand.HeldEntity.Value))
{
_popup.PopupEntity(Loc.GetString("comp-storagevoicecontrol-self-insert", ("entity", hands.ActiveHand.HeldEntity.Value)), ent, args.Source);
return;
}
if (_storage.CanInsert(ent, hands.ActiveHand.HeldEntity.Value, out var failedReason))
{
// We adminlog before insertion, otherwise the logger will attempt to pull info on an entity that no longer is present and throw an exception
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Source)} inserted {ToPrettyString(hands.ActiveHand.HeldEntity.Value)} into {ToPrettyString(ent)} via voice control");
_storage.Insert(ent, hands.ActiveHand.HeldEntity.Value, out _);
return;
}
{
// Tell the player the reason why the item couldn't be inserted
if (failedReason == null)
return;
_popup.PopupEntity(Loc.GetString(failedReason), ent, args.Source);
_adminLogger.Add(LogType.Action,
LogImpact.Low,
$"{ToPrettyString(args.Source)} failed to insert {ToPrettyString(hands.ActiveHand.HeldEntity.Value)} into {ToPrettyString(ent)} via voice control");
}
return;
}
// If otherwise, we're retrieving an item, so check all the items currently in the attached storage
foreach (var item in storage.Container.ContainedEntities)
{
// Get the item's name
var itemName = MetaData(item).EntityName;
// The message doesn't match the item name the requestor requested, skip and move on to the next item
if (!args.Message.Contains(itemName, StringComparison.InvariantCultureIgnoreCase))
continue;
// We found the item we want, so draw it from storage and place it into the player's hands
if (storage.Container.ContainedEntities.Count != 0)
{
_container.RemoveEntity(ent, item);
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.Source)} retrieved {ToPrettyString(item)} from {ToPrettyString(ent)} via voice control");
_hands.TryPickup(args.Source, item, handsComp: hands);
break;
}
}
}
}