1
0

BaseActionComponent.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. using Robust.Shared.Audio;
  2. using Robust.Shared.Prototypes;
  3. using Robust.Shared.Serialization;
  4. using Robust.Shared.Utility;
  5. namespace Content.Shared.Actions;
  6. // TODO ACTIONS make this a separate component and remove the inheritance stuff.
  7. // TODO ACTIONS convert to auto comp state?
  8. // TODO add access attribute. Need to figure out what to do with decal & mapping actions.
  9. // [Access(typeof(SharedActionsSystem))]
  10. [EntityCategory("Actions")]
  11. public abstract partial class BaseActionComponent : Component
  12. {
  13. public abstract BaseActionEvent? BaseEvent { get; }
  14. /// <summary>
  15. /// Icon representing this action in the UI.
  16. /// </summary>
  17. [DataField("icon")] public SpriteSpecifier? Icon;
  18. /// <summary>
  19. /// For toggle actions only, icon to show when toggled on. If omitted, the action will simply be highlighted
  20. /// when turned on.
  21. /// </summary>
  22. [DataField("iconOn")] public SpriteSpecifier? IconOn;
  23. /// <summary>
  24. /// For toggle actions only, background to show when toggled on.
  25. /// </summary>
  26. [DataField] public SpriteSpecifier? BackgroundOn;
  27. /// <summary>
  28. /// If not null, this color will modulate the action icon color.
  29. /// </summary>
  30. /// <remarks>
  31. /// This currently only exists for decal-placement actions, so that the action icons correspond to the color of
  32. /// the decal. But this is probably useful for other actions, including maybe changing color on toggle.
  33. /// </remarks>
  34. [DataField("iconColor")] public Color IconColor = Color.White;
  35. /// <summary>
  36. /// The original <see cref="IconColor"/> this action was.
  37. /// </summary>
  38. [DataField] public Color OriginalIconColor;
  39. /// <summary>
  40. /// The color the action should turn to when disabled
  41. /// </summary>
  42. [DataField] public Color DisabledIconColor = Color.DimGray;
  43. /// <summary>
  44. /// Keywords that can be used to search for this action in the action menu.
  45. /// </summary>
  46. [DataField("keywords")] public HashSet<string> Keywords = new();
  47. /// <summary>
  48. /// Whether this action is currently enabled. If not enabled, this action cannot be performed.
  49. /// </summary>
  50. [DataField("enabled")] public bool Enabled = true;
  51. /// <summary>
  52. /// The toggle state of this action. Toggling switches the currently displayed icon, see <see cref="Icon"/> and <see cref="IconOn"/>.
  53. /// </summary>
  54. /// <remarks>
  55. /// The toggle can set directly via <see cref="SharedActionsSystem.SetToggled"/>, but it will also be
  56. /// automatically toggled for targeted-actions while selecting a target.
  57. /// </remarks>
  58. [DataField]
  59. public bool Toggled;
  60. /// <summary>
  61. /// The current cooldown on the action.
  62. /// </summary>
  63. // TODO serialization
  64. public (TimeSpan Start, TimeSpan End)? Cooldown;
  65. /// <summary>
  66. /// If true, the action will have an initial cooldown applied upon addition.
  67. /// </summary>
  68. [DataField] public bool StartDelay = false;
  69. /// <summary>
  70. /// Time interval between action uses.
  71. /// </summary>
  72. [DataField("useDelay")] public TimeSpan? UseDelay;
  73. /// <summary>
  74. /// Convenience tool for actions with limited number of charges. Automatically decremented on use, and the
  75. /// action is disabled when it reaches zero. Does NOT automatically remove the action from the action bar.
  76. /// However, charges will regenerate if <see cref="RenewCharges"/> is enabled and the action will not disable
  77. /// when charges reach zero.
  78. /// </summary>
  79. [DataField("charges")] public int? Charges;
  80. /// <summary>
  81. /// The max charges this action has. If null, this is set automatically from <see cref="Charges"/> on mapinit.
  82. /// </summary>
  83. [DataField] public int? MaxCharges;
  84. /// <summary>
  85. /// If enabled, charges will regenerate after a <see cref="Cooldown"/> is complete
  86. /// </summary>
  87. [DataField("renewCharges")]public bool RenewCharges;
  88. /// <summary>
  89. /// The entity that contains this action. If the action is innate, this may be the user themselves.
  90. /// This should almost always be non-null.
  91. /// </summary>
  92. [Access(typeof(ActionContainerSystem), typeof(SharedActionsSystem))]
  93. [DataField]
  94. public EntityUid? Container;
  95. /// <summary>
  96. /// Entity to use for the action icon. If no entity is provided and the <see cref="Container"/> differs from
  97. /// <see cref="AttachedEntity"/>, then it will default to using <see cref="Container"/>
  98. /// </summary>
  99. public EntityUid? EntityIcon
  100. {
  101. get
  102. {
  103. if (EntIcon != null)
  104. return EntIcon;
  105. if (AttachedEntity != Container)
  106. return Container;
  107. return null;
  108. }
  109. set => EntIcon = value;
  110. }
  111. [DataField]
  112. public EntityUid? EntIcon;
  113. /// <summary>
  114. /// Whether the action system should block this action if the user cannot currently interact. Some spells or
  115. /// abilities may want to disable this and implement their own checks.
  116. /// </summary>
  117. [DataField("checkCanInteract")] public bool CheckCanInteract = true;
  118. /// <summary>
  119. /// Whether to check if the user is conscious or not. Can be used instead of <see cref="CheckCanInteract"/>
  120. /// for a more permissive check.
  121. /// </summary>
  122. [DataField] public bool CheckConsciousness = true;
  123. /// <summary>
  124. /// If true, this will cause the action to only execute locally without ever notifying the server.
  125. /// </summary>
  126. [DataField("clientExclusive")] public bool ClientExclusive = false;
  127. /// <summary>
  128. /// Determines the order in which actions are automatically added the action bar.
  129. /// </summary>
  130. [DataField("priority")] public int Priority = 0;
  131. /// <summary>
  132. /// What entity, if any, currently has this action in the actions component?
  133. /// </summary>
  134. [DataField] public EntityUid? AttachedEntity;
  135. /// <summary>
  136. /// 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.
  137. /// </summary>
  138. [DataField]
  139. public bool RaiseOnUser;
  140. /// <summary>
  141. /// 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.
  142. /// Takes priority over RaiseOnUser.
  143. /// </summary>
  144. [DataField]
  145. [Obsolete("This datafield will be reworked in an upcoming action refactor")]
  146. public bool RaiseOnAction;
  147. /// <summary>
  148. /// Whether or not to automatically add this action to the action bar when it becomes available.
  149. /// </summary>
  150. [DataField("autoPopulate")] public bool AutoPopulate = true;
  151. /// <summary>
  152. /// Temporary actions are deleted when they get removed a <see cref="ActionsComponent"/>.
  153. /// </summary>
  154. [DataField("temporary")] public bool Temporary;
  155. /// <summary>
  156. /// Determines the appearance of the entity-icon for actions that are enabled via some entity.
  157. /// </summary>
  158. [DataField("itemIconStyle")] public ItemActionIconStyle ItemIconStyle;
  159. /// <summary>
  160. /// If not null, this sound will be played when performing this action.
  161. /// </summary>
  162. [DataField("sound")] public SoundSpecifier? Sound;
  163. }
  164. [Serializable, NetSerializable]
  165. public abstract class BaseActionComponentState : ComponentState
  166. {
  167. public SpriteSpecifier? Icon;
  168. public SpriteSpecifier? IconOn;
  169. public Color IconColor;
  170. public Color OriginalIconColor;
  171. public Color DisabledIconColor;
  172. public HashSet<string> Keywords;
  173. public bool Enabled;
  174. public bool Toggled;
  175. public (TimeSpan Start, TimeSpan End)? Cooldown;
  176. public TimeSpan? UseDelay;
  177. public int? Charges;
  178. public int? MaxCharges;
  179. public bool RenewCharges;
  180. public NetEntity? Container;
  181. public NetEntity? EntityIcon;
  182. public bool CheckCanInteract;
  183. public bool CheckConsciousness;
  184. public bool ClientExclusive;
  185. public int Priority;
  186. public NetEntity? AttachedEntity;
  187. public bool RaiseOnUser;
  188. public bool RaiseOnAction;
  189. public bool AutoPopulate;
  190. public bool Temporary;
  191. public ItemActionIconStyle ItemIconStyle;
  192. public SoundSpecifier? Sound;
  193. protected BaseActionComponentState(BaseActionComponent component, IEntityManager entManager)
  194. {
  195. Container = entManager.GetNetEntity(component.Container);
  196. EntityIcon = entManager.GetNetEntity(component.EntIcon);
  197. AttachedEntity = entManager.GetNetEntity(component.AttachedEntity);
  198. RaiseOnUser = component.RaiseOnUser;
  199. RaiseOnAction = component.RaiseOnAction;
  200. Icon = component.Icon;
  201. IconOn = component.IconOn;
  202. IconColor = component.IconColor;
  203. OriginalIconColor = component.OriginalIconColor;
  204. DisabledIconColor = component.DisabledIconColor;
  205. Keywords = component.Keywords;
  206. Enabled = component.Enabled;
  207. Toggled = component.Toggled;
  208. Cooldown = component.Cooldown;
  209. UseDelay = component.UseDelay;
  210. Charges = component.Charges;
  211. MaxCharges = component.MaxCharges;
  212. RenewCharges = component.RenewCharges;
  213. CheckCanInteract = component.CheckCanInteract;
  214. CheckConsciousness = component.CheckConsciousness;
  215. ClientExclusive = component.ClientExclusive;
  216. Priority = component.Priority;
  217. AutoPopulate = component.AutoPopulate;
  218. Temporary = component.Temporary;
  219. ItemIconStyle = component.ItemIconStyle;
  220. Sound = component.Sound;
  221. }
  222. }