ECS verbs and update context menu (#4594)
* Functioning ECS verbs Currently only ID card console works. * Changed verb types and allow ID card insertions * Verb GUI sorting and verb networking * More networking, and shared components * Clientside verbs work now. * Verb enums changed to bitmask flags * Verb Categories redo * Fix range check * GasTank Verb * Remove unnecessary bodypart verb * Buckle Verb * buckle & unbuckle verbs * Updated range checks * Item cabinet verbs * Add range user override * construction verb * Chemistry machine verbs * Climb Verb * Generalise pulled entity verbs * ViewVariables Verb * rejuvenate, delete, sentient, control verbs * Outfit verb * inrangeunoccluded and tubedirection verbs * attach-to verbs * remove unused verbs and move VV * Rename DebugVerbSystem * Ghost role and pointing verbs * Remove global verbs * Allow verbs to raise events * Changing categories and simplifying debug verbs * Add rotate and flip verbs * fix rejuvenate test * redo context menu * new Add Gas debug verb * Add Set Temperature debug verb * Uncuff verb * Disposal unit verbs * Add pickup verb * lock/unlock verb * Remove verb type, add specific verb events * rename verb messages -> events * Context menu displays verbs by interaction type * Updated context menu HandleMove previously, checked if entities moved 1 tile from click location. Now checks if entities moved out of view. Now you can actually right-click interact with yourself while walking! * Misc Verb menu GUI changes * Fix non-human/ghost verbs * Update types and categories * Allow non-ghost/human to open context menu * configuration verb * tagger verb * Morgue Verbs * Medical Scanner Verbs * Fix solution refactor merge issues * Fix context menu in-view check * Remove prepare GUI * Redo verb restrictions * Fix context menu UI * Disposal Verbs * Spill verb * Light verb * Hand Held light verb * power cell verbs * storage verbs and adding names to insert/eject * Pulling verb * Close context menu on verb execution * Strip verb * AmmoBox verb * fix pull verb * gun barrel verbs revolver verb energy weapon verbs Bolt action verb * Magazine gun barrel verbs * Add charger verbs * PDA verbs * Transfer amount verb * Add reagent verb * make alt-click use ECS verbs * Delete old verb files * Magboot verb * finalising tweaks * context menu visibility changes * code cleanup * Update AdminAddReagentUI.cs * Remove HasFlag * Consistent verb keys * Remove Linq, add comment * Fix in-inventory check * Update GUI text alignment and padding * Added close-menu option * Changed some "interaction" verbs to "activation" * Remove verb keys, use sorted sets * fix master merge * update some verb text * Undo Changes Remove some new verbs that can be added later undid some .ftl bugfixes, can and should be done separately * fix merge * Undo file rename * fix merge * Misc Cleanup * remove contraction * Fix keybinding issue * fix comment * merge fix * fix merge * fix merge * fix merge * fix merge * fix open-close verbs * adjust uncuff verb * fix merge and undo the renaming of SharedPullableComponent to PullableComponent. I'm tired of all of those merge conflicts
This commit is contained in:
@@ -1,90 +1,166 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
using System;
|
||||
|
||||
namespace Content.Shared.Verbs
|
||||
{
|
||||
/// <summary>
|
||||
/// A verb is an action in the right click menu of an entity.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To add a verb to an entity, define it as a nested class inside the owning component,
|
||||
/// and mark it with <see cref="VerbAttribute"/>
|
||||
/// </remarks>
|
||||
[UsedImplicitly]
|
||||
public abstract class Verb : VerbBase
|
||||
[Flags]
|
||||
public enum VerbType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations should write into <paramref name="data"/> to return their data.
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
/// <param name="data">The data that must be filled into.</param>
|
||||
protected abstract void GetData(IEntity user, IComponent component, VerbData data);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this verb is activated from the right click menu.
|
||||
/// </summary>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
public abstract void Activate(IEntity user, IComponent component);
|
||||
|
||||
public VerbData GetData(IEntity user, IComponent component)
|
||||
{
|
||||
var data = new VerbData();
|
||||
GetData(user, component, data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Sub class of <see cref="T:Content.Shared.Verbs.Verb" /> that works on a specific type of component,
|
||||
/// to reduce casting boiler plate for implementations.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of component that this verb will run on.</typeparam>
|
||||
public abstract class Verb<T> : Verb where T : IComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the visible verb data for the user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Implementations should write into <paramref name="data"/> to return their data.
|
||||
/// </remarks>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
/// <param name="data">The data that must be filled into.</param>
|
||||
protected abstract void GetData(IEntity user, T component, VerbData data);
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when this verb is activated from the right click menu.
|
||||
/// </summary>
|
||||
/// <param name="user">The entity of the user opening this menu.</param>
|
||||
/// <param name="component">The component instance for which this verb is being loaded.</param>
|
||||
protected abstract void Activate(IEntity user, T component);
|
||||
|
||||
protected sealed override void GetData(IEntity user, IComponent component, VerbData data)
|
||||
{
|
||||
GetData(user, (T) component, data);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public sealed override void Activate(IEntity user, IComponent component)
|
||||
{
|
||||
Activate(user, (T) component);
|
||||
}
|
||||
Interaction = 1,
|
||||
Activation = 2,
|
||||
Alternative = 4,
|
||||
Other = 8,
|
||||
All = 1+2+4+8
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This attribute should be used on <see cref="Verb"/> implementations nested inside component classes,
|
||||
/// so that they're automatically detected.
|
||||
/// Verb objects describe actions that a user can take. The actions can be specified via an Action, local
|
||||
/// events, or networked events. Verbs also provide text, icons, and categories for displaying in the
|
||||
/// context-menu.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
[MeansImplicitUse]
|
||||
public sealed class VerbAttribute : Attribute
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class Verb : IComparable
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an action that will be run when the verb is "acted" out.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This delegate probably just points to some function in the system assembling this verb. This delegate
|
||||
/// will be run regardless of whether <see cref="LocalVerbEventArgs"/> or <see cref="NetworkVerbEventArgs"/>
|
||||
/// are defined.
|
||||
/// </remarks>
|
||||
[NonSerialized]
|
||||
public Action? Act;
|
||||
|
||||
/// <summary>
|
||||
/// This is local event that will be raised when the verb is executed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This event will be raised regardless of whether <see cref="NetworkVerbEventArgs"/> or <see cref="Act"/>
|
||||
/// are defined.
|
||||
/// </remarks>
|
||||
[NonSerialized]
|
||||
public object? LocalVerbEventArgs;
|
||||
|
||||
/// <summary>
|
||||
/// Where do direct the local event.
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public EntityUid LocalEventTarget = EntityUid.Invalid;
|
||||
|
||||
/// <summary>
|
||||
/// This is networked event that will be raised when the verb is executed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This event will be raised regardless of whether <see cref="LocalVerbEventArgs"/> or <see cref="Act"/>
|
||||
/// are defined.
|
||||
/// </remarks>
|
||||
[NonSerialized]
|
||||
public EntityEventArgs? NetworkVerbEventArgs;
|
||||
|
||||
/// <summary>
|
||||
/// The text that the user sees on the verb button.
|
||||
/// </summary>
|
||||
public string Text = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Sprite of the icon that the user sees on the verb button.
|
||||
/// </summary>
|
||||
public SpriteSpecifier? Icon
|
||||
{
|
||||
get => _icon ??=
|
||||
IconTexture == null ? null : new SpriteSpecifier.Texture(new ResourcePath(IconTexture));
|
||||
set => _icon = value;
|
||||
}
|
||||
private SpriteSpecifier? _icon;
|
||||
|
||||
/// <summary>
|
||||
/// Name of the category this button is under. Used to group verbs in the context menu.
|
||||
/// </summary>
|
||||
public VerbCategory? Category;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this verb is disabled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Disabled verbs are shown in the context menu with a slightly darker background color, and cannot be
|
||||
/// executed. It is recommended that a <see cref="Tooltip"/> message be provided outlining why this verb is
|
||||
/// disabled.
|
||||
/// </remarks>
|
||||
public bool Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// Optional tooltip to show when hovering over this verb.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Useful for disabled verbs as a replacement for informative pop-up messages.
|
||||
/// </remarks>
|
||||
public string? Tooltip;
|
||||
|
||||
/// <summary>
|
||||
/// Determines the priority of the verb. This affects both how the verb is displayed in the context menu
|
||||
/// GUI, and which verb is actually executed when left/alt clicking.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Bigger is higher priority (appears first, gets executed preferentially).
|
||||
/// </remarks>
|
||||
public int Priority;
|
||||
|
||||
/// <summary>
|
||||
/// Raw texture path used to load the <see cref="Icon"/>.
|
||||
/// </summary>
|
||||
public string? IconTexture;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to close the context menu after using it to run this verb.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting this to false may be useful for repeatable actions, like rotating an object or maybe knocking on
|
||||
/// a window.
|
||||
/// </remarks>
|
||||
public bool CloseMenu = true;
|
||||
|
||||
/// <summary>
|
||||
/// Compares two verbs based on their <see cref="Priority"/>, <see cref="Category"/>, <see cref="Text"/>,
|
||||
/// and <see cref="IconTexture"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is comparison is used when storing verbs in a SortedSet. The ordering of verbs determines both how
|
||||
/// the verbs are displayed in the context menu, and the order in which alternative action verbs are
|
||||
/// executed when alt-clicking.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If two verbs are equal according to this comparison, they cannot both be added to the same sorted set of
|
||||
/// verbs. This is desirable, given that these verbs would also appear identical in the context menu.
|
||||
/// Distinct verbs should always have a unique and descriptive combination of text, icon, and category.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is not Verb otherVerb)
|
||||
return -1;
|
||||
|
||||
// Sort first by priority
|
||||
if (Priority != otherVerb.Priority)
|
||||
return otherVerb.Priority - Priority;
|
||||
|
||||
// Then try use alphabetical verb categories. Uncategorized verbs always appear first.
|
||||
if (Category?.Text != otherVerb.Category?.Text)
|
||||
{
|
||||
return string.Compare(Category?.Text, otherVerb.Category?.Text, StringComparison.CurrentCulture);
|
||||
}
|
||||
|
||||
// Then try use alphabetical verb text.
|
||||
if (Text != otherVerb.Text)
|
||||
{
|
||||
return string.Compare(Text, otherVerb.Text, StringComparison.CurrentCulture);
|
||||
}
|
||||
|
||||
// Finally, compare icon texture paths. Note that this matters for verbs that don't have any text (e.g., the rotate-verbs)
|
||||
return string.Compare(IconTexture, otherVerb.IconTexture, StringComparison.CurrentCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user