]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Adds real-time charge & disabled action information to Actions (#31821)
authorkeronshb <54602815+keronshb@users.noreply.github.com>
Wed, 25 Sep 2024 14:27:28 +0000 (10:27 -0400)
committerGitHub <noreply@github.com>
Wed, 25 Sep 2024 14:27:28 +0000 (10:27 -0400)
Content.Client/Actions/ActionsSystem.cs
Content.Shared/Actions/BaseActionComponent.cs
Content.Shared/Actions/SharedActionsSystem.cs

index 26a22fa8b8df373fe9e87cd1a9413ddda9fd0164..7b13233bab5cd5c975fe0e1655d89241afcd6123 100644 (file)
@@ -51,6 +51,29 @@ namespace Content.Client.Actions
             SubscribeLocalEvent<EntityWorldTargetActionComponent, ComponentHandleState>(OnEntityWorldTargetHandleState);
         }
 
+        public override void FrameUpdate(float frameTime)
+        {
+            base.FrameUpdate(frameTime);
+
+            var worldActionQuery = EntityQueryEnumerator<WorldTargetActionComponent>();
+            while (worldActionQuery.MoveNext(out var uid, out var action))
+            {
+                UpdateAction(uid, action);
+            }
+
+            var instantActionQuery = EntityQueryEnumerator<InstantActionComponent>();
+            while (instantActionQuery.MoveNext(out var uid, out var action))
+            {
+                UpdateAction(uid, action);
+            }
+
+            var entityActionQuery = EntityQueryEnumerator<EntityTargetActionComponent>();
+            while (entityActionQuery.MoveNext(out var uid, out var action))
+            {
+                UpdateAction(uid, action);
+            }
+        }
+
         private void OnInstantHandleState(EntityUid uid, InstantActionComponent component, ref ComponentHandleState args)
         {
             if (args.Current is not InstantActionComponentState state)
@@ -95,6 +118,8 @@ namespace Content.Client.Actions
             component.Icon = state.Icon;
             component.IconOn = state.IconOn;
             component.IconColor = state.IconColor;
+            component.OriginalIconColor = state.OriginalIconColor;
+            component.DisabledIconColor = state.DisabledIconColor;
             component.Keywords.Clear();
             component.Keywords.UnionWith(state.Keywords);
             component.Enabled = state.Enabled;
@@ -125,6 +150,8 @@ namespace Content.Client.Actions
             if (!ResolveActionData(actionId, ref action))
                 return;
 
+            action.IconColor = action.Charges < 1 ? action.DisabledIconColor : action.OriginalIconColor;
+
             base.UpdateAction(actionId, action);
             if (_playerManager.LocalEntity != action.AttachedEntity)
                 return;
index 9156f747f5c90a0fee240bfad76ac22b51f58957..01452bdc72e0f49643ca05654e2971d2d9a48cd1 100644 (file)
@@ -40,6 +40,16 @@ public abstract partial class BaseActionComponent : Component
     /// </remarks>
     [DataField("iconColor")] public Color IconColor = Color.White;
 
+    /// <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;
+
     /// <summary>
     ///     Keywords that can be used to search for this action in the action menu.
     /// </summary>
@@ -179,6 +189,8 @@ public abstract class BaseActionComponentState : ComponentState
     public SpriteSpecifier? Icon;
     public SpriteSpecifier? IconOn;
     public Color IconColor;
+    public Color OriginalIconColor;
+    public Color DisabledIconColor;
     public HashSet<string> Keywords;
     public bool Enabled;
     public bool Toggled;
@@ -209,6 +221,8 @@ public abstract class BaseActionComponentState : ComponentState
         Icon = component.Icon;
         IconOn = component.IconOn;
         IconColor = component.IconColor;
+        OriginalIconColor = component.OriginalIconColor;
+        DisabledIconColor = component.DisabledIconColor;
         Keywords = component.Keywords;
         Enabled = component.Enabled;
         Toggled = component.Toggled;
index 275634542825d15474620bdaa70257caf69d2697..76b8a1b081b49c29c53775d54afe3110b45fc1be 100644 (file)
@@ -69,8 +69,42 @@ public abstract class SharedActionsSystem : EntitySystem
         SubscribeAllEvent<RequestPerformActionEvent>(OnActionRequest);
     }
 
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+
+        var worldActionQuery = EntityQueryEnumerator<WorldTargetActionComponent>();
+        while (worldActionQuery.MoveNext(out var uid, out var action))
+        {
+            if (IsCooldownActive(action) || !ShouldResetCharges(action))
+                continue;
+
+            ResetCharges(uid, dirty: true);
+        }
+
+        var instantActionQuery = EntityQueryEnumerator<InstantActionComponent>();
+        while (instantActionQuery.MoveNext(out var uid, out var action))
+        {
+            if (IsCooldownActive(action) || !ShouldResetCharges(action))
+                continue;
+
+            ResetCharges(uid, dirty: true);
+        }
+
+        var entityActionQuery = EntityQueryEnumerator<EntityTargetActionComponent>();
+        while (entityActionQuery.MoveNext(out var uid, out var action))
+        {
+            if (IsCooldownActive(action) || !ShouldResetCharges(action))
+                continue;
+
+            ResetCharges(uid, dirty: true);
+        }
+    }
+
     private void OnActionMapInit(EntityUid uid, BaseActionComponent component, MapInitEvent args)
     {
+        component.OriginalIconColor = component.IconColor;
+
         if (component.Charges == null)
             return;
 
@@ -326,14 +360,18 @@ public abstract class SharedActionsSystem : EntitySystem
         Dirty(actionId.Value, action);
     }
 
-    public void ResetCharges(EntityUid? actionId)
+    public void ResetCharges(EntityUid? actionId, bool update = false, bool dirty = false)
     {
         if (!TryGetActionData(actionId, out var action))
             return;
 
         action.Charges = action.MaxCharges;
-        UpdateAction(actionId, action);
-        Dirty(actionId.Value, action);
+
+        if (update)
+            UpdateAction(actionId, action);
+
+        if (dirty)
+            Dirty(actionId.Value, action);
     }
 
     private void OnActionsGetState(EntityUid uid, ActionsComponent component, ref ComponentGetState args)
@@ -386,13 +424,12 @@ public abstract class SharedActionsSystem : EntitySystem
             return;
 
         var curTime = GameTiming.CurTime;
-        // TODO: Check for charge recovery timer
-        if (action.Cooldown.HasValue && action.Cooldown.Value.End > curTime)
+        if (IsCooldownActive(action, curTime))
             return;
 
         // TODO: Replace with individual charge recovery when we have the visuals to aid it
         if (action is { Charges: < 1, RenewCharges: true })
-            ResetCharges(actionEnt);
+            ResetCharges(actionEnt, true, true);
 
         BaseActionEvent? performEvent = null;
 
@@ -1072,4 +1109,19 @@ public abstract class SharedActionsSystem : EntitySystem
         action.EntityIcon = icon;
         Dirty(uid, action);
     }
+
+    /// <summary>
+    ///     Checks if the action has a cooldown and if it's still active
+    /// </summary>
+    protected bool IsCooldownActive(BaseActionComponent action, TimeSpan? curTime = null)
+    {
+        curTime ??= GameTiming.CurTime;
+        // TODO: Check for charge recovery timer
+        return action.Cooldown.HasValue && action.Cooldown.Value.End > curTime;
+    }
+
+    protected bool ShouldResetCharges(BaseActionComponent action)
+    {
+        return action is { Charges: < 1, RenewCharges: true };
+    }
 }