From c3adcf87aa0336697c07f55a50a81a63980a501f Mon Sep 17 00:00:00 2001 From: EmoGarbage404 Date: Sun, 15 Mar 2026 17:06:24 -0400 Subject: [PATCH 1/2] Light overload code --- .../Components/ESApcVoteComponent.cs | 9 +++ .../ESLightOverloadRuleComponent.cs | 9 +++ .../LightOverload/ESLightOverloadRule.cs | 78 +++++++++++++++++++ .../EntitySystems/SharedPoweredLightSystem.cs | 5 ++ .../Structures/Lighting/base_lighting.yml | 4 - 5 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 Content.Server/_ES/StationEvents/LightOverload/Components/ESApcVoteComponent.cs create mode 100644 Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs create mode 100644 Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs diff --git a/Content.Server/_ES/StationEvents/LightOverload/Components/ESApcVoteComponent.cs b/Content.Server/_ES/StationEvents/LightOverload/Components/ESApcVoteComponent.cs new file mode 100644 index 00000000000..f2f5fa18dbf --- /dev/null +++ b/Content.Server/_ES/StationEvents/LightOverload/Components/ESApcVoteComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server._ES.StationEvents.LightOverload.Components; + +[RegisterComponent] +[Access(typeof(ESLightOverloadRule))] +public sealed partial class ESApcVoteComponent : Component +{ + [DataField] + public int Count = 4; +} diff --git a/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs b/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs new file mode 100644 index 00000000000..a0310929958 --- /dev/null +++ b/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs @@ -0,0 +1,9 @@ +namespace Content.Server._ES.StationEvents.LightOverload.Components; + +[RegisterComponent] +[Access(typeof(ESLightOverloadRule))] +public sealed partial class ESLightOverloadRuleComponent : Component +{ + [DataField] + public List Apcs; +} diff --git a/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs b/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs new file mode 100644 index 00000000000..93c56d56a5c --- /dev/null +++ b/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs @@ -0,0 +1,78 @@ +using Content.Server._ES.StationEvents.LightOverload.Components; +using Content.Server.Light.EntitySystems; +using Content.Server.Power.Components; +using Content.Server.StationEvents.Events; +using Content.Shared._ES.Voting.Components; +using Content.Shared._ES.Voting.Results; +using Content.Shared.GameTicking.Components; +using Robust.Shared.Random; + +namespace Content.Server._ES.StationEvents.LightOverload; + +public sealed class ESLightOverloadRule : StationEventSystem +{ + [Dependency] private readonly PoweredLightSystem _poweredLight = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnSynchronizedVotesCompleted); + SubscribeLocalEvent(OnGetVoteOptions); + } + + private void OnSynchronizedVotesCompleted(Entity ent, ref ESSynchronizedVotesCompletedEvent args) + { + for (var i = 0; i < args.Results.Count; ++i) + { + if (args.TryGetResult(i, out var result) && + TryGetEntity(result.Entity, out var apc)) + { + ent.Comp.Apcs.Add(apc.Value); + } + } + } + + private void OnGetVoteOptions(Entity ent, ref ESGetVoteOptionsEvent args) + { + var apcs = new List(); + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out _)) + { + apcs.Add(uid); + } + + foreach (var apc in RobustRandom.GetItems(apcs, Math.Min(apcs.Count, ent.Comp.Count))) + { + args.Options.Add(new ESEntityVoteOption + { + DisplayString = Name(apc), + Entity = GetNetEntity(apc), + }); + } + } + + protected override void Started(EntityUid uid, + ESLightOverloadRuleComponent component, + GameRuleComponent gameRule, + GameRuleStartedEvent args) + { + base.Started(uid, component, gameRule, args); + + foreach (var apc in component.Apcs) + { + if (TerminatingOrDeleted(apc)) + return; + + if (!TryComp(apc, out var apcPowerComponent)) + return; + + foreach (var receiverComp in apcPowerComponent.LinkedReceivers) + { + var receiver = receiverComp.Owner; + _poweredLight.TryDestroyBulb(receiver); + } + } + } +} diff --git a/Content.Shared/Light/EntitySystems/SharedPoweredLightSystem.cs b/Content.Shared/Light/EntitySystems/SharedPoweredLightSystem.cs index 0c5a2b5850a..f53b4a8d3d8 100644 --- a/Content.Shared/Light/EntitySystems/SharedPoweredLightSystem.cs +++ b/Content.Shared/Light/EntitySystems/SharedPoweredLightSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared._ES.Sparks; using Content.Shared.Audio; using Content.Shared.Damage; using Content.Shared.Damage.Components; @@ -39,6 +40,7 @@ public abstract class SharedPoweredLightSystem : EntitySystem [Dependency] private readonly SharedDeviceLinkSystem _deviceLink = default!; // ES START [Dependency] private readonly SharedGameTicker _gameTicker = default!; + [Dependency] private readonly ESSparksSystem _sparks = default!; // ES END private static readonly TimeSpan ThunkDelay = TimeSpan.FromSeconds(2); @@ -249,6 +251,9 @@ public bool TryDestroyBulb(EntityUid uid, PoweredLightComponent? light = null, E return false; // break it +// ES START + _sparks.DoSparks(uid, user: user, tileFireChance: 0.05f); +// ES END _bulbSystem.SetState(bulbUid.Value, LightBulbState.Broken, lightBulb); _bulbSystem.PlayBreakSound(bulbUid.Value, lightBulb, user); UpdateLight(uid, light); diff --git a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml index 8bc70361b11..84b2583e390 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml @@ -85,10 +85,6 @@ collection: GlassBreak - type: PlacementReplacement key: lights -# ES START - - type: ESSparkOnHit - tileFireChance: 0.05 -# ES END placement: mode: SnapgridCenter snap: From adaa95e23f63ee33befee7d3b6c4c314201dc333 Mon Sep 17 00:00:00 2001 From: EmoGarbage404 Date: Sun, 15 Mar 2026 18:38:35 -0400 Subject: [PATCH 2/2] Add light overload event prototype --- .../ESLightOverloadRuleComponent.cs | 5 +++- .../LightOverload/ESLightOverloadRule.cs | 10 +++---- .../_ES/station-events/light-overload.ftl | 3 ++ .../_ES/GameRules/station_events.yml | 28 +++++++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 Resources/Locale/en-US/_ES/station-events/light-overload.ftl diff --git a/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs b/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs index a0310929958..7d1dfe621b4 100644 --- a/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs +++ b/Content.Server/_ES/StationEvents/LightOverload/Components/ESLightOverloadRuleComponent.cs @@ -5,5 +5,8 @@ namespace Content.Server._ES.StationEvents.LightOverload.Components; public sealed partial class ESLightOverloadRuleComponent : Component { [DataField] - public List Apcs; + public List Apcs = []; + + [DataField] + public float Radius = 8f; } diff --git a/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs b/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs index 93c56d56a5c..1a7de84242e 100644 --- a/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs +++ b/Content.Server/_ES/StationEvents/LightOverload/ESLightOverloadRule.cs @@ -5,12 +5,14 @@ using Content.Shared._ES.Voting.Components; using Content.Shared._ES.Voting.Results; using Content.Shared.GameTicking.Components; +using Content.Shared.Light.Components; using Robust.Shared.Random; namespace Content.Server._ES.StationEvents.LightOverload; public sealed class ESLightOverloadRule : StationEventSystem { + [Dependency] private readonly EntityLookupSystem _entityLookup = default!; [Dependency] private readonly PoweredLightSystem _poweredLight = default!; /// @@ -65,13 +67,11 @@ protected override void Started(EntityUid uid, if (TerminatingOrDeleted(apc)) return; - if (!TryComp(apc, out var apcPowerComponent)) - return; - foreach (var receiverComp in apcPowerComponent.LinkedReceivers) + var coords = Transform(apc).Coordinates; + foreach (var light in _entityLookup.GetEntitiesInRange(coords, component.Radius)) { - var receiver = receiverComp.Owner; - _poweredLight.TryDestroyBulb(receiver); + _poweredLight.TryDestroyBulb(light); } } } diff --git a/Resources/Locale/en-US/_ES/station-events/light-overload.ftl b/Resources/Locale/en-US/_ES/station-events/light-overload.ftl new file mode 100644 index 00000000000..1478383366a --- /dev/null +++ b/Resources/Locale/en-US/_ES/station-events/light-overload.ftl @@ -0,0 +1,3 @@ +es-station-event-light-overload-start-announcement = An anomalous power surge has been detected in station's powernet. Low-voltage lighting equipment may be affected. + +es-voter-query-string-light-overload-location = The APC that will be overloaded is: diff --git a/Resources/Prototypes/_ES/GameRules/station_events.yml b/Resources/Prototypes/_ES/GameRules/station_events.yml index 8af6f325e00..cf42351f783 100644 --- a/Resources/Prototypes/_ES/GameRules/station_events.yml +++ b/Resources/Prototypes/_ES/GameRules/station_events.yml @@ -44,6 +44,7 @@ - id: ESStationEventPowerGridCheck - id: ESStationEventSolarFlare - id: ESStationEventVentClog + - id: ESStationEventLightOverload - id: ESStationEventMeteorSwarm - id: ESStationEventElectricalFire @@ -273,3 +274,30 @@ - type: ESRandomLocationVote count: 6 checkLOS: false + +## Light Overload +- type: entity + parent: ESBaseStationEvent + id: ESStationEventLightOverload + name: Light Overload + description: Overload several APCs across the station, breaking all lights attached to them. + components: + - type: StationEvent + startAudio: + path: /Audio/_ES/Announcements/attention_medium.ogg + params: + volume: -4 + startAnnouncement: es-station-event-light-overload-start-announcement + - type: ESLightOverloadRule + - type: ESSynchronizedVoteManager + votes: + - ESVoteLightOverloadAPC + +- type: entity + id: ESVoteLightOverloadAPC + name: Which APC should be overloaded? + components: + - type: ESVote + queryString: es-voter-query-string-light-overload-location + duration: 30 + - type: ESApcVote