+++ /dev/null
-using System.Threading;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
-
-namespace Content.Server.Engineering.Components
-{
- [RegisterComponent]
- public sealed partial class DisassembleOnAltVerbComponent : Component
- {
- [DataField("prototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
- public string? Prototype { get; private set; }
-
- [DataField("doAfter")]
- public float DoAfterTime = 0;
- }
-}
+++ /dev/null
-using Content.Server.Engineering.Components;
-using Content.Shared.DoAfter;
-using Content.Shared.Hands.EntitySystems;
-using Content.Shared.Verbs;
-using JetBrains.Annotations;
-
-namespace Content.Server.Engineering.EntitySystems
-{
- [UsedImplicitly]
- public sealed class DisassembleOnAltVerbSystem : EntitySystem
- {
- [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
-
- public override void Initialize()
- {
- base.Initialize();
-
- SubscribeLocalEvent<DisassembleOnAltVerbComponent, GetVerbsEvent<AlternativeVerb>>(AddDisassembleVerb);
- }
- private void AddDisassembleVerb(EntityUid uid, DisassembleOnAltVerbComponent component, GetVerbsEvent<AlternativeVerb> args)
- {
- if (!args.CanInteract || !args.CanAccess || args.Hands == null)
- return;
-
- AlternativeVerb verb = new()
- {
- Act = () =>
- {
- AttemptDisassemble(uid, args.User, args.Target, component);
- },
- Text = Loc.GetString("disassemble-system-verb-disassemble"),
- Priority = 2
- };
- args.Verbs.Add(verb);
- }
-
- public async void AttemptDisassemble(EntityUid uid, EntityUid user, EntityUid target, DisassembleOnAltVerbComponent? component = null)
- {
- if (!Resolve(uid, ref component))
- return;
- if (string.IsNullOrEmpty(component.Prototype))
- return;
-
- if (component.DoAfterTime > 0 && TryGet<SharedDoAfterSystem>(out var doAfterSystem))
- {
- var doAfterArgs = new DoAfterArgs(EntityManager, user, component.DoAfterTime, new AwaitedDoAfterEvent(), null)
- {
- BreakOnMove = true,
- };
- var result = await doAfterSystem.WaitDoAfter(doAfterArgs);
-
- if (result != DoAfterStatus.Finished)
- return;
- }
-
- if (component.Deleted || Deleted(uid))
- return;
-
- if (!TryComp(uid, out TransformComponent? transformComp))
- return;
-
- var entity = EntityManager.SpawnEntity(component.Prototype, transformComp.Coordinates);
-
- _handsSystem.TryPickup(user, entity);
-
- EntityManager.DeleteEntity(uid);
- }
- }
-}
--- /dev/null
+using Content.Shared.DoAfter;
+using Robust.Shared.GameStates;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Engineering.Components;
+
+/// <summary>
+/// Add a verb to entities that will disassemble them after an optional doafter to a specified prototype.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class DisassembleOnAltVerbComponent : Component
+{
+ /// <summary>
+ /// The prototype that is spawned after disassembly. If null, nothing will spawn.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public EntProtoId? PrototypeToSpawn;
+
+ /// <summary>
+ /// The time it takes to disassemble the entity.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public TimeSpan DisassembleTime = TimeSpan.FromSeconds(0);
+}
+
+[Serializable, NetSerializable]
+public sealed partial class DisassembleDoAfterEvent : SimpleDoAfterEvent;
--- /dev/null
+using Content.Shared.DoAfter;
+using Content.Shared.Engineering.Components;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Verbs;
+using Robust.Shared.Network;
+
+namespace Content.Shared.Engineering.Systems;
+
+public sealed partial class DisassembleOnAltVerbSystem : EntitySystem
+{
+ [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+ [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
+ [Dependency] private readonly INetManager _net = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<DisassembleOnAltVerbComponent, GetVerbsEvent<AlternativeVerb>>(AddDisassembleVerb);
+ SubscribeLocalEvent<DisassembleOnAltVerbComponent, DisassembleDoAfterEvent>(OnDisassembleDoAfter);
+ }
+ private void AddDisassembleVerb(Entity<DisassembleOnAltVerbComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
+ {
+ if (!args.CanInteract || !args.CanAccess || args.Hands == null)
+ return;
+
+ // Doafter setup
+ var doAfterArgs = new DoAfterArgs(EntityManager,
+ args.User,
+ entity.Comp.DisassembleTime,
+ new DisassembleDoAfterEvent(),
+ entity,
+ entity)
+ {
+ BreakOnMove = true,
+ };
+
+ // Actual verb stuff
+ AlternativeVerb verb = new()
+ {
+ Act = () =>
+ {
+ _doAfter.TryStartDoAfter(doAfterArgs);
+ },
+ Text = Loc.GetString("disassemble-system-verb-disassemble"),
+ Priority = 2
+ };
+ args.Verbs.Add(verb);
+ }
+
+ private void OnDisassembleDoAfter(Entity<DisassembleOnAltVerbComponent> entity, ref DisassembleDoAfterEvent args)
+ {
+ if (!_net.IsServer) // This is odd but it works :)
+ return;
+
+ if (TrySpawnNextTo(entity.Comp.PrototypeToSpawn, entity.Owner, out var spawnedEnt))
+ _handsSystem.TryPickup(args.User, spawnedEnt.Value);
+
+ QueueDel(entity.Owner);
+ }
+}
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: DisassembleOnAltVerb
- prototype: InflatableWallStack1
- doAfter: 3
+ prototypeToSpawn: InflatableWallStack1
+ disassembleTime: 3
- type: Airtight
- type: Transform
anchored: true
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: DisassembleOnAltVerb
- prototype: InflatableDoorStack1
- doAfter: 3
+ prototypeToSpawn: InflatableDoorStack1
+ disassembleTime: 3
- type: Occluder
enabled: false