Adds real-time charge & disabled action information to Actions (#31821)
This commit is contained in:
parent
52f6c66fd2
commit
aaa4ab9351
|
|
@ -52,6 +52,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)
|
||||
|
|
@ -96,6 +119,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;
|
||||
|
|
@ -126,6 +151,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue