using Content.Shared.Actions; using Robust.Shared.Audio; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; using Robust.Shared.Utility; namespace Content.Shared.Actions.Components; /// /// Component all actions are required to have. /// [RegisterComponent, NetworkedComponent, Access(typeof(SharedActionsSystem))] [AutoGenerateComponentState(true, true)] [EntityCategory("Actions")] public sealed partial class ActionComponent : Component { /// /// Icon representing this action in the UI. /// [DataField, AutoNetworkedField] public SpriteSpecifier? Icon; /// /// For toggle actions only, icon to show when toggled on. If omitted, the action will simply be highlighted /// when turned on. /// [DataField, AutoNetworkedField] public SpriteSpecifier? IconOn; /// /// For toggle actions only, background to show when toggled on. /// [DataField] public SpriteSpecifier? BackgroundOn; /// /// If not null, this color will modulate the action icon color. /// /// /// This currently only exists for decal-placement actions, so that the action icons correspond to the color of /// the decal. But this is probably useful for other actions, including maybe changing color on toggle. /// [DataField, AutoNetworkedField] public Color IconColor = Color.White; /// /// The original this action was. /// [DataField, AutoNetworkedField] public Color OriginalIconColor; /// /// The color the action should turn to when disabled /// [DataField] public Color DisabledIconColor = Color.DimGray; /// /// Keywords that can be used to search for this action in the action menu. /// [DataField, AutoNetworkedField] public HashSet Keywords = new(); /// /// Whether this action is currently enabled. If not enabled, this action cannot be performed. /// [DataField, AutoNetworkedField] public bool Enabled = true; /// /// The toggle state of this action. Toggling switches the currently displayed icon, see and . /// /// /// The toggle can set directly via , but it will also be /// automatically toggled for targeted-actions while selecting a target. /// [DataField, AutoNetworkedField] public bool Toggled; /// /// The current cooldown on the action. /// [DataField, AutoNetworkedField] public ActionCooldown? Cooldown; /// /// If true, the action will have an initial cooldown applied upon addition. /// [DataField] public bool StartDelay = false; /// /// Time interval between action uses. /// [DataField, AutoNetworkedField] public TimeSpan? UseDelay; /// /// The entity that contains this action. If the action is innate, this may be the user themselves. /// This should almost always be non-null. /// [Access(typeof(ActionContainerSystem), typeof(SharedActionsSystem))] [DataField, AutoNetworkedField] public EntityUid? Container; /// /// Entity to use for the action icon. If no entity is provided and the differs from /// , then it will default to using /// public EntityUid? EntityIcon { get { if (EntIcon != null) return EntIcon; if (AttachedEntity != Container) return Container; return null; } set => EntIcon = value; } [DataField, AutoNetworkedField] public EntityUid? EntIcon; /// /// Whether the action system should block this action if the user cannot currently interact. Some spells or /// abilities may want to disable this and implement their own checks. /// [DataField, AutoNetworkedField] public bool CheckCanInteract = true; /// /// Whether to check if the user is conscious or not. Can be used instead of /// for a more permissive check. /// [DataField, AutoNetworkedField] public bool CheckConsciousness = true; /// /// If true, this will cause the action to only execute locally without ever notifying the server. /// [DataField, AutoNetworkedField] public bool ClientExclusive; /// /// Determines the order in which actions are automatically added the action bar. /// [DataField, AutoNetworkedField] public int Priority = 0; /// /// What entity, if any, currently has this action in the actions component? /// [DataField, AutoNetworkedField] public EntityUid? AttachedEntity; /// /// If true, this will cause the the action event to always be raised directed at the action performer/user instead of the action's container/provider. /// [DataField, AutoNetworkedField] public bool RaiseOnUser; /// /// If true, this will cause the the action event to always be raised directed at the action itself instead of the action's container/provider. /// Takes priority over RaiseOnUser. /// [DataField] [Obsolete("This datafield will be reworked in an upcoming action refactor")] public bool RaiseOnAction; /// /// Whether or not to automatically add this action to the action bar when it becomes available. /// [DataField, AutoNetworkedField] public bool AutoPopulate = true; /// /// Temporary actions are deleted when they get removed a . /// [DataField, AutoNetworkedField] public bool Temporary; /// /// Determines the appearance of the entity-icon for actions that are enabled via some entity. /// [DataField, AutoNetworkedField] public ItemActionIconStyle ItemIconStyle; /// /// If not null, this sound will be played when performing this action. /// [DataField, AutoNetworkedField] public SoundSpecifier? Sound; } [DataRecord, Serializable, NetSerializable] public record struct ActionCooldown { [DataField(required: true, customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan Start; [DataField(required: true, customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan End; }