diff --git a/Content.Shared/Trigger/Components/Effects/SpawnEntityTableOnTriggerComponent.cs b/Content.Shared/Trigger/Components/Effects/SpawnEntityTableOnTriggerComponent.cs new file mode 100644 index 0000000000..41cb785c05 --- /dev/null +++ b/Content.Shared/Trigger/Components/Effects/SpawnEntityTableOnTriggerComponent.cs @@ -0,0 +1,33 @@ +using Content.Shared.EntityTable.EntitySelectors; +using Robust.Shared.GameStates; + +namespace Content.Shared.Trigger.Components.Effects; + +/// +/// Spawns an entity table at this entity when triggered. +/// If TargetUser is true it will be spawned at their location. +/// +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class SpawnEntityTableOnTriggerComponent : BaseXOnTriggerComponent +{ + /// + /// The table to spawn. + /// + [DataField(required: true), AutoNetworkedField] + public EntityTableSelector Table; + + /// + /// Use MapCoordinates for spawning? + /// Set to true if you don't want the new entity parented to the spawner. + /// + [DataField, AutoNetworkedField] + public bool UseMapCoords; + + /// + /// Whether to use predicted spawning. + /// + /// Randomization in EntityTables is not currently predicted! Use with caution. + [DataField, AutoNetworkedField] + public bool Predicted; +} diff --git a/Content.Shared/Trigger/Components/Effects/SpawnOnTriggerComponent.cs b/Content.Shared/Trigger/Components/Effects/SpawnOnTriggerComponent.cs index 782626f479..e1c7dad0b8 100644 --- a/Content.Shared/Trigger/Components/Effects/SpawnOnTriggerComponent.cs +++ b/Content.Shared/Trigger/Components/Effects/SpawnOnTriggerComponent.cs @@ -7,6 +7,7 @@ namespace Content.Shared.Trigger.Components.Effects; /// Spawns a protoype when triggered. /// If TargetUser is true it will be spawned at their location. /// +/// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class SpawnOnTriggerComponent : BaseXOnTriggerComponent { diff --git a/Content.Shared/Trigger/Systems/TriggerSystem.Spawn.cs b/Content.Shared/Trigger/Systems/TriggerSystem.Spawn.cs index edcdd03894..83457361fd 100644 --- a/Content.Shared/Trigger/Systems/TriggerSystem.Spawn.cs +++ b/Content.Shared/Trigger/Systems/TriggerSystem.Spawn.cs @@ -1,16 +1,17 @@ using Content.Shared.Trigger.Components.Effects; using Content.Shared.Trigger.Components.Triggers; +using Robust.Shared.Prototypes; namespace Content.Shared.Trigger.Systems; public sealed partial class TriggerSystem { - private void InitializeSpawn() { SubscribeLocalEvent(OnSpawnInit); SubscribeLocalEvent(HandleSpawnOnTrigger); + SubscribeLocalEvent(HandleSpawnTableOnTrigger); SubscribeLocalEvent(HandleDeleteOnTrigger); } @@ -30,27 +31,55 @@ public sealed partial class TriggerSystem return; var xform = Transform(target.Value); + SpawnTriggerHelper((target.Value, xform), ent.Comp.Proto, ent.Comp.UseMapCoords, ent.Comp.Predicted); + } - if (ent.Comp.UseMapCoords) + private void HandleSpawnTableOnTrigger(Entity ent, ref TriggerEvent args) + { + if (args.Key != null && !ent.Comp.KeysIn.Contains(args.Key)) + return; + + var target = ent.Comp.TargetUser ? args.User : ent.Owner; + + if (target == null) + return; + + var xform = Transform(target.Value); + var spawns = _entityTable.GetSpawns(ent.Comp.Table); + foreach (var proto in spawns) { - var mapCoords = _transform.GetMapCoordinates(target.Value, xform); - if (ent.Comp.Predicted) - EntityManager.PredictedSpawn(ent.Comp.Proto, mapCoords); - else if (_net.IsServer) - Spawn(ent.Comp.Proto, mapCoords); - + SpawnTriggerHelper((target.Value, xform), proto, ent.Comp.UseMapCoords, ent.Comp.Predicted); } + } + + /// + /// Helper function to combine HandleSpawnOnTrigger and HandleSpawnTableOnTrigger. + /// + /// The entity to spawn attached to or at the feet of. + /// The entity to spawn. + /// If true, spawn at target's MapCoordinates. If false, spawn attached to target. + /// Whether to use predicted spawning. + private void SpawnTriggerHelper(Entity target, EntProtoId proto, bool useMapCoords, bool predicted) + { + if (useMapCoords) + { + var mapCoords = _transform.GetMapCoordinates(target); + if (predicted) + EntityManager.PredictedSpawn(proto, mapCoords); + else if (_net.IsServer) + Spawn(proto, mapCoords); + } + else { - var coords = xform.Coordinates; + var coords = target.Comp.Coordinates; if (!coords.IsValid(EntityManager)) return; - if (ent.Comp.Predicted) - PredictedSpawnAttachedTo(ent.Comp.Proto, coords); + if (predicted) + PredictedSpawnAttachedTo(proto, coords); else if (_net.IsServer) - SpawnAttachedTo(ent.Comp.Proto, coords); - + SpawnAttachedTo(proto, coords); } } diff --git a/Content.Shared/Trigger/Systems/TriggerSystem.cs b/Content.Shared/Trigger/Systems/TriggerSystem.cs index 6a749b87ab..ca60901a79 100644 --- a/Content.Shared/Trigger/Systems/TriggerSystem.cs +++ b/Content.Shared/Trigger/Systems/TriggerSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Administration.Logs; using Content.Shared.Database; using Content.Shared.DeviceLinking; +using Content.Shared.EntityTable; using Content.Shared.Item.ItemToggle; using Content.Shared.Popups; using Content.Shared.Timing; @@ -38,6 +39,7 @@ public sealed partial class TriggerSystem : EntitySystem [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; [Dependency] private readonly ItemToggleSystem _itemToggle = default!; [Dependency] private readonly SharedDeviceLinkSystem _deviceLink = default!; + [Dependency] private readonly EntityTableSystem _entityTable = default!; public const string DefaultTriggerKey = "trigger";