#nullable enable
using System;
using System.Collections.Generic;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.Actions
{
///
/// Base class for action prototypes.
///
[ImplicitDataDefinitionForInheritors]
public abstract class BaseActionPrototype : IPrototype, ISerializationHooks
{
public abstract string ID { get; }
///
/// Icon representing this action in the UI.
///
[ViewVariables]
[field: DataField("icon")]
public SpriteSpecifier Icon { get; } = SpriteSpecifier.Invalid;
///
/// For toggle actions only, icon to show when toggled on. If omitted,
/// the action will simply be highlighted when turned on.
///
[ViewVariables]
[field: DataField("iconOn")]
public SpriteSpecifier IconOn { get; } = SpriteSpecifier.Invalid;
///
/// Name to show in UI. Accepts formatting.
///
[DataField("name")]
public FormattedMessage Name { get; private set; } = new();
///
/// Description to show in UI. Accepts formatting.
///
[field: DataField("description")]
public FormattedMessage Description { get; } = new();
///
/// Requirements message to show in UI. Accepts formatting, but generally should be avoided
/// so the requirements message isn't too prominent in the tooltip.
///
[field: DataField("requires")]
public string Requires { get; } = string.Empty;
///
/// The type of behavior this action has. This is valid clientside and serverside.
///
[DataField("behaviorType")]
public BehaviorType BehaviorType { get; protected set; } = BehaviorType.None;
///
/// 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.
///
[field: DataField("repeat")]
public bool Repeat { get; }
///
/// For TargetEntity/TargetPoint actions, should the action be de-selected if currently selected (choosing a target)
/// when it goes on cooldown. Defaults to false.
///
[field: DataField("deselectOnCooldown")]
public bool DeselectOnCooldown { get; }
///
/// For TargetEntity actions, should the action be de-selected if the user doesn't click an entity when
/// selecting a target. Defaults to false.
///
[field: DataField("deselectWhenEntityNotClicked")]
public bool DeselectWhenEntityNotClicked { get; }
[DataField("filters")] private List _filters = new();
///
/// Filters that can be used to filter this item in action menu.
///
public IEnumerable Filters => _filters;
[DataField("keywords")] private List _keywords = new();
///
/// Keywords that can be used to search this item in action menu.
///
public IEnumerable Keywords => _keywords;
///
/// True if this is an action that requires selecting a target
///
public bool IsTargetAction =>
BehaviorType == BehaviorType.TargetEntity || BehaviorType == BehaviorType.TargetPoint;
public virtual void AfterDeserialization()
{
Name = new FormattedMessage();
Name.AddText(ID);
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);
}
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);
}
}
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);
}
}
}
///
/// 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
///
public enum BehaviorType
{
///
/// Action doesn't do anything.
///
None,
///
/// IInstantAction/IInstantItemAction. Action which does something immediately when used and has
/// no target.
///
Instant,
///
/// IToggleAction/IToggleItemAction Action which can be toggled on and off
///
Toggle,
///
/// ITargetEntityAction/ITargetEntityItemAction. Action which is used on a targeted entity.
///
TargetEntity,
///
/// ITargetPointAction/ITargetPointItemAction. Action which requires the user to select a target point, which
/// does not necessarily have an entity on it.
///
TargetPoint
}
}