Add utility verbs (#6473)
This commit is contained in:
@@ -41,6 +41,18 @@ namespace Content.Client.Verbs.UI
|
|||||||
ExpansionIndicator.Visible = true;
|
ExpansionIndicator.Visible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verb.Icon == null && verb.IconEntity != null)
|
||||||
|
{
|
||||||
|
var spriteView = new SpriteView()
|
||||||
|
{
|
||||||
|
OverrideDirection = Direction.South,
|
||||||
|
Sprite = IoCManager.Resolve<IEntityManager>().GetComponentOrNull<ISpriteComponent>(verb.IconEntity.Value)
|
||||||
|
};
|
||||||
|
|
||||||
|
Icon.AddChild(spriteView);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Icon.AddChild(new TextureRect()
|
Icon.AddChild(new TextureRect()
|
||||||
{
|
{
|
||||||
Texture = verb.Icon?.Frame0(),
|
Texture = verb.Icon?.Frame0(),
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace Content.Client.Verbs.UI
|
|||||||
if (verb.Category?.Text == category.Text)
|
if (verb.Category?.Text == category.Text)
|
||||||
{
|
{
|
||||||
verbsInCategory.Add(verb);
|
verbsInCategory.Add(verb);
|
||||||
drawIcons = drawIcons || verb.Icon != null;
|
drawIcons = drawIcons || verb.Icon != null || verb.IconEntity != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Disposal.Unit.Components;
|
||||||
|
using Content.Server.Disposal.Unit.EntitySystems;
|
||||||
using Content.Server.Hands.Components;
|
using Content.Server.Hands.Components;
|
||||||
using Content.Server.Storage.Components;
|
using Content.Server.Storage.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
@@ -8,9 +11,6 @@ using JetBrains.Annotations;
|
|||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly DisposalUnitSystem _disposalSystem = default!;
|
||||||
|
|
||||||
private readonly List<IPlayerSession> _sessionCache = new();
|
private readonly List<IPlayerSession> _sessionCache = new();
|
||||||
|
|
||||||
@@ -33,9 +34,11 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(HandleEntityInsertedIntoContainer);
|
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(HandleEntityInsertedIntoContainer);
|
||||||
|
|
||||||
SubscribeLocalEvent<EntityStorageComponent, GetVerbsEvent<InteractionVerb>>(AddToggleOpenVerb);
|
SubscribeLocalEvent<EntityStorageComponent, GetVerbsEvent<InteractionVerb>>(AddToggleOpenVerb);
|
||||||
SubscribeLocalEvent<ServerStorageComponent, GetVerbsEvent<ActivationVerb>>(AddOpenUiVerb);
|
|
||||||
SubscribeLocalEvent<EntityStorageComponent, RelayMovementEntityEvent>(OnRelayMovement);
|
SubscribeLocalEvent<EntityStorageComponent, RelayMovementEntityEvent>(OnRelayMovement);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ServerStorageComponent, GetVerbsEvent<ActivationVerb>>(AddOpenUiVerb);
|
||||||
|
SubscribeLocalEvent<ServerStorageComponent, GetVerbsEvent<UtilityVerb>>(AddTransferVerbs);
|
||||||
|
|
||||||
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
SubscribeLocalEvent<StorageFillComponent, MapInitEvent>(OnStorageFillMapInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +120,97 @@ namespace Content.Server.Storage.EntitySystems
|
|||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddTransferVerbs(EntityUid uid, ServerStorageComponent component, GetVerbsEvent<UtilityVerb> args)
|
||||||
|
{
|
||||||
|
if (!args.CanAccess || !args.CanInteract)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var entities = component.Storage?.ContainedEntities;
|
||||||
|
if (entities == null || entities.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if the target is storage, add a verb to transfer storage.
|
||||||
|
if (TryComp(args.Target, out ServerStorageComponent? targetStorage)
|
||||||
|
&& (!TryComp(uid, out LockComponent? targetLock) || !targetLock.Locked))
|
||||||
|
{
|
||||||
|
UtilityVerb verb = new()
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("storage-component-transfer-verb"),
|
||||||
|
IconEntity = args.Using,
|
||||||
|
Act = () => TransferEntities(uid, args.Target, component, lockComponent, targetStorage, targetLock)
|
||||||
|
};
|
||||||
|
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the target is a disposal unit, add a verb to transfer storage into the unit (e.g., empty a trash bag).
|
||||||
|
if (!TryComp(args.Target, out DisposalUnitComponent? disposal))
|
||||||
|
return;
|
||||||
|
|
||||||
|
UtilityVerb dispose = new()
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("storage-component-dispose-verb"),
|
||||||
|
IconEntity = args.Using,
|
||||||
|
Act = () => DisposeEntities(args.User, uid, args.Target, component, lockComponent, disposal)
|
||||||
|
};
|
||||||
|
|
||||||
|
args.Verbs.Add(dispose);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move entities from one storage to another.
|
||||||
|
/// </summary>
|
||||||
|
public void TransferEntities(EntityUid source, EntityUid target,
|
||||||
|
ServerStorageComponent? sourceComp = null, LockComponent? sourceLock = null,
|
||||||
|
ServerStorageComponent? targetComp = null, LockComponent? targetLock = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(source, ref sourceComp) || !Resolve(target, ref targetComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var entities = sourceComp.Storage?.ContainedEntities;
|
||||||
|
if (entities == null || entities.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Resolve(source, ref sourceLock, false) && sourceLock.Locked
|
||||||
|
|| Resolve(target, ref targetLock, false) && targetLock.Locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var entity in entities.ToList())
|
||||||
|
{
|
||||||
|
targetComp.Insert(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move entities from storage into a disposal unit.
|
||||||
|
/// </summary>
|
||||||
|
public void DisposeEntities(EntityUid user, EntityUid source, EntityUid target,
|
||||||
|
ServerStorageComponent? sourceComp = null, LockComponent? sourceLock = null,
|
||||||
|
DisposalUnitComponent? disposalComp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(source, ref sourceComp) || !Resolve(target, ref disposalComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var entities = sourceComp.Storage?.ContainedEntities;
|
||||||
|
if (entities == null || entities.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Resolve(source, ref sourceLock, false) && sourceLock.Locked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var entity in entities.ToList())
|
||||||
|
{
|
||||||
|
if (_disposalSystem.CanInsert(disposalComp, entity)
|
||||||
|
&& disposalComp.Container.Insert(entity))
|
||||||
|
{
|
||||||
|
_disposalSystem.AfterInsert(disposalComp, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleEntityRemovedFromContainer(EntRemovedFromContainerMessage message)
|
private void HandleEntityRemovedFromContainer(EntRemovedFromContainerMessage message)
|
||||||
{
|
{
|
||||||
var oldParentEntity = message.Container.Owner;
|
var oldParentEntity = message.Container.Owner;
|
||||||
|
|||||||
@@ -404,6 +404,7 @@ namespace Content.Shared.Containers.ItemSlots
|
|||||||
: EntityManager.GetComponent<MetaDataComponent>(slot.Item!.Value).EntityName ?? string.Empty;
|
: EntityManager.GetComponent<MetaDataComponent>(slot.Item!.Value).EntityName ?? string.Empty;
|
||||||
|
|
||||||
AlternativeVerb verb = new();
|
AlternativeVerb verb = new();
|
||||||
|
verb.IconEntity = slot.Item;
|
||||||
verb.Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);
|
verb.Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);
|
||||||
|
|
||||||
if (slot.EjectVerbText == null)
|
if (slot.EjectVerbText == null)
|
||||||
@@ -414,7 +415,6 @@ namespace Content.Shared.Containers.ItemSlots
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
verb.Text = Loc.GetString(slot.EjectVerbText);
|
verb.Text = Loc.GetString(slot.EjectVerbText);
|
||||||
verb.IconTexture = "/Textures/Interface/VerbIcons/eject.svg.192dpi.png";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
@@ -439,8 +439,8 @@ namespace Content.Shared.Containers.ItemSlots
|
|||||||
: EntityManager.GetComponent<MetaDataComponent>(slot.Item!.Value).EntityName ?? string.Empty;
|
: EntityManager.GetComponent<MetaDataComponent>(slot.Item!.Value).EntityName ?? string.Empty;
|
||||||
|
|
||||||
InteractionVerb takeVerb = new();
|
InteractionVerb takeVerb = new();
|
||||||
|
takeVerb.IconEntity = slot.Item;
|
||||||
takeVerb.Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);
|
takeVerb.Act = () => TryEjectToHands(uid, slot, args.User, excludeUserAudio: true);
|
||||||
takeVerb.IconTexture = "/Textures/Interface/VerbIcons/pickup.svg.192dpi.png";
|
|
||||||
|
|
||||||
if (slot.EjectVerbText == null)
|
if (slot.EjectVerbText == null)
|
||||||
takeVerb.Text = Loc.GetString("take-item-verb-text", ("subject", verbSubject));
|
takeVerb.Text = Loc.GetString("take-item-verb-text", ("subject", verbSubject));
|
||||||
@@ -465,6 +465,7 @@ namespace Content.Shared.Containers.ItemSlots
|
|||||||
: Name(args.Using.Value) ?? string.Empty;
|
: Name(args.Using.Value) ?? string.Empty;
|
||||||
|
|
||||||
InteractionVerb insertVerb = new();
|
InteractionVerb insertVerb = new();
|
||||||
|
insertVerb.IconEntity = args.Using;
|
||||||
insertVerb.Act = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true);
|
insertVerb.Act = () => Insert(uid, slot, args.Using.Value, args.User, excludeUserAudio: true);
|
||||||
|
|
||||||
if (slot.InsertVerbText != null)
|
if (slot.InsertVerbText != null)
|
||||||
|
|||||||
@@ -47,16 +47,16 @@ namespace Content.Shared.Verbs
|
|||||||
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
|
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
|
||||||
/// does not request verbs from the server.
|
/// does not request verbs from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SortedSet<Verb> GetLocalVerbs(EntityUid target, EntityUid user, Type type, bool force = false, bool all = false)
|
public SortedSet<Verb> GetLocalVerbs(EntityUid target, EntityUid user, Type type, bool force = false)
|
||||||
{
|
{
|
||||||
return GetLocalVerbs(target, user, new List<Type>() { type }, force, all);
|
return GetLocalVerbs(target, user, new List<Type>() { type }, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
|
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
|
||||||
/// does not request verbs from the server.
|
/// does not request verbs from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SortedSet<Verb> GetLocalVerbs(EntityUid target, EntityUid user, List<Type> types, bool force = false, bool all = false)
|
public SortedSet<Verb> GetLocalVerbs(EntityUid target, EntityUid user, List<Type> types, bool force = false)
|
||||||
{
|
{
|
||||||
SortedSet<Verb> verbs = new();
|
SortedSet<Verb> verbs = new();
|
||||||
|
|
||||||
@@ -99,6 +99,15 @@ namespace Content.Shared.Verbs
|
|||||||
verbs.UnionWith(verbEvent.Verbs);
|
verbs.UnionWith(verbEvent.Verbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (types.Contains(typeof(UtilityVerb))
|
||||||
|
&& @using != null
|
||||||
|
&& @using != target)
|
||||||
|
{
|
||||||
|
var verbEvent = new GetVerbsEvent<UtilityVerb>(user, target, @using, hands, canInteract, canAccess);
|
||||||
|
RaiseLocalEvent(@using.Value, verbEvent); // directed at used, not at target
|
||||||
|
verbs.UnionWith(verbEvent.Verbs);
|
||||||
|
}
|
||||||
|
|
||||||
if (types.Contains(typeof(AlternativeVerb)))
|
if (types.Contains(typeof(AlternativeVerb)))
|
||||||
{
|
{
|
||||||
var verbEvent = new GetVerbsEvent<AlternativeVerb>(user, target, @using, hands, canInteract, canAccess);
|
var verbEvent = new GetVerbsEvent<AlternativeVerb>(user, target, @using, hands, canInteract, canAccess);
|
||||||
|
|||||||
@@ -121,6 +121,12 @@ namespace Content.Shared.Verbs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string? IconTexture;
|
public string? IconTexture;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this is not null, and no icon or icon texture were specified, a sprite view of this entity will be
|
||||||
|
/// used as the icon for this verb.
|
||||||
|
/// </summary>
|
||||||
|
public EntityUid? IconEntity;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not to close the context menu after using it to run this verb.
|
/// Whether or not to close the context menu after using it to run this verb.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -200,6 +206,7 @@ namespace Content.Shared.Verbs
|
|||||||
{
|
{
|
||||||
{ typeof(Verb) },
|
{ typeof(Verb) },
|
||||||
{ typeof(InteractionVerb) },
|
{ typeof(InteractionVerb) },
|
||||||
|
{ typeof(UtilityVerb) },
|
||||||
{ typeof(AlternativeVerb) },
|
{ typeof(AlternativeVerb) },
|
||||||
{ typeof(ActivationVerb) },
|
{ typeof(ActivationVerb) },
|
||||||
{ typeof(ExamineVerb) }
|
{ typeof(ExamineVerb) }
|
||||||
@@ -226,6 +233,27 @@ namespace Content.Shared.Verbs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// These verbs are similar to the normal interaction verbs, except these interactions are facilitated by the
|
||||||
|
/// currently held entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The only notable difference between these and InteractionVerbs is that they are obtained by raising an event
|
||||||
|
/// directed at the currently held entity. Distinguishing between utility and interaction verbs helps avoid
|
||||||
|
/// confusion if a component enables verbs both when the item is used on something else, or when it is the
|
||||||
|
/// target of an interaction. These verbs are only obtained if the target and the held entity are NOT the same.
|
||||||
|
/// </remarks>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class UtilityVerb : Verb
|
||||||
|
{
|
||||||
|
public override int TypePriority => 3;
|
||||||
|
|
||||||
|
public UtilityVerb() : base()
|
||||||
|
{
|
||||||
|
TextStyleClass = InteractionVerb.DefaultTextStyleClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verbs for alternative-interactions.
|
/// Verbs for alternative-interactions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
storage-component-transfer-verb = Transfer contents
|
||||||
|
storage-component-dispose-verb = Dispose of contents
|
||||||
Reference in New Issue
Block a user