Actions System + UI (#2710)

Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
chairbender
2020-12-13 14:28:20 -08:00
committed by GitHub
parent fd0df9a00a
commit 7a3c281f60
150 changed files with 7283 additions and 854 deletions

View File

@@ -0,0 +1,70 @@
using System.Collections.Generic;
using System.Linq;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
namespace Content.Shared.Actions
{
/// <summary>
/// Provides access to all configured actions by action type.
/// </summary>
public class ActionManager
{
[Dependency]
private readonly IPrototypeManager _prototypeManager = default!;
private Dictionary<ActionType, ActionPrototype> _typeToAction;
private Dictionary<ItemActionType, ItemActionPrototype> _typeToItemAction;
public void Initialize()
{
_typeToAction = new Dictionary<ActionType, ActionPrototype>();
foreach (var action in _prototypeManager.EnumeratePrototypes<ActionPrototype>())
{
if (!_typeToAction.TryAdd(action.ActionType, action))
{
Logger.ErrorS("action",
"Found action with duplicate actionType {0} - all actions must have" +
" a unique actionType, this one will be skipped", action.ActionType);
}
}
_typeToItemAction = new Dictionary<ItemActionType, ItemActionPrototype>();
foreach (var action in _prototypeManager.EnumeratePrototypes<ItemActionPrototype>())
{
if (!_typeToItemAction.TryAdd(action.ActionType, action))
{
Logger.ErrorS("action",
"Found itemAction with duplicate actionType {0} - all actions must have" +
" a unique actionType, this one will be skipped", action.ActionType);
}
}
}
/// <returns>all action prototypes of all types</returns>
public IEnumerable<BaseActionPrototype> EnumerateActions()
{
return _typeToAction.Values.Concat<BaseActionPrototype>(_typeToItemAction.Values);
}
/// <summary>
/// Tries to get the action of the indicated type
/// </summary>
/// <returns>true if found</returns>
public bool TryGet(ActionType actionType, out ActionPrototype action)
{
return _typeToAction.TryGetValue(actionType, out action);
}
/// <summary>
/// Tries to get the item action of the indicated type
/// </summary>
/// <returns>true if found</returns>
public bool TryGet(ItemActionType actionType, out ItemActionPrototype action)
{
return _typeToItemAction.TryGetValue(actionType, out action);
}
}
}

View File

@@ -0,0 +1,100 @@
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using YamlDotNet.RepresentationModel;
using Robust.Shared.Log;
namespace Content.Shared.Actions
{
/// <summary>
/// An action which is granted directly to an entity (such as an innate ability
/// or skill).
/// </summary>
[Prototype("action")]
public class ActionPrototype : BaseActionPrototype
{
/// <summary>
/// Type of action, no 2 action prototypes should have the same one.
/// </summary>
public ActionType ActionType { get; private set; }
/// <summary>
/// The IInstantAction that should be invoked when performing this
/// action. Null if this is not an Instant ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public IInstantAction InstantAction { get; private set; }
/// <summary>
/// The IToggleAction that should be invoked when performing this
/// action. Null if this is not a Toggle ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public IToggleAction ToggleAction { get; private set; }
/// <summary>
/// The ITargetEntityAction that should be invoked when performing this
/// action. Null if this is not a TargetEntity ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public ITargetEntityAction TargetEntityAction { get; private set; }
/// <summary>
/// The ITargetPointAction that should be invoked when performing this
/// action. Null if this is not a TargetPoint ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public ITargetPointAction TargetPointAction { get; private set; }
public override void LoadFrom(YamlMappingNode mapping)
{
base.LoadFrom(mapping);
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(this, x => x.ActionType, "actionType", ActionType.Error);
if (ActionType == ActionType.Error)
{
Logger.ErrorS("action", "missing or invalid actionType for action with name {0}", Name);
}
// TODO: Split this class into server/client after RobustToolbox#1405
if (IoCManager.Resolve<IModuleManager>().IsClientModule) return;
IActionBehavior behavior = null;
serializer.DataField(ref behavior, "behavior", null);
switch (behavior)
{
case null:
BehaviorType = BehaviorType.None;
Logger.ErrorS("action", "missing or invalid behavior for action with name {0}", Name);
break;
case IInstantAction instantAction:
ValidateBehaviorType(BehaviorType.Instant, typeof(IInstantAction));
BehaviorType = BehaviorType.Instant;
InstantAction = instantAction;
break;
case IToggleAction toggleAction:
ValidateBehaviorType(BehaviorType.Toggle, typeof(IToggleAction));
BehaviorType = BehaviorType.Toggle;
ToggleAction = toggleAction;
break;
case ITargetEntityAction targetEntity:
ValidateBehaviorType(BehaviorType.TargetEntity, typeof(ITargetEntityAction));
BehaviorType = BehaviorType.TargetEntity;
TargetEntityAction = targetEntity;
break;
case ITargetPointAction targetPointAction:
ValidateBehaviorType(BehaviorType.TargetPoint, typeof(ITargetPointAction));
BehaviorType = BehaviorType.TargetPoint;
TargetPointAction = targetPointAction;
break;
default:
BehaviorType = BehaviorType.None;
Logger.ErrorS("action", "unrecognized behavior type for action with name {0}", Name);
break;
}
}
}
}

View File

@@ -0,0 +1,33 @@
namespace Content.Shared.Actions
{
/// <summary>
/// Every possible action. Corresponds to actionType in action prototypes.
/// </summary>
public enum ActionType : byte
{
Error,
HumanScream,
DebugInstant,
DebugToggle,
DebugTargetPoint,
DebugTargetPointRepeat,
DebugTargetEntity,
DebugTargetEntityRepeat
}
/// <summary>
/// Every possible item action. Corresponds to actionType in itemAction prototypes.
/// </summary>
public enum ItemActionType : byte
{
Error,
ToggleInternals,
ToggleLight,
DebugInstant,
DebugToggle,
DebugTargetPoint,
DebugTargetPointRepeat,
DebugTargetEntity,
DebugTargetEntityRepeat
}
}

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Actions
{
/// <summary>
/// Base class for action prototypes.
/// </summary>
public abstract class BaseActionPrototype : IPrototype
{
/// <summary>
/// Icon representing this action in the UI.
/// </summary>
[ViewVariables]
public SpriteSpecifier Icon { get; private set; }
/// <summary>
/// For toggle actions only, icon to show when toggled on. If omitted,
/// the action will simply be highlighted when turned on.
/// </summary>
[ViewVariables]
public SpriteSpecifier IconOn { get; private set; }
/// <summary>
/// Name to show in UI. Accepts formatting.
/// </summary>
public FormattedMessage Name { get; private set; }
/// <summary>
/// Description to show in UI. Accepts formatting.
/// </summary>
public FormattedMessage Description { get; private set; }
/// <summary>
/// Requirements message to show in UI. Accepts formatting, but generally should be avoided
/// so the requirements message isn't too prominent in the tooltip.
/// </summary>
public string Requires { get; private set; }
/// <summary>
/// The type of behavior this action has. This is valid clientside and serverside.
/// </summary>
public BehaviorType BehaviorType { get; protected set; }
/// <summary>
/// For targetpoint or targetentity actions, if this is true the action will remain
/// selected after it is used, so it can be continuously re-used. If this is false,
/// the action will be deselected after one use.
/// </summary>
public bool Repeat { get; private set; }
/// <summary>
/// Filters that can be used to filter this item in action menu.
/// </summary>
public IEnumerable<string> Filters { get; private set; }
/// <summary>
/// Keywords that can be used to search this item in action menu.
/// </summary>
public IEnumerable<string> Keywords { get; private set; }
public virtual void LoadFrom(YamlMappingNode mapping)
{
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataReadFunction("name", string.Empty,
s => Name = FormattedMessage.FromMarkup(s));
serializer.DataReadFunction("description", string.Empty,
s => Description = FormattedMessage.FromMarkup(s));
serializer.DataField(this, x => x.Requires,"requires", null);
serializer.DataField(this, x => x.Icon,"icon", SpriteSpecifier.Invalid);
serializer.DataField(this, x => x.IconOn,"iconOn", SpriteSpecifier.Invalid);
// client needs to know what type of behavior it is even if the actual implementation is only
// on server side. If we wanted to avoid this we'd need to always add a shared or clientside interface
// for each action even if there was only server-side logic, which would be cumbersome
serializer.DataField(this, x => x.BehaviorType, "behaviorType", BehaviorType.None);
if (BehaviorType == BehaviorType.None)
{
Logger.ErrorS("action", "Missing behaviorType for action with name {0}", Name);
}
if (BehaviorType != BehaviorType.Toggle && IconOn != SpriteSpecifier.Invalid)
{
Logger.ErrorS("action", "for action {0}, iconOn was specified but behavior" +
" type was {1}. iconOn is only supported for Toggle behavior type.", Name);
}
serializer.DataField(this, x => x.Repeat, "repeat", false);
if (Repeat && BehaviorType != BehaviorType.TargetEntity && BehaviorType != BehaviorType.TargetPoint)
{
Logger.ErrorS("action", " action named {0} used repeat: true, but this is only supported for" +
" TargetEntity and TargetPoint behaviorType and its behaviorType is {1}",
Name, BehaviorType);
}
serializer.DataReadFunction("filters", new List<string>(),
rawTags =>
{
Filters = rawTags.Select(rawTag => rawTag.Trim()).ToList();
});
serializer.DataReadFunction("keywords", new List<string>(),
rawTags =>
{
Keywords = rawTags.Select(rawTag => rawTag.Trim()).ToList();
});
}
protected void ValidateBehaviorType(BehaviorType expected, Type actualInterface)
{
if (BehaviorType != expected)
{
Logger.ErrorS("action", "for action named {0}, behavior implements " +
"{1}, so behaviorType should be {2} but was {3}", Name, actualInterface.Name, expected, BehaviorType);
}
}
}
/// <summary>
/// The behavior / logic of the action. Each of these corresponds to a particular IActionBehavior
/// (for actions) or IItemActionBehavior (for item actions)
/// interface. Corresponds to action.behaviorType in YAML
/// </summary>
public enum BehaviorType
{
/// <summary>
/// Action doesn't do anything.
/// </summary>
None,
/// <summary>
/// IInstantAction/IInstantItemAction. Action which does something immediately when used and has
/// no target.
/// </summary>
Instant,
/// <summary>
/// IToggleAction/IToggleItemAction Action which can be toggled on and off
/// </summary>
Toggle,
/// <summary>
/// ITargetEntityAction/ITargetEntityItemAction. Action which is used on a targeted entity.
/// </summary>
TargetEntity,
/// <summary>
/// ITargetPointAction/ITargetPointItemAction. Action which requires the user to select a target point, which
/// does not necessarily have an entity on it.
/// </summary>
TargetPoint
}
}

View File

@@ -0,0 +1,44 @@
using System;
using Content.Shared.GameObjects.Components.Mobs;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
namespace Content.Shared.Actions
{
/// <summary>
/// Currently just a marker interface delineating the different possible
/// types of action behaviors.
/// </summary>
public interface IActionBehavior : IExposeData { }
/// <summary>
/// Base class for all action event args
/// </summary>
public abstract class ActionEventArgs : EventArgs
{
/// <summary>
/// Entity performing the action.
/// </summary>
public readonly IEntity Performer;
/// <summary>
/// Action being performed
/// </summary>
public readonly ActionType ActionType;
/// <summary>
/// Actions component of the performer.
/// </summary>
public readonly SharedActionsComponent PerformerActions;
public ActionEventArgs(IEntity performer, ActionType actionType)
{
Performer = performer;
ActionType = actionType;
if (!Performer.TryGetComponent(out PerformerActions))
{
throw new InvalidOperationException($"performer {performer.Name} tried to perform action {actionType} " +
$" but the performer had no actions component," +
" which should never occur");
}
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
namespace Content.Shared.Actions
{
/// <summary>
/// Action which does something immediately when used and has
/// no target.
/// </summary>
public interface IInstantAction : IActionBehavior
{
/// <summary>
/// Invoked when the instant action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoInstantAction(InstantActionEventArgs args);
}
public class InstantActionEventArgs : ActionEventArgs
{
public InstantActionEventArgs(IEntity performer, ActionType actionType) : base(performer, actionType)
{
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
namespace Content.Shared.Actions
{
/// <summary>
/// Item action which does something immediately when used and has
/// no target.
/// </summary>
public interface IInstantItemAction : IItemActionBehavior
{
/// <summary>
/// Invoked when the instant action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoInstantAction(InstantItemActionEventArgs args);
}
public class InstantItemActionEventArgs : ItemActionEventArgs
{
public InstantItemActionEventArgs(IEntity performer, IEntity item, ItemActionType actionType) :
base(performer, item, actionType)
{
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Content.Shared.GameObjects.Components.Mobs;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
namespace Content.Shared.Actions
{
/// <summary>
/// Currently just a marker interface delineating the different possible
/// types of item action behaviors.
/// </summary>
public interface IItemActionBehavior : IExposeData
{
}
/// <summary>
/// Base class for all item action event args
/// </summary>
public abstract class ItemActionEventArgs : EventArgs
{
/// <summary>
/// Entity performing the action.
/// </summary>
public readonly IEntity Performer;
/// <summary>
/// Item being used to perform the action
/// </summary>
public readonly IEntity Item;
/// <summary>
/// Action being performed
/// </summary>
public readonly ItemActionType ActionType;
/// <summary>
/// Item actions component of the item.
/// </summary>
public readonly ItemActionsComponent ItemActions;
public ItemActionEventArgs(IEntity performer, IEntity item, ItemActionType actionType)
{
Performer = performer;
ActionType = actionType;
Item = item;
if (!Item.TryGetComponent(out ItemActions))
{
throw new InvalidOperationException($"performer {performer.Name} tried to perform item action {actionType} " +
$" for item {Item.Name} but the item had no ItemActionsComponent," +
" which should never occur");
}
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Map;
namespace Content.Shared.Actions
{
/// <summary>
/// Action which is used on a targeted entity.
/// </summary>
public interface ITargetEntityAction : IActionBehavior
{
/// <summary>
/// Invoked when the target entity action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoTargetEntityAction(TargetEntityActionEventArgs args);
}
public class TargetEntityActionEventArgs : ActionEventArgs
{
/// <summary>
/// Entity being targeted
/// </summary>
public readonly IEntity Target;
public TargetEntityActionEventArgs(IEntity performer, ActionType actionType, IEntity target) :
base(performer, actionType)
{
Target = target;
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Serialization;
using Robust.Shared.Map;
namespace Content.Shared.Actions
{
/// <summary>
/// Item action which is used on a targeted entity.
/// </summary>
public interface ITargetEntityItemAction : IItemActionBehavior
{
/// <summary>
/// Invoked when the target entity action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoTargetEntityAction(TargetEntityItemActionEventArgs args);
}
public class TargetEntityItemActionEventArgs : ItemActionEventArgs
{
/// <summary>
/// Entity being targeted
/// </summary>
public readonly IEntity Target;
public TargetEntityItemActionEventArgs(IEntity performer, IEntity target, IEntity item,
ItemActionType actionType) : base(performer, item, actionType)
{
Target = target;
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Shared.Actions
{
/// <summary>
/// Action which requires the user to select a target point, which
/// does not necessarily have an entity on it.
/// </summary>
public interface ITargetPointAction : IActionBehavior
{
/// <summary>
/// Invoked when the target point action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoTargetPointAction(TargetPointActionEventArgs args);
}
public class TargetPointActionEventArgs : ActionEventArgs
{
/// <summary>
/// Local coordinates of the targeted position.
/// </summary>
public readonly EntityCoordinates Target;
public TargetPointActionEventArgs(IEntity performer, EntityCoordinates target, ActionType actionType)
: base(performer, actionType)
{
Target = target;
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Map;
namespace Content.Shared.Actions
{
/// <summary>
/// Item action which requires the user to select a target point, which
/// does not necessarily have an entity on it.
/// </summary>
public interface ITargetPointItemAction : IItemActionBehavior
{
/// <summary>
/// Invoked when the target point action should be performed.
/// Implementation should perform the server side logic of the action.
/// </summary>
void DoTargetPointAction(TargetPointItemActionEventArgs args);
}
public class TargetPointItemActionEventArgs : ItemActionEventArgs
{
/// <summary>
/// Local coordinates of the targeted position.
/// </summary>
public readonly EntityCoordinates Target;
public TargetPointItemActionEventArgs(IEntity performer, EntityCoordinates target, IEntity item,
ItemActionType actionType) : base(performer, item, actionType)
{
Target = target;
}
}
}

View File

@@ -0,0 +1,41 @@
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Shared.Actions
{
/// <summary>
/// Action which can be toggled on and off
/// </summary>
public interface IToggleAction : IActionBehavior
{
/// <summary>
/// Invoked when the action will be toggled on/off.
/// Implementation should perform the server side logic of whatever
/// happens when it is toggled on / off.
/// </summary>
/// <returns>true if the attempt to toggle was successful, meaning the state should be toggled to the desired value.
/// False to leave toggle status unchanged. This is NOT returning the new toggle status, it is only returning
/// whether the attempt to toggle to the indicated status was successful.
///
/// Note that it's still okay if the implementation directly modifies toggle status via SharedActionsComponent,
/// this is just an additional level of safety to ensure implementations will always
/// explicitly indicate if the toggle status should be changed.</returns>
bool DoToggleAction(ToggleActionEventArgs args);
}
public class ToggleActionEventArgs : ActionEventArgs
{
/// <summary>
/// True if the toggle is attempting to be toggled on, false if attempting to toggle off
/// </summary>
public readonly bool ToggledOn;
/// <summary>
/// Opposite of ToggledOn
/// </summary>
public bool ToggledOff => !ToggledOn;
public ToggleActionEventArgs(IEntity performer, ActionType actionType, bool toggledOn) : base(performer, actionType)
{
ToggledOn = toggledOn;
}
}
}

View File

@@ -0,0 +1,42 @@
using Robust.Shared.Interfaces.GameObjects;
namespace Content.Shared.Actions
{
/// <summary>
/// Item action which can be toggled on and off
/// </summary>
public interface IToggleItemAction : IItemActionBehavior
{
/// <summary>
/// Invoked when the action will be toggled on/off.
/// Implementation should perform the server side logic of whatever
/// happens when it is toggled on / off.
/// </summary>
/// <returns>true if the attempt to toggle was successful, meaning the state should be toggled to the desired value.
/// False to leave toggle status unchanged. This is NOT returning the new toggle status, it is only returning
/// whether the attempt to toggle to the indicated status was successful.
///
/// Note that it's still okay if the implementation directly modifies toggle status via ItemActionsComponent,
/// this is just an additional level of safety to ensure implementations will always
/// explicitly indicate if the toggle status should be changed.</returns>
bool DoToggleAction(ToggleItemActionEventArgs args);
}
public class ToggleItemActionEventArgs : ItemActionEventArgs
{
/// <summary>
/// True if the toggle was toggled on, false if it was toggled off
/// </summary>
public readonly bool ToggledOn;
/// <summary>
/// Opposite of ToggledOn
/// </summary>
public bool ToggledOff => !ToggledOn;
public ToggleItemActionEventArgs(IEntity performer, bool toggledOn, IEntity item,
ItemActionType actionType) : base(performer, item, actionType)
{
ToggledOn = toggledOn;
}
}
}

View File

@@ -0,0 +1,122 @@
using Content.Shared.Interfaces;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using YamlDotNet.RepresentationModel;
namespace Content.Shared.Actions
{
/// <summary>
/// An action which is granted to an entity via an item (such as toggling a flashlight).
/// </summary>
[Prototype("itemAction")]
public class ItemActionPrototype : BaseActionPrototype
{
/// <summary>
/// Type of item action, no 2 itemAction prototypes should have the same one.
/// </summary>
public ItemActionType ActionType { get; private set; }
/// <see cref="ItemActionIconStyle"/>
public ItemActionIconStyle IconStyle { get; private set; }
/// <summary>
/// The IInstantItemAction that should be invoked when performing this
/// action. Null if this is not an Instant ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public IInstantItemAction InstantAction { get; private set; }
/// <summary>
/// The IToggleItemAction that should be invoked when performing this
/// action. Null if this is not a Toggle ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public IToggleItemAction ToggleAction { get; private set; }
/// <summary>
/// The ITargetEntityItemAction that should be invoked when performing this
/// action. Null if this is not a TargetEntity ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public ITargetEntityItemAction TargetEntityAction { get; private set; }
/// <summary>
/// The ITargetPointItemAction that should be invoked when performing this
/// action. Null if this is not a TargetPoint ActionBehaviorType.
/// Will be null on client side if the behavior is not in Content.Client.
/// </summary>
public ITargetPointItemAction TargetPointAction { get; private set; }
public override void LoadFrom(YamlMappingNode mapping)
{
base.LoadFrom(mapping);
var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(this, x => x.ActionType, "actionType", ItemActionType.Error);
if (ActionType == ItemActionType.Error)
{
Logger.ErrorS("action", "missing or invalid actionType for action with name {0}", Name);
}
serializer.DataField(this, x => x.IconStyle, "iconStyle", ItemActionIconStyle.BigItem);
// TODO: Split this class into server/client after RobustToolbox#1405
if (IoCManager.Resolve<IModuleManager>().IsClientModule) return;
IItemActionBehavior behavior = null;
serializer.DataField(ref behavior, "behavior", null);
switch (behavior)
{
case null:
BehaviorType = BehaviorType.None;
Logger.ErrorS("action", "missing or invalid behavior for action with name {0}", Name);
break;
case IInstantItemAction instantAction:
ValidateBehaviorType(BehaviorType.Instant, typeof(IInstantItemAction));
BehaviorType = BehaviorType.Instant;
InstantAction = instantAction;
break;
case IToggleItemAction toggleAction:
ValidateBehaviorType(BehaviorType.Toggle, typeof(IToggleItemAction));
BehaviorType = BehaviorType.Toggle;
ToggleAction = toggleAction;
break;
case ITargetEntityItemAction targetEntity:
ValidateBehaviorType(BehaviorType.TargetEntity, typeof(ITargetEntityItemAction));
BehaviorType = BehaviorType.TargetEntity;
TargetEntityAction = targetEntity;
break;
case ITargetPointItemAction targetPointAction:
ValidateBehaviorType(BehaviorType.TargetPoint, typeof(ITargetPointItemAction));
BehaviorType = BehaviorType.TargetPoint;
TargetPointAction = targetPointAction;
break;
default:
BehaviorType = BehaviorType.None;
Logger.ErrorS("action", "unrecognized behavior type for action with name {0}", Name);
break;
}
}
}
/// <summary>
/// Determines how the action icon appears in the hotbar for item actions.
/// </summary>
public enum ItemActionIconStyle : byte
{
/// <summary>
/// The default - the item icon will be big with a small action icon in the corner
/// </summary>
BigItem,
/// <summary>
/// The action icon will be big with a small item icon in the corner
/// </summary>
BigAction,
/// <summary>
/// BigAction but no item icon will be shown in the corner.
/// </summary>
NoItem
}
}