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)
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;
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;
/// </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>
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;
Icon = component.Icon;
IconOn = component.IconOn;
IconColor = component.IconColor;
+ OriginalIconColor = component.OriginalIconColor;
+ DisabledIconColor = component.DisabledIconColor;
Keywords = component.Keywords;
Enabled = component.Enabled;
Toggled = component.Toggled;
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;
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)
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;
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 };
+ }
}