2024-05-10 17:04:01 -07:00
using Robust.Shared.Audio ;
2024-06-02 16:08:15 +12:00
using Robust.Shared.Prototypes ;
2023-09-08 18:16:05 -07:00
using Robust.Shared.Serialization ;
using Robust.Shared.Utility ;
namespace Content.Shared.Actions ;
2024-06-02 16:08:15 +12:00
// TODO ACTIONS make this a separate component and remove the inheritance stuff.
2024-02-19 21:08:41 -05:00
// TODO ACTIONS convert to auto comp state?
2023-09-23 04:49:39 -04:00
// TODO add access attribute. Need to figure out what to do with decal & mapping actions.
// [Access(typeof(SharedActionsSystem))]
2024-06-02 16:08:15 +12:00
[EntityCategory("Actions")]
2023-09-08 18:16:05 -07:00
public abstract partial class BaseActionComponent : Component
{
public abstract BaseActionEvent ? BaseEvent { get ; }
/// <summary>
/// Icon representing this action in the UI.
/// </summary>
[DataField("icon")] public SpriteSpecifier ? Icon ;
/// <summary>
/// For toggle actions only, icon to show when toggled on. If omitted, the action will simply be highlighted
/// when turned on.
/// </summary>
[DataField("iconOn")] public SpriteSpecifier ? IconOn ;
2024-05-10 17:04:01 -07:00
/// <summary>
/// For toggle actions only, background to show when toggled on.
/// </summary>
[DataField] public SpriteSpecifier ? BackgroundOn ;
2023-09-08 18:16:05 -07:00
/// <summary>
/// If not null, this color will modulate the action icon color.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
[DataField("iconColor")] public Color IconColor = Color . White ;
2024-09-25 10:27:28 -04:00
/// <summary>
/// The original <see cref="IconColor"/> this action was.
/// </summary>
[DataField] public Color OriginalIconColor ;
/// <summary>
/// The color the action should turn to when disabled
/// </summary>
[DataField] public Color DisabledIconColor = Color . DimGray ;
2023-09-08 18:16:05 -07:00
/// <summary>
/// Keywords that can be used to search for this action in the action menu.
/// </summary>
[DataField("keywords")] public HashSet < string > Keywords = new ( ) ;
/// <summary>
/// Whether this action is currently enabled. If not enabled, this action cannot be performed.
/// </summary>
[DataField("enabled")] public bool Enabled = true ;
/// <summary>
/// The toggle state of this action. Toggling switches the currently displayed icon, see <see cref="Icon"/> and <see cref="IconOn"/>.
/// </summary>
/// <remarks>
/// The toggle can set directly via <see cref="SharedActionsSystem.SetToggled"/>, but it will also be
/// automatically toggled for targeted-actions while selecting a target.
/// </remarks>
2023-09-23 04:49:39 -04:00
[DataField]
2023-09-08 18:16:05 -07:00
public bool Toggled ;
/// <summary>
/// The current cooldown on the action.
/// </summary>
2023-09-23 04:49:39 -04:00
// TODO serialization
2023-09-08 18:16:05 -07:00
public ( TimeSpan Start , TimeSpan End ) ? Cooldown ;
/// <summary>
/// Time interval between action uses.
/// </summary>
[DataField("useDelay")] public TimeSpan ? UseDelay ;
/// <summary>
/// Convenience tool for actions with limited number of charges. Automatically decremented on use, and the
/// action is disabled when it reaches zero. Does NOT automatically remove the action from the action bar.
2023-12-15 04:41:44 -05:00
/// However, charges will regenerate if <see cref="RenewCharges"/> is enabled and the action will not disable
/// when charges reach zero.
2023-09-08 18:16:05 -07:00
/// </summary>
[DataField("charges")] public int? Charges ;
2023-12-15 04:41:44 -05:00
/// <summary>
2024-02-19 21:08:41 -05:00
/// The max charges this action has. If null, this is set automatically from <see cref="Charges"/> on mapinit.
2023-12-15 04:41:44 -05:00
/// </summary>
2024-02-19 21:08:41 -05:00
[DataField] public int? MaxCharges ;
2023-12-15 04:41:44 -05:00
/// <summary>
/// If enabled, charges will regenerate after a <see cref="Cooldown"/> is complete
/// </summary>
[DataField("renewCharges")] public bool RenewCharges ;
2023-09-08 18:16:05 -07:00
/// <summary>
2023-09-23 04:49:39 -04:00
/// The entity that contains this action. If the action is innate, this may be the user themselves.
/// This should almost always be non-null.
2023-09-08 18:16:05 -07:00
/// </summary>
2023-09-23 04:49:39 -04:00
[Access(typeof(ActionContainerSystem), typeof(SharedActionsSystem))]
[DataField]
public EntityUid ? Container ;
2023-09-08 18:16:05 -07:00
/// <summary>
2023-09-23 04:49:39 -04:00
/// Entity to use for the action icon. If no entity is provided and the <see cref="Container"/> differs from
/// <see cref="AttachedEntity"/>, then it will default to using <see cref="Container"/>
2023-09-08 18:16:05 -07:00
/// </summary>
public EntityUid ? EntityIcon
{
2023-09-23 04:49:39 -04:00
get
{
if ( EntIcon ! = null )
return EntIcon ;
if ( AttachedEntity ! = Container )
return Container ;
return null ;
}
set = > EntIcon = value ;
2023-09-08 18:16:05 -07:00
}
2023-09-23 04:49:39 -04:00
[DataField]
public EntityUid ? EntIcon ;
2023-09-08 18:16:05 -07:00
/// <summary>
/// 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.
/// </summary>
[DataField("checkCanInteract")] public bool CheckCanInteract = true ;
2024-03-19 00:35:46 +02:00
/// <summary>
/// Whether to check if the user is conscious or not. Can be used instead of <see cref="CheckCanInteract"/>
/// for a more permissive check.
/// </summary>
[DataField] public bool CheckConsciousness = true ;
2023-09-08 18:16:05 -07:00
/// <summary>
2023-09-23 04:49:39 -04:00
/// If true, this will cause the action to only execute locally without ever notifying the server.
2023-09-08 18:16:05 -07:00
/// </summary>
[DataField("clientExclusive")] public bool ClientExclusive = false ;
/// <summary>
/// Determines the order in which actions are automatically added the action bar.
/// </summary>
[DataField("priority")] public int Priority = 0 ;
/// <summary>
/// What entity, if any, currently has this action in the actions component?
/// </summary>
2024-02-19 21:08:41 -05:00
[DataField] public EntityUid ? AttachedEntity ;
2023-09-08 18:16:05 -07:00
2023-11-03 19:55:32 -04:00
/// <summary>
/// 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.
/// </summary>
[DataField]
public bool RaiseOnUser ;
2023-09-08 18:16:05 -07:00
/// <summary>
/// Whether or not to automatically add this action to the action bar when it becomes available.
/// </summary>
[DataField("autoPopulate")] public bool AutoPopulate = true ;
/// <summary>
2023-09-23 04:49:39 -04:00
/// Temporary actions are deleted when they get removed a <see cref="ActionsComponent"/>.
2023-09-08 18:16:05 -07:00
/// </summary>
[DataField("temporary")] public bool Temporary ;
/// <summary>
/// Determines the appearance of the entity-icon for actions that are enabled via some entity.
/// </summary>
[DataField("itemIconStyle")] public ItemActionIconStyle ItemIconStyle ;
/// <summary>
/// If not null, this sound will be played when performing this action.
/// </summary>
[DataField("sound")] public SoundSpecifier ? Sound ;
}
[Serializable, NetSerializable]
public abstract class BaseActionComponentState : ComponentState
{
public SpriteSpecifier ? Icon ;
public SpriteSpecifier ? IconOn ;
public Color IconColor ;
2024-09-25 10:27:28 -04:00
public Color OriginalIconColor ;
public Color DisabledIconColor ;
2023-09-08 18:16:05 -07:00
public HashSet < string > Keywords ;
public bool Enabled ;
public bool Toggled ;
public ( TimeSpan Start , TimeSpan End ) ? Cooldown ;
public TimeSpan ? UseDelay ;
public int? Charges ;
2024-02-19 21:08:41 -05:00
public int? MaxCharges ;
2023-12-15 04:41:44 -05:00
public bool RenewCharges ;
2023-09-23 04:49:39 -04:00
public NetEntity ? Container ;
2023-09-11 09:42:41 +10:00
public NetEntity ? EntityIcon ;
2023-09-08 18:16:05 -07:00
public bool CheckCanInteract ;
2024-03-19 00:35:46 +02:00
public bool CheckConsciousness ;
2023-09-08 18:16:05 -07:00
public bool ClientExclusive ;
public int Priority ;
2023-09-11 09:42:41 +10:00
public NetEntity ? AttachedEntity ;
2023-11-03 19:55:32 -04:00
public bool RaiseOnUser ;
2023-09-08 18:16:05 -07:00
public bool AutoPopulate ;
public bool Temporary ;
public ItemActionIconStyle ItemIconStyle ;
public SoundSpecifier ? Sound ;
2023-09-11 09:42:41 +10:00
protected BaseActionComponentState ( BaseActionComponent component , IEntityManager entManager )
2023-09-08 18:16:05 -07:00
{
2023-09-23 04:49:39 -04:00
Container = entManager . GetNetEntity ( component . Container ) ;
EntityIcon = entManager . GetNetEntity ( component . EntIcon ) ;
AttachedEntity = entManager . GetNetEntity ( component . AttachedEntity ) ;
2023-11-03 19:55:32 -04:00
RaiseOnUser = component . RaiseOnUser ;
2023-09-08 18:16:05 -07:00
Icon = component . Icon ;
IconOn = component . IconOn ;
IconColor = component . IconColor ;
2024-09-25 10:27:28 -04:00
OriginalIconColor = component . OriginalIconColor ;
DisabledIconColor = component . DisabledIconColor ;
2023-09-08 18:16:05 -07:00
Keywords = component . Keywords ;
Enabled = component . Enabled ;
Toggled = component . Toggled ;
Cooldown = component . Cooldown ;
UseDelay = component . UseDelay ;
Charges = component . Charges ;
2023-12-15 04:41:44 -05:00
MaxCharges = component . MaxCharges ;
RenewCharges = component . RenewCharges ;
2023-09-08 18:16:05 -07:00
CheckCanInteract = component . CheckCanInteract ;
2024-03-19 00:35:46 +02:00
CheckConsciousness = component . CheckConsciousness ;
2023-09-08 18:16:05 -07:00
ClientExclusive = component . ClientExclusive ;
Priority = component . Priority ;
AutoPopulate = component . AutoPopulate ;
Temporary = component . Temporary ;
ItemIconStyle = component . ItemIconStyle ;
Sound = component . Sound ;
}
}