diff --git a/Content.Server/StationEvents/Components/VentCrittersRuleComponent.cs b/Content.Server/StationEvents/Components/VentCrittersRuleComponent.cs index f280468fc34..a575075632e 100644 --- a/Content.Server/StationEvents/Components/VentCrittersRuleComponent.cs +++ b/Content.Server/StationEvents/Components/VentCrittersRuleComponent.cs @@ -1,5 +1,6 @@ using Content.Server.StationEvents.Events; using Content.Shared.Storage; +using Robust.Shared.Map; // DeltaV namespace Content.Server.StationEvents.Components; @@ -14,4 +15,28 @@ public sealed partial class VentCrittersRuleComponent : Component /// [DataField("specialEntries")] public List SpecialEntries = new(); + + /// + /// DeltaV: The location of the vent that got picked. + /// + [ViewVariables] + public EntityCoordinates? Location; + + /// + /// DeltaV: Base minimum number of critters to spawn. + /// + [DataField] + public int Min = 2; + + /// + /// DeltaV: Base maximum number of critters to spawn. + /// + [DataField] + public int Max = 3; + + /// + /// DeltaV: Min and max get multiplied by the player count then divided by this. + /// + [DataField] + public int PlayerRatio = 25; } diff --git a/Content.Server/StationEvents/Events/VentCrittersRule.cs b/Content.Server/StationEvents/Events/VentCrittersRule.cs index aee141f2dba..20143a77591 100644 --- a/Content.Server/StationEvents/Events/VentCrittersRule.cs +++ b/Content.Server/StationEvents/Events/VentCrittersRule.cs @@ -1,13 +1,23 @@ -using Content.Server.StationEvents.Components; +using Content.Server.Antag; using Content.Server.GameTicking.Rules.Components; +using Content.Server.Pinpointer; +using Content.Server.StationEvents.Components; using Content.Shared.GameTicking.Components; using Content.Shared.Station.Components; using Content.Shared.Storage; using Robust.Shared.Map; +using Robust.Shared.Player; using Robust.Shared.Random; namespace Content.Server.StationEvents.Events; +/// +/// DeltaV: Reworked vent critters to spawn a number of mobs at a single telegraphed location. +/// This gives players time to run away and let sec do their job. +/// +/// +/// This entire file is rewritten, ignore upstream changes. +/// public sealed class VentCrittersRule : StationEventSystem { /* @@ -15,45 +25,75 @@ public sealed class VentCrittersRule : StationEventSystem _locations = new(); + + protected override void Added(EntityUid uid, VentCrittersRuleComponent comp, GameRuleComponent gameRule, GameRuleAddedEvent args) + { + PickLocation(comp); + if (comp.Location is not {} coords) { + ForceEndSelf(uid, gameRule); return; } - var locations = EntityQueryEnumerator(); - var validLocations = new List(); - while (locations.MoveNext(out _, out _, out var transform)) + var mapCoords = _transform.ToMapCoordinates(coords); + if (!_navMap.TryGetNearestBeacon(mapCoords, out var beacon, out _)) + return; + + var nearest = beacon?.Comp?.Text!; + Comp(uid).StartAnnouncement = Loc.GetString("station-event-vent-creatures-start-announcement-deltav", ("location", nearest)); + + base.Added(uid, comp, gameRule, args); + } + + protected override void Ended(EntityUid uid, VentCrittersRuleComponent comp, GameRuleComponent gameRule, GameRuleEndedEvent args) + { + base.Ended(uid, comp, gameRule, args); + + if (comp.Location is not {} coords) + return; + + var players = _antag.GetTotalPlayerCount(_player.Sessions); + var min = comp.Min * players / comp.PlayerRatio; + var max = comp.Max * players / comp.PlayerRatio; + var count = Math.Max(RobustRandom.Next(min, max), 1); + for (int i = 0; i < count; i++) { - if (CompOrNull(transform.GridUid)?.Station == station) + foreach (var spawn in EntitySpawnCollection.GetSpawns(comp.Entries, RobustRandom)) { - validLocations.Add(transform.Coordinates); - foreach (var spawn in EntitySpawnCollection.GetSpawns(component.Entries, RobustRandom)) - { - Spawn(spawn, transform.Coordinates); - } + Spawn(spawn, coords); } } - if (component.SpecialEntries.Count == 0 || validLocations.Count == 0) - { + if (comp.SpecialEntries.Count == 0) return; - } // guaranteed spawn - var specialEntry = RobustRandom.Pick(component.SpecialEntries); - var specialSpawn = RobustRandom.Pick(validLocations); - Spawn(specialEntry.PrototypeId, specialSpawn); + var specialEntry = RobustRandom.Pick(comp.SpecialEntries); + Spawn(specialEntry.PrototypeId, coords); + } - foreach (var location in validLocations) + private void PickLocation(VentCrittersRuleComponent comp) + { + if (!TryGetRandomStation(out var station)) + return; + + var locations = EntityQueryEnumerator(); + _locations.Clear(); + while (locations.MoveNext(out var uid, out _, out var transform)) { - foreach (var spawn in EntitySpawnCollection.GetSpawns(component.SpecialEntries, RobustRandom)) + if (CompOrNull(transform.GridUid)?.Station == station) { - Spawn(spawn, location); + _locations.Add(transform.Coordinates); } } + + if (_locations.Count > 0) + comp.Location = RobustRandom.Pick(_locations); } } diff --git a/Resources/Locale/en-US/deltav/station-events/events/vent-critters.ftl b/Resources/Locale/en-US/deltav/station-events/events/vent-critters.ftl new file mode 100644 index 00000000000..046b0ca7126 --- /dev/null +++ b/Resources/Locale/en-US/deltav/station-events/events/vent-critters.ftl @@ -0,0 +1 @@ +station-event-vent-creatures-start-announcement-deltav = Attention. A large influx of unknown life forms has been detected in ventilation systems near {$location}. All personnel must vacate the area immediately. diff --git a/Resources/Prototypes/DeltaV/GameRules/events.yml b/Resources/Prototypes/DeltaV/GameRules/events.yml index 45a6a1d0237..94217ab589a 100644 --- a/Resources/Prototypes/DeltaV/GameRules/events.yml +++ b/Resources/Prototypes/DeltaV/GameRules/events.yml @@ -45,7 +45,7 @@ earliestStart: 45 minimumPlayers: 20 weight: 1 - duration: 60 + duration: 30 - type: PrecognitionResult message: psionic-power-precognition-xeno-vents-result-message - type: VentCrittersRule @@ -75,7 +75,7 @@ earliestStart: 15 minimumPlayers: 15 weight: 4 - duration: 60 + duration: 30 - type: PrecognitionResult message: psionic-power-precognition-mothroach-spawn-result-message - type: VentCrittersRule diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index b22bc621c80..849a9418be8 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -389,7 +389,7 @@ earliestStart: 20 minimumPlayers: 15 weight: 5 - duration: 60 + duration: 30 # DeltaV: was 60, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-slimes-spawn-result-message - type: VentCrittersRule @@ -412,7 +412,7 @@ earliestStart: 20 minimumPlayers: 15 weight: 5 - duration: 60 + duration: 30 # DeltaV: was 60, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-snake-spawn-result-message - type: VentCrittersRule @@ -435,7 +435,7 @@ earliestStart: 20 minimumPlayers: 15 weight: 5 - duration: 60 + duration: 30 # DeltaV: was 60, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-spider-spawn-result-message - type: VentCrittersRule @@ -454,10 +454,11 @@ earliestStart: 45 # DeltaV - was 20 minimumPlayers: 30 # DeltaV - was 20 weight: 1 # DeltaV - was 1.5 - duration: 60 + duration: 30 # DeltaV: was 60, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-spider-clown-spawn-result-message - type: VentCrittersRule + playerRatio: 35 # DeltaV: Clown spiders are very robust entries: - id: MobClownSpider prob: 0.03 # DeltaV - was 0.05 diff --git a/Resources/Prototypes/GameRules/pests.yml b/Resources/Prototypes/GameRules/pests.yml index 0bc1e582e37..8ddde7e1a61 100644 --- a/Resources/Prototypes/GameRules/pests.yml +++ b/Resources/Prototypes/GameRules/pests.yml @@ -27,7 +27,7 @@ path: /Audio/Announcements/attention.ogg earliestStart: 15 weight: 6 - duration: 50 + duration: 30 # DeltaV: was 50, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-mouse-migration-result-message - type: VentCrittersRule @@ -52,7 +52,7 @@ path: /Audio/Announcements/attention.ogg earliestStart: 15 weight: 6 - duration: 50 + duration: 30 # DeltaV: was 50, used as a delay now minimumPlayers: 30 # Hopefully this is enough for the Rat King's potential Army (it was not, raised from 15 -> 30) - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-king-rat-migration-result-message @@ -79,7 +79,7 @@ startAudio: path: /Audio/Announcements/attention.ogg weight: 6 - duration: 50 + duration: 30 # DeltaV: was 50, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-cockroach-migration-result-message - type: VentCrittersRule @@ -98,7 +98,7 @@ startAudio: path: /Audio/Announcements/attention.ogg weight: 6 - duration: 50 + duration: 30 # DeltaV: was 50, used as a delay now - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-snail-migration-result-message - type: VentCrittersRule @@ -120,7 +120,7 @@ path: /Audio/Announcements/attention.ogg earliestStart: 15 weight: 6 - duration: 50 + duration: 30 # DeltaV: was 50, used as a delay now minimumPlayers: 30 - type: PrecognitionResult # DeltaV - Precogniton message: psionic-power-precognition-snail-migration-result-message