--- /dev/null
+using Content.Shared.Whitelist;
+
+namespace Content.Server.GameTicking.Rules.VariationPass.Components;
+
+/// <summary>
+/// Handles cutting a random wire on random devices around the station.
+/// </summary>
+[RegisterComponent]
+public sealed partial class CutWireVariationPassComponent : Component
+{
+ /// <summary>
+ /// Blacklist of hackable entities that should not be chosen to
+ /// have wires cut.
+ /// </summary>
+ [DataField]
+ public EntityWhitelist Blacklist = new();
+
+ /// <summary>
+ /// Chance for an individual wire to be cut.
+ /// </summary>
+ [DataField]
+ public float WireCutChance = 0.05f;
+
+ /// <summary>
+ /// Maximum number of wires that can be cut stationwide.
+ /// </summary>
+ [DataField]
+ public int MaxWiresCut = 10;
+}
--- /dev/null
+using Content.Server.GameTicking.Rules.VariationPass.Components;
+using Content.Server.Wires;
+using Robust.Shared.Random;
+
+namespace Content.Server.GameTicking.Rules.VariationPass;
+
+/// <summary>
+/// Handles cutting a random wire on random devices around the station.
+/// This system identifies target devices and adds <see cref="CutWireOnMapInitComponent"/> to them.
+/// The actual wire cutting is handled by <see cref="CutWireOnMapInitSystem"/>.
+/// </summary>
+public sealed class CutWireVariationPassSystem : VariationPassSystem<CutWireVariationPassComponent>
+{
+ protected override void ApplyVariation(Entity<CutWireVariationPassComponent> ent, ref StationVariationPassEvent args)
+ {
+ var wiresCut = 0;
+ var query = AllEntityQuery<WiresComponent, TransformComponent>();
+ while (query.MoveNext(out var uid, out _, out var transform))
+ {
+ // Ignore if not part of the station
+ if (!IsMemberOfStation((uid, transform), ref args))
+ continue;
+
+ // Check against blacklist
+ if (ent.Comp.Blacklist.IsValid(uid))
+ continue;
+
+ if (Random.Prob(ent.Comp.WireCutChance))
+ {
+ EnsureComp<CutWireOnMapInitComponent>(uid);
+ wiresCut++;
+
+ // Limit max wires cut
+ if (wiresCut >= ent.Comp.MaxWiresCut)
+ break;
+ }
+ }
+ }
+}
--- /dev/null
+namespace Content.Server.Wires;
+
+/// <summary>
+/// Picks a random wire on the entity's <see cref="WireComponent"/> and cuts it.
+/// Runs at MapInit and removes itself afterwards.
+/// </summary>
+[RegisterComponent]
+public sealed partial class CutWireOnMapInitComponent : Component
+{
+}
--- /dev/null
+using Robust.Shared.Random;
+
+namespace Content.Server.Wires;
+
+/// <summary>
+/// Handles cutting a random wire on devices that have <see cref="CutWireOnMapInitComponent"/>.
+/// </summary>
+public sealed partial class CutWireOnMapInitSystem : EntitySystem
+{
+ [Dependency] private readonly IRobustRandom _random = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<CutWireOnMapInitComponent, MapInitEvent>(OnMapInit, after: [typeof(WiresSystem)]);
+ }
+
+ private void OnMapInit(Entity<CutWireOnMapInitComponent> entity, ref MapInitEvent args)
+ {
+ if (TryComp<WiresComponent>(entity, out var panel) && panel.WiresList.Count > 0)
+ {
+ // Pick a random wire
+ var targetWire = _random.Pick(panel.WiresList);
+
+ // Cut the wire
+ if (targetWire.Action == null || targetWire.Action.Cut(EntityUid.Invalid, targetWire))
+ targetWire.IsCut = true;
+ }
+
+ // Our work here is done
+ RemCompDeferred(entity, entity.Comp);
+ }
+}
- id: BasicTrashVariationPass
- id: SolidWallRustingVariationPass
- id: ReinforcedWallRustingVariationPass
+ - id: CutWireVariationPass
- id: BasicPuddleMessVariationPass
prob: 0.99
orGroup: puddleMess
tilesPerSpillAverage: 150
tilesPerSpillStdDev: 10
randomPuddleSolutionFill: RandomFillTrashPuddleBloodbath
+
+- type: entity
+ id: CutWireVariationPass
+ parent: BaseVariationPass
+ noSpawn: true
+ components:
+ - type: CutWireVariationPass
+ wireCutChance: 0.01
+ maxWiresCut: 20
+ blacklist:
+ components:
+ - ParticleAcceleratorControlBox