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 (instantAction.Event != null)
|
||||
{
|
||||
instantAction.Event.Performer = user;
|
||||
instantAction.Event.Action = actionId;
|
||||
}
|
||||
|
||||
PerformAction(user, actions, actionId, instantAction, instantAction.Event, GameTiming.CurTime);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -219,8 +219,6 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
|
||||
if (action.Event != null)
|
||||
{
|
||||
action.Event.Target = coords;
|
||||
action.Event.Performer = user;
|
||||
action.Event.Action = actionId;
|
||||
}
|
||||
|
||||
_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)
|
||||
{
|
||||
action.Event.Target = entity;
|
||||
action.Event.Performer = user;
|
||||
action.Event.Action = actionId;
|
||||
}
|
||||
|
||||
_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.Coords = coords;
|
||||
action.Event.Performer = user;
|
||||
action.Event.Action = actionId;
|
||||
}
|
||||
|
||||
_actionsSystem.PerformAction(user, actionComp, actionId, action, action.Event, _timing.CurTime);
|
||||
|
||||
@@ -55,12 +55,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
||||
return;
|
||||
|
||||
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);
|
||||
args.Handled = true;
|
||||
}
|
||||
@@ -94,8 +88,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
||||
var (entActId, entAct) = _random.Pick(entOptions);
|
||||
if (entAct.Event != null)
|
||||
{
|
||||
entAct.Event.Performer = args.User;
|
||||
entAct.Event.Action = entActId;
|
||||
entAct.Event.Target = args.Target.Value;
|
||||
}
|
||||
|
||||
@@ -119,8 +111,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
||||
var (entActId, entAct) = _random.Pick(entWorldOptions);
|
||||
if (entAct.Event != null)
|
||||
{
|
||||
entAct.Event.Performer = args.User;
|
||||
entAct.Event.Action = entActId;
|
||||
entAct.Event.Entity = args.Target;
|
||||
entAct.Event.Coords = args.ClickLocation;
|
||||
}
|
||||
@@ -145,8 +135,6 @@ public sealed class ActionOnInteractSystem : EntitySystem
|
||||
var (actId, act) = _random.Pick(options);
|
||||
if (act.Event != null)
|
||||
{
|
||||
act.Event.Performer = args.User;
|
||||
act.Event.Action = actId;
|
||||
act.Event.Target = args.ClickLocation;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ public sealed class NPCUseActionOnTargetSystem : EntitySystem
|
||||
|
||||
if (action.Event != null)
|
||||
{
|
||||
action.Event.Performer = user;
|
||||
action.Event.Action = user.Comp.ActionEnt.Value;
|
||||
action.Event.Coords = Transform(target).Coordinates;
|
||||
}
|
||||
|
||||
|
||||
@@ -187,5 +187,10 @@ public abstract partial class BaseActionEvent : HandledEntityEventArgs
|
||||
/// <summary>
|
||||
/// The action the event belongs to.
|
||||
/// </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.Whitelist;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -45,6 +44,8 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
SubscribeLocalEvent<WorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
||||
SubscribeLocalEvent<EntityWorldTargetActionComponent, ComponentShutdown>(OnActionShutdown);
|
||||
|
||||
SubscribeLocalEvent<ActionsComponent, ActionComponentChangeEvent>(OnActionCompChange);
|
||||
SubscribeLocalEvent<ActionsComponent, RelayedActionComponentChangeEvent>(OnRelayActionCompChange);
|
||||
SubscribeLocalEvent<ActionsComponent, DidEquipEvent>(OnDidEquip);
|
||||
SubscribeLocalEvent<ActionsComponent, DidEquipHandEvent>(OnHandEquipped);
|
||||
SubscribeLocalEvent<ActionsComponent, DidUnequipEvent>(OnDidUnequip);
|
||||
@@ -490,12 +491,6 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
break;
|
||||
}
|
||||
|
||||
if (performEvent != null)
|
||||
{
|
||||
performEvent.Performer = user;
|
||||
performEvent.Action = actionEnt;
|
||||
}
|
||||
|
||||
// All checks passed. Perform the action!
|
||||
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).
|
||||
actionEvent.Handled = false;
|
||||
var target = performer;
|
||||
actionEvent.Performer = performer;
|
||||
actionEvent.Action = (actionId, action);
|
||||
|
||||
if (!action.RaiseOnUser && action.Container != null && !HasComp<MindComponent>(action.Container))
|
||||
target = action.Container.Value;
|
||||
@@ -653,10 +650,14 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
return; // no interaction occurred.
|
||||
|
||||
// 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)
|
||||
{
|
||||
@@ -673,10 +674,11 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
action.Cooldown = (curTime, curTime + action.UseDelay.Value);
|
||||
}
|
||||
|
||||
Dirty(actionId, action);
|
||||
|
||||
if (dirty && component != null)
|
||||
Dirty(performer, component);
|
||||
if (dirty)
|
||||
{
|
||||
Dirty(actionId, action);
|
||||
UpdateAction(actionId, action);
|
||||
}
|
||||
|
||||
var ev = new ActionPerformedEvent(performer);
|
||||
RaiseLocalEvent(actionId, ref ev);
|
||||
@@ -975,6 +977,47 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
|
||||
#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
|
||||
private void OnDidEquip(EntityUid uid, ActionsComponent component, DidEquipEvent args)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user