Action stuff (#31305)
* Action stuff - Cleanup some event stuff - Avoid dirtying entity unnecessarily - Add ActionGrant as an easy way to apply / remove actions via compregistry. * Fix merge
This commit is contained in:
@@ -259,12 +259,6 @@ namespace Content.Client.Actions
|
|||||||
|
|
||||||
if (action.ClientExclusive)
|
if (action.ClientExclusive)
|
||||||
{
|
{
|
||||||
if (instantAction.Event != null)
|
|
||||||
{
|
|
||||||
instantAction.Event.Performer = user;
|
|
||||||
instantAction.Event.Action = actionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
PerformAction(user, actions, actionId, instantAction, instantAction.Event, GameTiming.CurTime);
|
PerformAction(user, actions, actionId, instantAction, instantAction.Event, GameTiming.CurTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -219,8 +219,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
|
|||||||
if (action.Event != null)
|
if (action.Event != null)
|
||||||
{
|
{
|
||||||
action.Event.Target = coords;
|
action.Event.Target = coords;
|
||||||
action.Event.Performer = user;
|
|
||||||
action.Event.Action = actionId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
||||||
@@ -254,8 +252,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
|
|||||||
if (action.Event != null)
|
if (action.Event != null)
|
||||||
{
|
{
|
||||||
action.Event.Target = entity;
|
action.Event.Target = entity;
|
||||||
action.Event.Performer = user;
|
|
||||||
action.Event.Action = actionId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
||||||
@@ -295,8 +291,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
|
|||||||
{
|
{
|
||||||
action.Event.Entity = entity;
|
action.Event.Entity = entity;
|
||||||
action.Event.Coords = coords;
|
action.Event.Coords = coords;
|
||||||
action.Event.Performer = user;
|
|
||||||
action.Event.Action = actionId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
||||||
|
|||||||
@@ -55,12 +55,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var (actId, act) = _random.Pick(options);
|
var (actId, act) = _random.Pick(options);
|
||||||
if (act.Event != null)
|
|
||||||
{
|
|
||||||
act.Event.Performer = args.User;
|
|
||||||
act.Event.Action = actId;
|
|
||||||
}
|
|
||||||
|
|
||||||
_actions.PerformAction(args.User, null, actId, act, act.Event, _timing.CurTime, false);
|
_actions.PerformAction(args.User, null, actId, act, act.Event, _timing.CurTime, false);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
@@ -94,8 +88,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
|||||||
var (entActId, entAct) = _random.Pick(entOptions);
|
var (entActId, entAct) = _random.Pick(entOptions);
|
||||||
if (entAct.Event != null)
|
if (entAct.Event != null)
|
||||||
{
|
{
|
||||||
entAct.Event.Performer = args.User;
|
|
||||||
entAct.Event.Action = entActId;
|
|
||||||
entAct.Event.Target = args.Target.Value;
|
entAct.Event.Target = args.Target.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +111,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
|||||||
var (entActId, entAct) = _random.Pick(entWorldOptions);
|
var (entActId, entAct) = _random.Pick(entWorldOptions);
|
||||||
if (entAct.Event != null)
|
if (entAct.Event != null)
|
||||||
{
|
{
|
||||||
entAct.Event.Performer = args.User;
|
|
||||||
entAct.Event.Action = entActId;
|
|
||||||
entAct.Event.Entity = args.Target;
|
entAct.Event.Entity = args.Target;
|
||||||
entAct.Event.Coords = args.ClickLocation;
|
entAct.Event.Coords = args.ClickLocation;
|
||||||
}
|
}
|
||||||
@@ -145,8 +135,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
|||||||
var (actId, act) = _random.Pick(options);
|
var (actId, act) = _random.Pick(options);
|
||||||
if (act.Event != null)
|
if (act.Event != null)
|
||||||
{
|
{
|
||||||
act.Event.Performer = args.User;
|
|
||||||
act.Event.Action = actId;
|
|
||||||
act.Event.Target = args.ClickLocation;
|
act.Event.Target = args.ClickLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ public sealed class NPCUseActionOnTargetSystem : EntitySystem
|
|||||||
|
|
||||||
if (action.Event != null)
|
if (action.Event != null)
|
||||||
{
|
{
|
||||||
action.Event.Performer = user;
|
|
||||||
action.Event.Action = user.Comp.ActionEnt.Value;
|
|
||||||
action.Event.Coords = Transform(target).Coordinates;
|
action.Event.Coords = Transform(target).Coordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,5 +187,10 @@ public abstract partial class BaseActionEvent : HandledEntityEventArgs
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The action the event belongs to.
|
/// The action the event belongs to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EntityUid Action;
|
public Entity<BaseActionComponent> Action;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should we toggle the action entity?
|
||||||
|
/// </summary>
|
||||||
|
public bool Toggle;
|
||||||
}
|
}
|
||||||
|
|||||||
17
Content.Shared/Actions/ActionGrantComponent.cs
Normal file
17
Content.Shared/Actions/ActionGrantComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Actions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grants actions on MapInit and removes them on shutdown
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(ActionGrantSystem))]
|
||||||
|
public sealed partial class ActionGrantComponent : Component
|
||||||
|
{
|
||||||
|
[DataField(required: true), AutoNetworkedField, AlwaysPushInheritance]
|
||||||
|
public List<EntProtoId> Actions = new();
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public List<EntityUid> ActionEntities = new();
|
||||||
|
}
|
||||||
48
Content.Shared/Actions/ActionGrantSystem.cs
Normal file
48
Content.Shared/Actions/ActionGrantSystem.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
namespace Content.Shared.Actions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="ActionGrantComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ActionGrantSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<ActionGrantComponent, MapInitEvent>(OnMapInit);
|
||||||
|
SubscribeLocalEvent<ActionGrantComponent, ComponentShutdown>(OnShutdown);
|
||||||
|
SubscribeLocalEvent<ItemActionGrantComponent, GetItemActionsEvent>(OnItemGet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnItemGet(Entity<ItemActionGrantComponent> ent, ref GetItemActionsEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp(ent.Owner, out ActionGrantComponent? grant))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var action in grant.ActionEntities)
|
||||||
|
{
|
||||||
|
args.AddAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMapInit(Entity<ActionGrantComponent> ent, ref MapInitEvent args)
|
||||||
|
{
|
||||||
|
foreach (var action in ent.Comp.Actions)
|
||||||
|
{
|
||||||
|
EntityUid? actionEnt = null;
|
||||||
|
_actions.AddAction(ent.Owner, ref actionEnt, action);
|
||||||
|
|
||||||
|
if (actionEnt != null)
|
||||||
|
ent.Comp.ActionEntities.Add(actionEnt.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShutdown(Entity<ActionGrantComponent> ent, ref ComponentShutdown args)
|
||||||
|
{
|
||||||
|
foreach (var actionEnt in ent.Comp.ActionEntities)
|
||||||
|
{
|
||||||
|
_actions.RemoveAction(ent.Owner, actionEnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Content.Shared/Actions/Events/ActionComponentChangeEvent.cs
Normal file
27
Content.Shared/Actions/Events/ActionComponentChangeEvent.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Actions.Events;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds / removes the component upon action.
|
||||||
|
/// </summary>
|
||||||
|
[Virtual]
|
||||||
|
public partial class ActionComponentChangeEvent : InstantActionEvent
|
||||||
|
{
|
||||||
|
[DataField(required: true)]
|
||||||
|
public ComponentRegistry Components = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar to <see cref="ActionComponentChangeEvent"/> except raises an event to attempt to relay it.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class RelayedActionComponentChangeEvent : ActionComponentChangeEvent
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct AttemptRelayActionComponentChangeEvent
|
||||||
|
{
|
||||||
|
public EntityUid? Target;
|
||||||
|
}
|
||||||
14
Content.Shared/Actions/ItemActionGrantComponent.cs
Normal file
14
Content.Shared/Actions/ItemActionGrantComponent.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared.Actions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Works in tandem with <see cref="ActionGrantComponent"/> by granting those actions to the equipper entity.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(ActionGrantSystem))]
|
||||||
|
public sealed partial class ItemActionGrantComponent : Component
|
||||||
|
{
|
||||||
|
[DataField(required: true), AutoNetworkedField, AlwaysPushInheritance]
|
||||||
|
public List<EntProtoId> Actions = new();
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ using Content.Shared.Mind;
|
|||||||
using Content.Shared.Rejuvenate;
|
using Content.Shared.Rejuvenate;
|
||||||
using Content.Shared.Whitelist;
|
using Content.Shared.Whitelist;
|
||||||
using Robust.Shared.Audio.Systems;
|
using Robust.Shared.Audio.Systems;
|
||||||
using Robust.Shared.Containers;
|
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -45,6 +44,8 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<WorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
SubscribeLocalEvent<WorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
||||||
SubscribeLocalEvent<EntityWorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
SubscribeLocalEvent<EntityWorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ActionsComponent, ActionComponentChangeEvent>(OnActionCompChange);
|
||||||
|
SubscribeLocalEvent<ActionsComponent, RelayedActionComponentChangeEvent>(OnRelayActionCompChange);
|
||||||
SubscribeLocalEvent<ActionsComponent, DidEquipEvent>(OnDidEquip);
|
SubscribeLocalEvent<ActionsComponent, DidEquipEvent>(OnDidEquip);
|
||||||
SubscribeLocalEvent<ActionsComponent, DidEquipHandEvent>(OnHandEquipped);
|
SubscribeLocalEvent<ActionsComponent, DidEquipHandEvent>(OnHandEquipped);
|
||||||
SubscribeLocalEvent<ActionsComponent, DidUnequipEvent>(OnDidUnequip);
|
SubscribeLocalEvent<ActionsComponent, DidUnequipEvent>(OnDidUnequip);
|
||||||
@@ -490,12 +491,6 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (performEvent != null)
|
|
||||||
{
|
|
||||||
performEvent.Performer = user;
|
|
||||||
performEvent.Action = actionEnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All checks passed. Perform the action!
|
// All checks passed. Perform the action!
|
||||||
PerformAction(user, component, actionEnt, action, performEvent, curTime);
|
PerformAction(user, component, actionEnt, action, performEvent, curTime);
|
||||||
}
|
}
|
||||||
@@ -641,6 +636,8 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
// This here is required because of client-side prediction (RaisePredictiveEvent results in event re-use).
|
// This here is required because of client-side prediction (RaisePredictiveEvent results in event re-use).
|
||||||
actionEvent.Handled = false;
|
actionEvent.Handled = false;
|
||||||
var target = performer;
|
var target = performer;
|
||||||
|
actionEvent.Performer = performer;
|
||||||
|
actionEvent.Action = (actionId, action);
|
||||||
|
|
||||||
if (!action.RaiseOnUser && action.Container != null && !HasComp<MindComponent>(action.Container))
|
if (!action.RaiseOnUser && action.Container != null && !HasComp<MindComponent>(action.Container))
|
||||||
target = action.Container.Value;
|
target = action.Container.Value;
|
||||||
@@ -653,10 +650,14 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
return; // no interaction occurred.
|
return; // no interaction occurred.
|
||||||
|
|
||||||
// play sound, reduce charges, start cooldown, and mark as dirty (if required).
|
// play sound, reduce charges, start cooldown, and mark as dirty (if required).
|
||||||
|
if (actionEvent?.Toggle == true)
|
||||||
|
{
|
||||||
|
action.Toggled = !action.Toggled;
|
||||||
|
}
|
||||||
|
|
||||||
_audio.PlayPredicted(action.Sound, performer,predicted ? performer : null);
|
_audio.PlayPredicted(action.Sound, performer, predicted ? performer : null);
|
||||||
|
|
||||||
var dirty = toggledBefore == action.Toggled;
|
var dirty = toggledBefore != action.Toggled;
|
||||||
|
|
||||||
if (action.Charges != null)
|
if (action.Charges != null)
|
||||||
{
|
{
|
||||||
@@ -673,10 +674,11 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
action.Cooldown = (curTime, curTime + action.UseDelay.Value);
|
action.Cooldown = (curTime, curTime + action.UseDelay.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
Dirty(actionId, action);
|
Dirty(actionId, action);
|
||||||
|
UpdateAction(actionId, action);
|
||||||
if (dirty && component != null)
|
}
|
||||||
Dirty(performer, component);
|
|
||||||
|
|
||||||
var ev = new ActionPerformedEvent(performer);
|
var ev = new ActionPerformedEvent(performer);
|
||||||
RaiseLocalEvent(actionId, ref ev);
|
RaiseLocalEvent(actionId, ref ev);
|
||||||
@@ -975,6 +977,47 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private void OnRelayActionCompChange(Entity<ActionsComponent> ent, ref RelayedActionComponentChangeEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ev = new AttemptRelayActionComponentChangeEvent();
|
||||||
|
RaiseLocalEvent(ent.Owner, ref ev);
|
||||||
|
var target = ev.Target ?? ent.Owner;
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
args.Toggle = true;
|
||||||
|
|
||||||
|
if (!args.Action.Comp.Toggled)
|
||||||
|
{
|
||||||
|
EntityManager.AddComponents(target, args.Components);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EntityManager.RemoveComponents(target, args.Components);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnActionCompChange(Entity<ActionsComponent> ent, ref ActionComponentChangeEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
args.Toggle = true;
|
||||||
|
var target = ent.Owner;
|
||||||
|
|
||||||
|
if (!args.Action.Comp.Toggled)
|
||||||
|
{
|
||||||
|
EntityManager.AddComponents(target, args.Components);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EntityManager.RemoveComponents(target, args.Components);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region EquipHandlers
|
#region EquipHandlers
|
||||||
private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args)
|
private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user