From 24e061bd4e77985b1496a84e35ebfd8305930765 Mon Sep 17 00:00:00 2001 From: Jessica M Date: Thu, 9 Oct 2025 14:14:12 -0700 Subject: [PATCH] Migrate revenant and PAI shops to use ActionGrant instead of hardcoding them (#40475) * add intrinsic store, replace revenant store with it. * migrate PAI and also move to shared where possible * fix typos and clean up... intrinisic * oops, hopefully fixes test * Move to StoreSystem and ActionGrant * documentation and remove thing * review --------- Co-authored-by: Jessica M Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Content.Client/PAI/PAISystem.cs | 8 ---- Content.Server/PAI/PAISystem.cs | 17 +-------- .../Revenant/EntitySystems/RevenantSystem.cs | 19 +--------- Content.Server/Store/Systems/StoreSystem.cs | 16 +++++--- Content.Shared/PAI/PAIComponent.cs | 12 +----- Content.Shared/PAI/SharedPAISystem.cs | 38 ------------------- .../Revenant/Components/RevenantComponent.cs | 2 - Content.Shared/Revenant/SharedRevenant.cs | 4 -- .../Store/Events/IntrinsicStoreActionEvent.cs | 11 ++++++ Resources/Prototypes/Actions/revenant.yml | 7 +--- Resources/Prototypes/Actions/types.yml | 13 ++++++- .../Entities/Mobs/NPCs/revenant.yml | 3 ++ .../Prototypes/Entities/Objects/Fun/pai.yml | 10 ++--- 13 files changed, 46 insertions(+), 114 deletions(-) delete mode 100644 Content.Client/PAI/PAISystem.cs delete mode 100644 Content.Shared/PAI/SharedPAISystem.cs create mode 100644 Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs diff --git a/Content.Client/PAI/PAISystem.cs b/Content.Client/PAI/PAISystem.cs deleted file mode 100644 index a28cf6a077..0000000000 --- a/Content.Client/PAI/PAISystem.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Content.Shared.PAI; - -namespace Content.Client.PAI -{ - public sealed class PAISystem : SharedPAISystem - { - } -} diff --git a/Content.Server/PAI/PAISystem.cs b/Content.Server/PAI/PAISystem.cs index 01cee8865c..86e2c7853d 100644 --- a/Content.Server/PAI/PAISystem.cs +++ b/Content.Server/PAI/PAISystem.cs @@ -7,22 +7,18 @@ using Content.Shared.Interaction.Events; using Content.Shared.Mind.Components; using Content.Shared.PAI; using Content.Shared.Popups; -using Content.Shared.Store; -using Content.Shared.Store.Components; using Content.Shared.Instruments; using Robust.Shared.Random; -using Robust.Shared.Prototypes; using System.Text; namespace Content.Server.PAI; -public sealed class PAISystem : SharedPAISystem +public sealed class PAISystem : EntitySystem { [Dependency] private readonly InstrumentSystem _instrumentSystem = default!; [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly StoreSystem _store = default!; [Dependency] private readonly ToggleableGhostRoleSystem _toggleableGhostRole = default!; /// @@ -38,8 +34,6 @@ public sealed class PAISystem : SharedPAISystem SubscribeLocalEvent(OnMindAdded); SubscribeLocalEvent(OnMindRemoved); SubscribeLocalEvent(OnMicrowaved); - - SubscribeLocalEvent(OnShop); } private void OnUseInHand(EntityUid uid, PAIComponent component, UseInHandEvent args) @@ -106,15 +100,6 @@ public sealed class PAISystem : SharedPAISystem var val = Loc.GetString("pai-system-pai-name-raw", ("name", name.ToString())); _metaData.SetEntityName(uid, val); } - - private void OnShop(Entity ent, ref PAIShopActionEvent args) - { - if (!TryComp(ent, out var store)) - return; - - _store.ToggleUi(args.Performer, ent, store); - } - public void PAITurningOff(EntityUid uid) { // Close the instrument interface if it was open diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs index bdf00184c8..71c7aa532f 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs @@ -1,7 +1,6 @@ using System.Numerics; using Content.Server.Actions; using Content.Server.GameTicking; -using Content.Server.Store.Components; using Content.Server.Mind; // Imp using Content.Server.Revenant.Components; // Imp using Content.Server.Store.Systems; @@ -52,19 +51,13 @@ public sealed partial class RevenantSystem : EntitySystem [Dependency] private readonly MetaDataSystem _meta = default!; // Imp [Dependency] private readonly TurfSystem _turf = default!; - private static readonly EntProtoId RevenantShopId = "ActionRevenantShop"; - - [ValidatePrototypeId] // Imp - private const string RevenantHauntId = "ActionRevenantHaunt"; // Imp - + private readonly EntProtoId _revenantHaunt = "ActionRevenantHaunt"; // Imp public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnShop); SubscribeLocalEvent(OnDamage); SubscribeLocalEvent(OnExamine); SubscribeLocalEvent(OnStatusAdded); @@ -104,8 +97,7 @@ public sealed partial class RevenantSystem : EntitySystem private void OnMapInit(EntityUid uid, RevenantComponent component, MapInitEvent args) { - _action.AddAction(uid, ref component.ShopAction, RevenantShopId); // Imp - _action.AddAction(uid, ref component.HauntAction, RevenantHauntId); // Imp + _action.AddAction(uid, ref component.HauntAction, _revenantHaunt); // Imp } private void OnStatusAdded(EntityUid uid, RevenantComponent component, StatusEffectAddedEvent args) @@ -199,13 +191,6 @@ public sealed partial class RevenantSystem : EntitySystem return true; } - private void OnShop(EntityUid uid, RevenantComponent component, RevenantShopActionEvent args) - { - if (!TryComp(uid, out var store)) - return; - _store.ToggleUi(uid, uid, store); - } - public void MakeVisible(bool visible) { var query = EntityQueryEnumerator(); diff --git a/Content.Server/Store/Systems/StoreSystem.cs b/Content.Server/Store/Systems/StoreSystem.cs index e74a83f78c..615071188c 100644 --- a/Content.Server/Store/Systems/StoreSystem.cs +++ b/Content.Server/Store/Systems/StoreSystem.cs @@ -1,17 +1,16 @@ +using System.Linq; using Content.Server.Store.Components; -using Content.Shared.UserInterface; using Content.Shared.FixedPoint; using Content.Shared.Implants.Components; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.Stacks; using Content.Shared.Store.Components; -using JetBrains.Annotations; +using Content.Shared.Store.Events; +using Content.Shared.UserInterface; using Robust.Shared.Prototypes; -using Robust.Shared.Utility; -using System.Linq; using Robust.Shared.Timing; -using Content.Shared.Mind; +using Robust.Shared.Utility; namespace Content.Server.Store.Systems; @@ -37,6 +36,7 @@ public sealed partial class StoreSystem : EntitySystem SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnImplantActivate); + SubscribeLocalEvent(OnIntrinsicStoreAction); InitializeUi(); InitializeCommand(); @@ -187,6 +187,12 @@ public sealed partial class StoreSystem : EntitySystem UpdateUserInterface(null, uid, store); return true; } + + private void OnIntrinsicStoreAction(Entity ent, ref IntrinsicStoreActionEvent args) + { + ToggleUi(args.Performer, ent.Owner, ent.Comp); + } + } public sealed class CurrencyInsertAttemptEvent : CancellableEntityEventArgs diff --git a/Content.Shared/PAI/PAIComponent.cs b/Content.Shared/PAI/PAIComponent.cs index fb9d7150e3..541172ffe0 100644 --- a/Content.Shared/PAI/PAIComponent.cs +++ b/Content.Shared/PAI/PAIComponent.cs @@ -1,8 +1,4 @@ -using Content.Shared.FixedPoint; -using Content.Shared.Store; using Robust.Shared.GameStates; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Shared.PAI; @@ -16,7 +12,7 @@ namespace Content.Shared.PAI; /// and there's not always enough players and ghost roles to justify it. /// All logic in PAISystem. /// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[RegisterComponent, NetworkedComponent] public sealed partial class PAIComponent : Component { /// @@ -26,12 +22,6 @@ public sealed partial class PAIComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public EntityUid? LastUser; - [DataField] - public EntProtoId ShopActionId = "ActionPAIOpenShop"; - - [DataField, AutoNetworkedField] - public EntityUid? ShopAction; - /// /// When microwaved there is this chance to brick the pai, kicking out its player and preventing it from being used again. /// diff --git a/Content.Shared/PAI/SharedPAISystem.cs b/Content.Shared/PAI/SharedPAISystem.cs deleted file mode 100644 index 00d3e23cef..0000000000 --- a/Content.Shared/PAI/SharedPAISystem.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Content.Shared.Actions; - -namespace Content.Shared.PAI; - -/// -/// pAIs, or Personal AIs, are essentially portable ghost role generators. -/// In their current implementation, they create a ghost role anyone can access, -/// and that a player can also "wipe" (reset/kick out player). -/// Theoretically speaking pAIs are supposed to use a dedicated "offer and select" system, -/// with the player holding the pAI being able to choose one of the ghosts in the round. -/// This seems too complicated for an initial implementation, though, -/// and there's not always enough players and ghost roles to justify it. -/// -public abstract class SharedPAISystem : EntitySystem -{ - [Dependency] private readonly SharedActionsSystem _actions = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMapInit); - SubscribeLocalEvent(OnShutdown); - } - - private void OnMapInit(Entity ent, ref MapInitEvent args) - { - _actions.AddAction(ent, ent.Comp.ShopActionId); - } - - private void OnShutdown(Entity ent, ref ComponentShutdown args) - { - _actions.RemoveAction(ent.Owner, ent.Comp.ShopAction); - } -} -public sealed partial class PAIShopActionEvent : InstantActionEvent -{ -} diff --git a/Content.Shared/Revenant/Components/RevenantComponent.cs b/Content.Shared/Revenant/Components/RevenantComponent.cs index 9d3135ae8e..cbe7ca91cd 100644 --- a/Content.Shared/Revenant/Components/RevenantComponent.cs +++ b/Content.Shared/Revenant/Components/RevenantComponent.cs @@ -299,7 +299,5 @@ public sealed partial class RevenantComponent : Component [DataField("harvestingState")] public string HarvestingState = "harvesting"; #endregion - - [DataField] public EntityUid? ShopAction; // Imp [DataField] public EntityUid? HauntAction; // Imp } diff --git a/Content.Shared/Revenant/SharedRevenant.cs b/Content.Shared/Revenant/SharedRevenant.cs index 9f83df32b8..0179ce64cc 100644 --- a/Content.Shared/Revenant/SharedRevenant.cs +++ b/Content.Shared/Revenant/SharedRevenant.cs @@ -42,10 +42,6 @@ public sealed class HarvestDoAfterCancelled : EntityEventArgs { } -public sealed partial class RevenantShopActionEvent : InstantActionEvent -{ -} - public sealed partial class RevenantHauntActionEvent : InstantActionEvent // Imp { } diff --git a/Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs b/Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs new file mode 100644 index 0000000000..dea2c25e6e --- /dev/null +++ b/Content.Shared/Store/Events/IntrinsicStoreActionEvent.cs @@ -0,0 +1,11 @@ +using Content.Shared.Actions; + +namespace Content.Shared.Store.Events; + +/// +/// Opens a store specified by +/// Used for entities with a store built into themselves like Revenant or PAI +/// +public sealed partial class IntrinsicStoreActionEvent : InstantActionEvent +{ +} diff --git a/Resources/Prototypes/Actions/revenant.yml b/Resources/Prototypes/Actions/revenant.yml index cc65793944..b8cb648e06 100644 --- a/Resources/Prototypes/Actions/revenant.yml +++ b/Resources/Prototypes/Actions/revenant.yml @@ -1,13 +1,8 @@ - type: entity - parent: BaseAction + parent: ActionIntrinsicStore id: ActionRevenantShop name: Shop description: Opens the ability shop. - components: - - type: Action - icon: Interface/Actions/shop.png - - type: InstantAction - event: !type:RevenantShopActionEvent - type: entity parent: BaseAction diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index aceea74250..1097d6982f 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -454,4 +454,15 @@ icon: { sprite: Actions/Implants/implants.rsi, state: chameleon } itemIconStyle: BigAction - type: InstantAction - event: !type:ChameleonControllerOpenMenuEvent \ No newline at end of file + event: !type:ChameleonControllerOpenMenuEvent + +- type: entity + parent: BaseMentalAction + id: ActionIntrinsicStore + name: Store + description: Opens the store + components: + - type: Action + icon: Interface/Actions/shop.png + - type: InstantAction + event: !type:IntrinsicStoreActionEvent diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index ce95f2045f..e118372693 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -73,6 +73,9 @@ type: StoreBoundUserInterface - type: Visibility layer: 2 #ghost vis layer + - type: ActionGrant + actions: + - ActionRevenantShop - type: Store categories: - RevenantAbilities diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 6aec812b77..2ba5acfbf1 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -58,6 +58,9 @@ - Common - type: DoAfter - type: Actions + - type: ActionGrant + actions: + - ActionPAIOpenShop - type: Store categories: - PAIAbilities @@ -188,15 +191,10 @@ node: potatoai - type: entity - parent: BaseMentalAction + parent: ActionIntrinsicStore id: ActionPAIOpenShop name: Software Catalog description: Install new software to assist your owner. - components: - - type: Action - icon: Interface/Actions/shop.png - - type: InstantAction - event: !type:PAIShopActionEvent - type: entity parent: BaseMentalAction