From 17a380f85fd7c4f5db9e3442317811686924e29f Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:12:29 -0400 Subject: [PATCH 01/14] Tesla passive energy decay: ball starves without a running PA The ball bleeds 10 energy/s, pinned to the Level-1 PA feed rate (3 emitters * 20 energy / 6s wave), so Level 1 is exactly break-even: alive, no motes. Standby/Level 0 starves it into collapse, Level 2+ nets positive. Despawn floor deepened to -600 (~60s starvation grace) because feed lands in 6-second lumps and the stock -100 floor would kill the ball after barely two missed waves. Decay defaults to 0 on the component so other users are unaffected; the tesla prototype opts in. --- .../Tesla/Components/TeslaEnergyBallComponent.cs | 8 ++++++++ .../Tesla/EntitySystem/TeslaEnergyBallSystem.cs | 16 ++++++++++++++++ .../Power/Generation/Tesla/energyball.yml | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs b/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs index 5e1c62f3042..1f65f8c5428 100644 --- a/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs +++ b/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs @@ -34,6 +34,14 @@ public sealed partial class TeslaEnergyBallComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public float EnergyToDespawn = -100f; + /// + /// Triad: energy bled passively per second while the ball exists. 0 disables decay (upstream + /// behavior, the default). The tesla prototype pins this to the Level-1 PA feed rate so Level 1 + /// is break-even: alive, no motes. See energyball.yml. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float PassiveEnergyDecay; + /// /// Played when energy reaches the lower limit (and entity destroyed) /// diff --git a/Content.Server/Tesla/EntitySystem/TeslaEnergyBallSystem.cs b/Content.Server/Tesla/EntitySystem/TeslaEnergyBallSystem.cs index 606f4615af3..f1a5668b73f 100644 --- a/Content.Server/Tesla/EntitySystem/TeslaEnergyBallSystem.cs +++ b/Content.Server/Tesla/EntitySystem/TeslaEnergyBallSystem.cs @@ -26,6 +26,22 @@ public override void Initialize() SubscribeLocalEvent(OnConsumed); } + // Triad: passive energy decay. The ball bleeds energy continuously so it needs a running PA to + // sustain it; with no feed it drains to EnergyToDespawn and collapses. + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var teslaEnergyBall)) + { + if (teslaEnergyBall.PassiveEnergyDecay <= 0f) + continue; + + AdjustEnergy(uid, teslaEnergyBall, -teslaEnergyBall.PassiveEnergyDecay * frameTime); + } + } + private void OnConsumed(Entity tesla, ref EntityConsumedByEventHorizonEvent args) { Spawn(tesla.Comp.ConsumeEffectProto, Transform(args.Entity).Coordinates); diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml index 43fce933263..cc2c34b4077 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml @@ -73,6 +73,12 @@ consumeEntities: false - type: TeslaEnergyBall spawnProto: TeslaMiniEnergyBall + # Triad: wild-tesla economy. Decay pinned to the Level-1 PA feed (3 emitters * 20 energy / 6s = 10/s) + # so Level 1 is break-even (alive, no motes), Standby/Level 0 starves the ball, Level 2+ makes motes. + # The deep despawn floor gives ~60s of grace under full starvation before collapse, since feed lands + # in 6-second lumps and the stock -100 floor would kill it after barely two missed waves. + passiveEnergyDecay: 10 + energyToDespawn: -600 soundCollapse: path: /Audio/Effects/tesla_collapse.ogg params: From a02094d308e48528926dc9563ecf8b6b63066b36 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:13:18 -0400 Subject: [PATCH 02/14] Tesla mote count tuned to the PA regime ladder With decay in place the threshold mechanism already scales mote output with net feed: spawn rate = net feed / needEnergyToSpawn, and motes live 120s. Threshold 120 lands the ladder at Level 1 = 0 motes, Level 2 = 5, Level 3 = 20 sustained. --- .../Entities/Structures/Power/Generation/Tesla/energyball.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml index cc2c34b4077..71b455cd85c 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml @@ -79,6 +79,9 @@ # in 6-second lumps and the stock -100 floor would kill it after barely two missed waves. passiveEnergyDecay: 10 energyToDespawn: -600 + # Mote count self-regulates: spawn rate = net feed / needEnergyToSpawn, motes live 120s, so + # Level 3 (net +20/s) sustains 20*120/120 = 20 motes and Level 2 (net +5/s) sustains 5. + needEnergyToSpawn: 120 soundCollapse: path: /Audio/Effects/tesla_collapse.ogg params: From 6cb861808fb1726e0b6175c9697a6213fe9e33f6 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:16:19 -0400 Subject: [PATCH 03/14] Charge-aware lightning routing: coils bid by headroom New LightningStrikeAttemptEvent raised on each candidate before a volley is sorted and rolled, letting targets adjust their effective priority and hit chance from live state. Targets with no subscriber keep their static values. Tesla coils subscribe: an empty coil is a guaranteed catch with a priority bump above every charged coil, and chance scales down with charge to a 0.05 floor when full, so overflow falls through to the grounding rods. At half charge the effective chance is ~0.52, close to the old static 0.5. --- Content.Server/Lightning/LightningSystem.cs | 40 +++++++++++++++---- .../Tesla/Components/TeslaCoilComponent.cs | 17 ++++++++ .../Tesla/EntitySystem/TeslaCoilSystem.cs | 20 ++++++++++ .../Power/Generation/Tesla/coil.yml | 2 +- 4 files changed, 70 insertions(+), 9 deletions(-) diff --git a/Content.Server/Lightning/LightningSystem.cs b/Content.Server/Lightning/LightningSystem.cs index c3bc6c257b0..55d38ac7ea0 100644 --- a/Content.Server/Lightning/LightningSystem.cs +++ b/Content.Server/Lightning/LightningSystem.cs @@ -106,8 +106,20 @@ private void ShootRandomLightnings(EntityUid user, float range, int boltCount, E // several hashsets every time var targets = _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(user), range).ToList(); - _random.Shuffle(targets); - targets.Sort((x, y) => y.Comp.Priority.CompareTo(x.Comp.Priority)); + // Triad: strike-attempt hook. Each candidate may adjust its effective priority and hit chance + // from live state (tesla coils bid by charge headroom) before the volley is sorted and rolled. + // Targets with no subscriber keep their static values, so behavior is unchanged for them. + // _random.Shuffle(targets); + // targets.Sort((x, y) => y.Comp.Priority.CompareTo(x.Comp.Priority)); + var candidates = new List<(Entity Target, int Priority, float HitProbability)>(targets.Count); + foreach (var target in targets) + { + var attempt = new LightningStrikeAttemptEvent(user, target.Comp.Priority, target.Comp.HitProbability); + RaiseLocalEvent(target, ref attempt); + candidates.Add((target, attempt.Priority, Math.Clamp(attempt.HitProbability, 0f, 1f))); + } + _random.Shuffle(candidates); + candidates.Sort((x, y) => y.Priority.CompareTo(x.Priority)); int shootedCount = 0; int count = -1; @@ -115,16 +127,16 @@ private void ShootRandomLightnings(EntityUid user, float range, int boltCount, E { count++; - if (count >= targets.Count) { break; } + if (count >= candidates.Count) { break; } - var curTarget = targets[count]; - if (!_random.Prob(curTarget.Comp.HitProbability)) //Chance to ignore target + var curTarget = candidates[count]; + if (!_random.Prob(curTarget.HitProbability)) //Chance to ignore target continue; - ShootLightning(user, targets[count].Owner, spawnOnHit, lightningPrototype, triggerLightningEvents); - if (arcDepth - targets[count].Comp.LightningResistance > 0) + ShootLightning(user, curTarget.Target.Owner, spawnOnHit, lightningPrototype, triggerLightningEvents); + if (arcDepth - curTarget.Target.Comp.LightningResistance > 0) { - ShootRandomLightnings(targets[count].Owner, range, 1, spawnOnHit, lightningPrototype, arcDepth - targets[count].Comp.LightningResistance, triggerLightningEvents); + ShootRandomLightnings(curTarget.Target.Owner, range, 1, spawnOnHit, lightningPrototype, arcDepth - curTarget.Target.Comp.LightningResistance, triggerLightningEvents); } shootedCount++; } @@ -138,3 +150,15 @@ private void ShootRandomLightnings(EntityUid user, float range, int boltCount, E /// The entity that was struck by lightning. [ByRefEvent] public readonly record struct HitByLightningEvent(EntityUid Source, EntityUid Target); + +/// +/// Triad: raised directed on each candidate target before a lightning volley is sorted and rolled. +/// Subscribers may adjust and from live state +/// (e.g. a tesla coil bidding by charge headroom). Both start at the target's static +/// LightningTargetComponent values; HitProbability is clamped to [0, 1] after the event. +/// +/// The entity shooting the lightning volley +/// Effective sort priority for this volley; higher is struck first +/// Effective chance this target is not skipped by the roll +[ByRefEvent] +public record struct LightningStrikeAttemptEvent(EntityUid Source, int Priority, float HitProbability); diff --git a/Content.Server/Tesla/Components/TeslaCoilComponent.cs b/Content.Server/Tesla/Components/TeslaCoilComponent.cs index d9c7be6fe4d..1ba42efbd4d 100644 --- a/Content.Server/Tesla/Components/TeslaCoilComponent.cs +++ b/Content.Server/Tesla/Components/TeslaCoilComponent.cs @@ -14,4 +14,21 @@ public sealed partial class TeslaCoilComponent : Component // To Do: Different lightning bolts have different powers and generate different amounts of energy [DataField, ViewVariables(VVAccess.ReadWrite)] public float ChargeFromLightning = 50000f; + + /// + /// Triad: strike-chance floor once the battery is full. Lightning favors the biggest potential + /// difference, so the coil's effective hit chance scales with charge headroom: empty = 1.0 + /// (plus a priority bump above every static target), full = this floor. A floored coil still + /// outranks grounding rods in the sort but gets skipped on almost every roll, so overflow + /// falls through to the rods. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float SaturatedHitProbability = 0.05f; + + /// + /// Triad: priority added on top of the coil's static LightningTarget priority while the battery + /// is completely empty, so a fresh coil catches the next bolt ahead of every charged coil. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int EmptyPriorityBonus = 1; } diff --git a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs index 4fd2f9b6ed0..5dd01832798 100644 --- a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs +++ b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs @@ -17,6 +17,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnHitByLightning); + SubscribeLocalEvent(OnLightningStrikeAttempt); // Triad } //When struck by lightning, charge the internal battery @@ -27,4 +28,23 @@ private void OnHitByLightning(Entity coil, ref HitByLightnin _battery.SetCharge(coil, batteryComponent.CurrentCharge + coil.Comp.ChargeFromLightning); } } + + // Triad: bid for the strike by charge headroom. An empty coil is a guaranteed catch and outbids + // every static target; a full coil floors at SaturatedHitProbability so bolts fall through to + // the grounding rods. At half charge the effective chance is ~0.52, close to the old static 0.5. + private void OnLightningStrikeAttempt(Entity coil, ref LightningStrikeAttemptEvent args) + { + if (!TryComp(coil, out var battery) || battery.MaxCharge <= 0f) + return; + + if (battery.CurrentCharge <= 0f) + { + args.Priority += coil.Comp.EmptyPriorityBonus; + args.HitProbability = 1f; + return; + } + + var headroom = 1f - battery.CurrentCharge / battery.MaxCharge; + args.HitProbability = MathHelper.Lerp(coil.Comp.SaturatedHitProbability, 1f, headroom); + } } diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index fbb1d8c1b0b..6756c502653 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -63,7 +63,7 @@ chargeFromLightning: 2000000 - type: LightningTarget priority: 4 - hitProbability: 0.5 + hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) lightningResistance: 10 lightningExplode: false - type: PowerNetworkBattery From ed419e24ffcd092f8acb306832d7115ec5499e41 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:18:30 -0400 Subject: [PATCH 04/14] Saturated tesla coils hold the arcing indicator New TeslaCoilVisuals.Charged appearance key driven off ChargeChangedEvent: while the battery cannot bank a full strike the coil shows the existing arc sprite on its own layer, so the 4-second strike flash cannot clobber it. Clears on its own as the coil pushes charge into the grid. --- Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs | 11 +++++++++++ Content.Shared/Power/TeslaCoilVisuals.cs | 3 ++- .../Structures/Power/Generation/Tesla/coil.yml | 7 +++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs index 5dd01832798..08abd3f9a38 100644 --- a/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs +++ b/Content.Server/Tesla/EntitySystem/TeslaCoilSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Power.EntitySystems; using Content.Server.Tesla.Components; using Content.Server.Lightning; +using Content.Shared.Power; // Triad namespace Content.Server.Tesla.EntitySystems; @@ -11,6 +12,7 @@ namespace Content.Server.Tesla.EntitySystems; public sealed class TeslaCoilSystem : EntitySystem { [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; // Triad public override void Initialize() { @@ -18,6 +20,7 @@ public override void Initialize() SubscribeLocalEvent(OnHitByLightning); SubscribeLocalEvent(OnLightningStrikeAttempt); // Triad + SubscribeLocalEvent(OnChargeChanged); // Triad } //When struck by lightning, charge the internal battery @@ -47,4 +50,12 @@ private void OnLightningStrikeAttempt(Entity coil, ref Light var headroom = 1f - battery.CurrentCharge / battery.MaxCharge; args.HitProbability = MathHelper.Lerp(coil.Comp.SaturatedHitProbability, 1f, headroom); } + + // Triad: hold the arcing indicator while the coil can't bank a full strike, so engineers can see + // saturation at a glance. Drains through the power net raise ChargeChangedEvent too, so the + // indicator clears on its own as the coil pushes charge into the grid. + private void OnChargeChanged(Entity coil, ref ChargeChangedEvent args) + { + _appearance.SetData(coil, TeslaCoilVisuals.Charged, args.Charge + coil.Comp.ChargeFromLightning > args.MaxCharge); + } } diff --git a/Content.Shared/Power/TeslaCoilVisuals.cs b/Content.Shared/Power/TeslaCoilVisuals.cs index 2cc633f8604..27f56cef554 100644 --- a/Content.Shared/Power/TeslaCoilVisuals.cs +++ b/Content.Shared/Power/TeslaCoilVisuals.cs @@ -6,5 +6,6 @@ namespace Content.Shared.Power; public enum TeslaCoilVisuals : byte { Enabled, - Lightning + Lightning, + Charged // Triad: coil battery too full to accept a full strike; shows the persistent arcing indicator } diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 6756c502653..af8f07ef25d 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -30,6 +30,9 @@ - state: coilhit visible: false map: ["hit"] + - state: coilhit # Triad: persistent arc while saturated; own layer so the strike flash can't clobber it + visible: false + map: ["charged"] - type: Appearance - type: GenericVisualizer visuals: @@ -41,6 +44,10 @@ hit: True: { visible: true } False: { visible: false } + enum.TeslaCoilVisuals.Charged: # Triad + charged: + True: { visible: true } + False: { visible: false } - type: LightningSparking - type: AnimationPlayer - type: NodeContainer From 16ae0eecfcc0f2f9f93a7b5926a16e735e8f6a52 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:19:54 -0400 Subject: [PATCH 05/14] Re-proportion tesla coil economy and durability for 9-hour rounds A strike now banks maxCharge/6 (500k into a 3M bank) instead of 2M into a 1M bank, so the charge-headroom routing has a real gradient and the saturation indicator means something. Coil supply cap is unchanged at 1MW. Strike damage drops 1 -> 0.05: ~4500 strikes to destruction, about 7 hours per coil at a moderate PA level under the mote-heavy strike economy. Service intervals stretch by welding or adding coils. --- .../Structures/Power/Generation/Tesla/coil.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index af8f07ef25d..609f0cc2395 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -63,16 +63,22 @@ sprite: Structures/Power/Generation/Tesla/coil.rsi state: coil - type: Battery - maxCharge: 1000000 + # Triad: wild-tesla economy. A strike banks maxCharge/6, so the charge-headroom routing has a + # real gradient instead of one strike pegging the coil (upstream: 2M strike into a 1M bank). + maxCharge: 3000000 startingCharge: 0 - type: BatteryDischarger - type: TeslaCoil - chargeFromLightning: 2000000 + chargeFromLightning: 500000 # Triad: was 2000000, see Battery note - type: LightningTarget priority: 4 hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) lightningResistance: 10 lightningExplode: false + # Triad: durability for 9-hour rounds under the mote-heavy strike economy: ~4500 strikes to + # destruction (~7h at a moderate PA level per coil). Stretch service intervals by welding + # (Repairable) or spreading load across more coils. + damageFromLightning: 0.05 - type: PowerNetworkBattery maxSupply: 1000000 supplyRampTolerance: 1000000 From 47ebff068ef12fbf726f319372c4ceadd3105cb6 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:33:30 -0400 Subject: [PATCH 06/14] Lightning strikes electrocute mobs instead of doing nothing Mobs have been on the strike table (priority 1) since the Mono port but took zero damage: the strike applies Structural, which no-ops on Biological damage containers. LightningTarget gains an opt-in electrocution path (15 shock, 5s, insulated gloves apply) enabled on the mob base, so bolts that overflow the coils and rods now zap whoever they land on. Mob lightningResistance stays 1, so a bolt can arc once more onward from the victim. Note this applies to every ShootRandomLightnings source, including the electrical anomaly, not just the tesla. --- .../Components/LightningTargetComponent.cs | 22 +++++++++++++++++++ .../Lightning/LightningTargetSystem.cs | 6 +++++ Resources/Prototypes/Entities/Mobs/base.yml | 3 +++ 3 files changed, 31 insertions(+) diff --git a/Content.Server/Lightning/Components/LightningTargetComponent.cs b/Content.Server/Lightning/Components/LightningTargetComponent.cs index 6d806b3fe7e..12624b1aa62 100644 --- a/Content.Server/Lightning/Components/LightningTargetComponent.cs +++ b/Content.Server/Lightning/Components/LightningTargetComponent.cs @@ -69,4 +69,26 @@ public sealed partial class LightningTargetComponent : Component /// [DataField] public FixedPoint2 DamageFromLightning = 1; + + // Triad: electrocution path. The Structural damage above no-ops on Biological damage containers, + // so mobs on the strike table took nothing. These make a strike electrocute the target instead; + // insulated gloves apply through the normal electrocution attempt. + + /// + /// Triad: whether a lightning strike electrocutes this target (stun + shock damage). + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public bool ElectrocuteOnStrike; + + /// + /// Triad: shock damage dealt by the electrocution. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public int ElectrocutionShockDamage = 15; + + /// + /// Triad: how long the electrocution lasts. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public TimeSpan ElectrocutionTime = TimeSpan.FromSeconds(5); } diff --git a/Content.Server/Lightning/LightningTargetSystem.cs b/Content.Server/Lightning/LightningTargetSystem.cs index 4a0ee23c5b7..1c74afe8c35 100644 --- a/Content.Server/Lightning/LightningTargetSystem.cs +++ b/Content.Server/Lightning/LightningTargetSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Electrocution; // Triad using Content.Server.Explosion.EntitySystems; using Content.Server.Lightning; using Content.Server.Lightning.Components; @@ -12,6 +13,7 @@ namespace Content.Server.Tesla.EntitySystems; public sealed class LightningTargetSystem : EntitySystem { [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly ElectrocutionSystem _electrocution = default!; // Triad [Dependency] private readonly ExplosionSystem _explosionSystem = default!; [Dependency] private readonly TransformSystem _transform = default!; @@ -24,6 +26,10 @@ public override void Initialize() private void OnHitByLightning(Entity uid, ref HitByLightningEvent args) { + // Triad: electrocution path for biological targets, which the Structural damage below no-ops on. + if (uid.Comp.ElectrocuteOnStrike) + _electrocution.TryDoElectrocution(uid, args.Source, uid.Comp.ElectrocutionShockDamage, uid.Comp.ElectrocutionTime, refresh: true); + DamageSpecifier damage = new(); damage.DamageDict.Add("Structural", uid.Comp.DamageFromLightning); _damageable.TryChangeDamage(uid, damage, true); diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index 69351eee1d4..5283f2e78e1 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -123,6 +123,9 @@ - type: LightningTarget priority: 1 # Mono lightningExplode: false + # Triad: bolts that overflow the coils and rods electrocute whoever they land on. + # Insulated gloves apply; lightningResistance stays 1 so the bolt can arc once more onward. + electrocuteOnStrike: true # Used for mobs that can enter combat mode and can attack. - type: entity From 78229dc3a75985331c6086af139a7059443a6a0f Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 18:56:05 -0400 Subject: [PATCH 07/14] Retune tesla decay and mote threshold from Monte Carlo simulation Simulating the ball wander in a 3-wide cage showed the far side PA lane misses about a third of waves, so effective Level-1 feed is ~7.3/s, not the ideal 10/s. Decay 10 starved the Level-1 ball dead; 7 idles it as designed. Mote threshold 120 -> 80 lands the target ladder at the effective feed: ~6 motes at Level 2, ~22 at Level 3, 1.8 MW sustained harvest at a hacked Level-3 PA with a 12-coil ring. --- .../Components/TeslaEnergyBallComponent.cs | 4 ++-- .../Structures/Power/Generation/Tesla/coil.yml | 6 +++--- .../Power/Generation/Tesla/energyball.yml | 17 +++++++++-------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs b/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs index 1f65f8c5428..96e85b86179 100644 --- a/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs +++ b/Content.Server/Tesla/Components/TeslaEnergyBallComponent.cs @@ -36,8 +36,8 @@ public sealed partial class TeslaEnergyBallComponent : Component /// /// Triad: energy bled passively per second while the ball exists. 0 disables decay (upstream - /// behavior, the default). The tesla prototype pins this to the Level-1 PA feed rate so Level 1 - /// is break-even: alive, no motes. See energyball.yml. + /// behavior, the default). The tesla prototype pins this to the effective Level-1 PA feed rate + /// so Level 1 idles the ball: alive, essentially no motes. See energyball.yml for the tuning. /// [DataField, ViewVariables(VVAccess.ReadWrite)] public float PassiveEnergyDecay; diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 609f0cc2395..755b3922cbb 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -75,9 +75,9 @@ hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) lightningResistance: 10 lightningExplode: false - # Triad: durability for 9-hour rounds under the mote-heavy strike economy: ~4500 strikes to - # destruction (~7h at a moderate PA level per coil). Stretch service intervals by welding - # (Repairable) or spreading load across more coils. + # Triad: durability for 9-hour rounds under the mote-heavy strike economy: 4500 strikes to + # destruction. Simulated with a 12-coil ring: first coil death ~11h at PA Level 2, ~4h at a + # hacked Level 3. Stretch service intervals by welding (Repairable) or adding coils. damageFromLightning: 0.05 - type: PowerNetworkBattery maxSupply: 1000000 diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml index 71b455cd85c..ae2d5c92460 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/energyball.yml @@ -73,15 +73,16 @@ consumeEntities: false - type: TeslaEnergyBall spawnProto: TeslaMiniEnergyBall - # Triad: wild-tesla economy. Decay pinned to the Level-1 PA feed (3 emitters * 20 energy / 6s = 10/s) - # so Level 1 is break-even (alive, no motes), Standby/Level 0 starves the ball, Level 2+ makes motes. - # The deep despawn floor gives ~60s of grace under full starvation before collapse, since feed lands - # in 6-second lumps and the stock -100 floor would kill it after barely two missed waves. - passiveEnergyDecay: 10 + # Triad: wild-tesla economy. Decay pinned to the EFFECTIVE Level-1 PA feed (~7.3/s from Monte + # Carlo, not the ideal 3 lanes * 20 / 6s = 10/s: the ball's wander in a 3-wide cage drops the far + # side lane about a third of the time). Level 1 idles the ball (alive, a stray mote every few + # minutes), Standby/Level 0 starves it, Level 2+ makes motes. The deep despawn floor gives ~85s + # of grace under full starvation, since feed lands in 6-second lumps. + passiveEnergyDecay: 7 energyToDespawn: -600 - # Mote count self-regulates: spawn rate = net feed / needEnergyToSpawn, motes live 120s, so - # Level 3 (net +20/s) sustains 20*120/120 = 20 motes and Level 2 (net +5/s) sustains 5. - needEnergyToSpawn: 120 + # Mote count self-regulates: spawn rate = net feed / needEnergyToSpawn, motes live 120s. + # Simulated ladder at these numbers: Level 1 ~0.5 motes, Level 2 ~6, Level 3 ~22 sustained. + needEnergyToSpawn: 80 soundCollapse: path: /Audio/Effects/tesla_collapse.ogg params: From 6179673dffae742c86f5ac7138fe06fd58b6ff70 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:00:36 -0400 Subject: [PATCH 08/14] Scale tesla strike energy to a ~7 MW Level-3 harvest ceiling Strike energy back to the upstream 2M but into a 12M bank, keeping the 6-strike routing gradient. Catch dynamics depend only on the strike-to-bank ratio, so saturation behavior and durability are unchanged; output scales linearly. Simulated: ~2.6 MW at stock Level 2, ~7.2 MW at a hacked Level 3 with a 12-coil ring. --- .../Entities/Structures/Power/Generation/Tesla/coil.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 755b3922cbb..2517c87b3cb 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -65,11 +65,13 @@ - type: Battery # Triad: wild-tesla economy. A strike banks maxCharge/6, so the charge-headroom routing has a # real gradient instead of one strike pegging the coil (upstream: 2M strike into a 1M bank). - maxCharge: 3000000 + # Sized from Monte Carlo for ~7 MW sustained at a hacked Level-3 PA with a 12-coil ring + # (~2.6 MW at stock Level 2). + maxCharge: 12000000 startingCharge: 0 - type: BatteryDischarger - type: TeslaCoil - chargeFromLightning: 500000 # Triad: was 2000000, see Battery note + chargeFromLightning: 2000000 # Triad: upstream value, but into a 12M bank instead of 1M — see Battery note - type: LightningTarget priority: 4 hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) From 5868488e389f4bca087838d815bc121ce0d006f1 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:05:27 -0400 Subject: [PATCH 09/14] Tesla coils become capacitors: one strike fills, tower count is throughput maxCharge drops to equal chargeFromLightning (2M) and supply throttles to 300 kW, so a struck tower saturates, its strike bid floors, and the routing round-robins bolts across the array while each bank trickles out smoothly. Tower count becomes the harvest knob: simulated at a hacked Level-3 PA, 12 towers ~3.5 MW, 24 ~6 MW, ~7 MW asymptote; stock Level 2 with 12 towers ~2.5 MW. Bigger arrays also spread strike damage: first coil death ~4.7h at 12 towers, ~11h at 32. --- .../Power/Generation/Tesla/coil.yml | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 2517c87b3cb..0b37ec7de44 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -63,15 +63,16 @@ sprite: Structures/Power/Generation/Tesla/coil.rsi state: coil - type: Battery - # Triad: wild-tesla economy. A strike banks maxCharge/6, so the charge-headroom routing has a - # real gradient instead of one strike pegging the coil (upstream: 2M strike into a 1M bank). - # Sized from Monte Carlo for ~7 MW sustained at a hacked Level-3 PA with a 12-coil ring - # (~2.6 MW at stock Level 2). - maxCharge: 12000000 + # Triad: wild-tesla economy, capacitor model. One strike fills the bank; the full coil's strike + # bid floors (see TeslaCoilSystem) so the next bolt round-robins to a drained coil, and the bank + # trickles out through the throttled supply below. Tower count is therefore the throughput knob: + # Monte Carlo at a hacked Level-3 PA gives ~3.5 MW with 12 towers, ~6 MW with 24, ~7 MW asymptote + # (~2.5 MW at stock Level 2 with 12). + maxCharge: 2000000 startingCharge: 0 - type: BatteryDischarger - type: TeslaCoil - chargeFromLightning: 2000000 # Triad: upstream value, but into a 12M bank instead of 1M — see Battery note + chargeFromLightning: 2000000 # Triad: equals maxCharge on purpose — one strike saturates, see Battery note - type: LightningTarget priority: 4 hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) @@ -82,8 +83,11 @@ # hacked Level 3. Stretch service intervals by welding (Repairable) or adding coils. damageFromLightning: 0.05 - type: PowerNetworkBattery - maxSupply: 1000000 - supplyRampTolerance: 1000000 + # Triad: throttled discharge is what makes tower count matter — each tower trickles its bank at + # 300 kW, so full harvest at a hacked Level-3 PA needs a ~24-tower array. The ~7s per-tower + # buffer also smooths the strike lumps into near-constant grid supply. + maxSupply: 300000 + supplyRampTolerance: 300000 - type: Anchorable - type: Rotatable - type: Pullable From 4db196a608bcde669e84c7cb353363c122f3c0bb Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:42:13 -0400 Subject: [PATCH 10/14] Tesla harvest peaks at 24 towers; ~2h service interval at max output Supply throttle 300 -> 500 kW moves the throughput knee to a 24-tower array (simulated ~5.3 MW at 12 towers, ~7 MW peak at 24; more towers add no output, only spread wear). Strike damage 0.05 -> 0.15 lands the first tower death at ~2h on the max array, ~3.4h at stock Level 2 with 12 towers. Welding rotation or extra towers stretch it. --- .../Power/Generation/Tesla/coil.yml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml index 0b37ec7de44..00b5128b9a7 100644 --- a/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml +++ b/Resources/Prototypes/Entities/Structures/Power/Generation/Tesla/coil.yml @@ -66,8 +66,8 @@ # Triad: wild-tesla economy, capacitor model. One strike fills the bank; the full coil's strike # bid floors (see TeslaCoilSystem) so the next bolt round-robins to a drained coil, and the bank # trickles out through the throttled supply below. Tower count is therefore the throughput knob: - # Monte Carlo at a hacked Level-3 PA gives ~3.5 MW with 12 towers, ~6 MW with 24, ~7 MW asymptote - # (~2.5 MW at stock Level 2 with 12). + # Monte Carlo at a hacked Level-3 PA: ~5.3 MW with 12 towers, peaking at ~7 MW with 24; towers + # beyond 24 add no output, only spread wear (~2.6 MW at stock Level 2 with 12). maxCharge: 2000000 startingCharge: 0 - type: BatteryDischarger @@ -78,16 +78,16 @@ hitProbability: 0.5 # Triad: fallback only; with a working battery the coil bids by charge headroom (see TeslaCoilSystem) lightningResistance: 10 lightningExplode: false - # Triad: durability for 9-hour rounds under the mote-heavy strike economy: 4500 strikes to - # destruction. Simulated with a 12-coil ring: first coil death ~11h at PA Level 2, ~4h at a - # hacked Level 3. Stretch service intervals by welding (Repairable) or adding coils. - damageFromLightning: 0.05 + # Triad: 1500 strikes to destruction. Simulated: first tower death ~2h on a max-output 24-tower + # array at a hacked Level 3, ~3.4h at stock Level 2 with 12 towers. Weld (Repairable) on a + # service rotation, or add towers beyond 24 to spread wear. + damageFromLightning: 0.15 - type: PowerNetworkBattery # Triad: throttled discharge is what makes tower count matter — each tower trickles its bank at - # 300 kW, so full harvest at a hacked Level-3 PA needs a ~24-tower array. The ~7s per-tower - # buffer also smooths the strike lumps into near-constant grid supply. - maxSupply: 300000 - supplyRampTolerance: 300000 + # 500 kW (4s recovery), sized so harvest at a hacked Level-3 PA peaks at a 24-tower array. The + # per-tower buffer also smooths the strike lumps into near-constant grid supply. + maxSupply: 500000 + supplyRampTolerance: 500000 - type: Anchorable - type: Rotatable - type: Pullable From c7c63480c5e4544e06434102d8c60856303a9e34 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:50:12 -0400 Subject: [PATCH 11/14] Tesla coil logistics: bulk crate of 12, buyable, Edison starts with one The Edison bulk crate holds a dozen flatpacks (was six) and gains a cargo console listing, since Frontier abstracted the upstream single-coil product and nothing sold coils at all. Edison map stock trims to exactly one bulk crate: a 12-tower starter array out of the box, with expansion bought through the console. --- Resources/Maps/_NF/POI/edison.yml | 39 ------------------- .../PointsOfInterest/EdisonPort/entities.yml | 4 +- .../_Triad/Catalog/Cargo/cargo_engines.yml | 12 ++++++ 3 files changed, 14 insertions(+), 41 deletions(-) create mode 100644 Resources/Prototypes/_Triad/Catalog/Cargo/cargo_engines.yml diff --git a/Resources/Maps/_NF/POI/edison.yml b/Resources/Maps/_NF/POI/edison.yml index 90e46479ba3..46f9eddf404 100644 --- a/Resources/Maps/_NF/POI/edison.yml +++ b/Resources/Maps/_NF/POI/edison.yml @@ -36438,23 +36438,6 @@ entities: - type: Transform pos: 33.5,-24.5 parent: 1 -- proto: CrateEngineeringTeslaCoil - entities: - - uid: 6050 - components: - - type: Transform - pos: 43.5,-23.5 - parent: 1 - - uid: 6051 - components: - - type: Transform - pos: 42.5,-23.5 - parent: 1 - - uid: 6052 - components: - - type: Transform - pos: 44.5,-23.5 - parent: 1 - proto: CrateEngineeringTeslaCoilBulk entities: - uid: 6053 @@ -80498,28 +80481,6 @@ entities: - type: Transform pos: 25.5,17.5 parent: 1 -- proto: TeslaCoilFlatpack - entities: - - uid: 12219 - components: - - type: Transform - pos: 46.438305,-23.349659 - parent: 1 - - uid: 12220 - components: - - type: Transform - pos: 46.713493,-23.386375 - parent: 1 - - uid: 12221 - components: - - type: Transform - pos: 46.493343,-23.569962 - parent: 1 - - uid: 12222 - components: - - type: Transform - pos: 46.823566,-23.569962 - parent: 1 - proto: TeslaGenerator entities: - uid: 12223 diff --git a/Resources/Prototypes/_NF/PointsOfInterest/EdisonPort/entities.yml b/Resources/Prototypes/_NF/PointsOfInterest/EdisonPort/entities.yml index fe68cd96662..b01db08b658 100644 --- a/Resources/Prototypes/_NF/PointsOfInterest/EdisonPort/entities.yml +++ b/Resources/Prototypes/_NF/PointsOfInterest/EdisonPort/entities.yml @@ -196,12 +196,12 @@ id: CrateEngineeringTeslaCoilBulk parent: CrateEngineeringSecure name: bulk tesla coil crate - description: A collection of six tesla coils. Attracts lightning and generates energy from it. + description: A dozen flatpacked tesla coils. Attract lightning and generate energy from it. components: - type: StorageFill contents: - id: TeslaCoilFlatpack - amount: 6 + amount: 12 # Triad: one crate = a starter array; two = the 24-tower max-output build - type: entity id: CrateEngineeringSingularityCollectorBulk diff --git a/Resources/Prototypes/_Triad/Catalog/Cargo/cargo_engines.yml b/Resources/Prototypes/_Triad/Catalog/Cargo/cargo_engines.yml new file mode 100644 index 00000000000..6d8b8e42fec --- /dev/null +++ b/Resources/Prototypes/_Triad/Catalog/Cargo/cargo_engines.yml @@ -0,0 +1,12 @@ +# Triad: the upstream single-coil product (EngineTeslaCoil) is abstract via Frontier, so this is +# the only console path to tesla coils. One bulk crate is a 12-tower starter array; two build the +# 24-tower max-output ring. +- type: cargoProduct + id: EngineTeslaCoilBulk + icon: + sprite: Structures/Power/Generation/Tesla/coil.rsi + state: coil + product: CrateEngineeringTeslaCoilBulk + cost: 10000 + category: cargoproduct-category-name-engineering + group: market From c007c72376a7a566459b5192ecc1787757b7278e Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:50:12 -0400 Subject: [PATCH 12/14] Update tesla guidebook for the wild economy Documents feeding and starvation (including starving out a tesloose), mote generation scaling with accelerator power, capacitor coils with the arcing charge indicator, potential-difference strike preference, wear and welding, and real crew electrocution. Deliberately does not mention the accelerator limiter. --- .../Guidebook/Engineering/TeslaEngine.xml | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml index 168f6253a8a..9a023064f7a 100644 --- a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml +++ b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml @@ -1,4 +1,4 @@ - + # Tesla Engine The Tesla Engine is a powerful generator that uses a contained ball of lightning to produce energy for the station. @@ -10,11 +10,23 @@ It generates power by harnessing the lightning strikes produced by the lightning ball using Tesla Coils. + ## Feeding the Ball + The lightning ball constantly bleeds energy into space. It must be continuously fed by a running Particle Accelerator, or it will starve, shrink, and collapse within a couple of minutes. + + How hard you feed it matters: + - At low accelerator power the ball merely survives, producing only its own occasional strikes. + - Fed harder, the ball builds surplus energy and sheds it as miniature ball lightning, which orbit the containment field and fire strikes of their own. + - The more miniature balls in orbit, the more lightning, and the more power your coils can harvest. A well-fed tesla is dramatically more generous, and dramatically more dangerous. + + + + + ## Containment Field The Tesla Engine requires a containment field to prevent the lightning ball from escaping and destroying the station. It is suggested to use the minimum size containment field for the lightning ball. - Larger containment fields allow the lightning ball to reach closer to sensitive equipment and potentially strike it, ignoring placed grounding rods and tesla coils. + A tight cage keeps the ball centered in the accelerator's particle stream, and keeps it away from sensitive equipment beyond the field. @@ -33,18 +45,16 @@ ## Lightning Strikes - When the Tesla Engine is active, the lightning ball will periodically strike objects surrounding it. - - The Tesla prefers to strike some objects more than others, such as Tesla Coils and Grounding Rods. + When the Tesla Engine is active, the lightning ball and its miniature balls will periodically strike objects surrounding them. - If the tesla can't find any Tesla Coils or Grounding Rods to strike first, it will strike almost any station object capable of being powered, such as Substations, APCs, and general machinery. + Lightning seeks the largest difference in electrical potential. An empty Tesla Coil is the most attractive target on the station; a fully charged one is nearly ignored. Grounding Rods are always willing targets and sit just below coils in preference. - Certain objects aren't struck by the tesla, such as batteries, lights, PDAs, and other handheld items. + If the tesla can't find any Tesla Coils or Grounding Rods to strike, it will strike almost any station object capable of being powered, such as Substations, APCs, and general machinery. - It will also strike mobs and crew members, shocking them. Make sure to wear insulated gloves before approaching it. + It will also strike mobs and crew members, electrocuting them. Make sure to wear insulated gloves before approaching it, and keep spectators away from a heavily fed engine. ## Tesla Coils - Lightning strikes can be harnessed using Tesla Coils, which convert the lightning strikes into power for the station. + Lightning strikes are harnessed using Tesla Coils, which store each strike and feed it to the grid. @@ -52,13 +62,13 @@ - Tesla Coils should be placed around the lightning ball to capture the energy from lightning strikes, as well as to prevent the lightning from striking sensitive equipment further away. + A single strike fully charges a coil's internal bank. While it holds charge the coil arcs visibly and discharges into the grid at a steady rate; lightning avoids it in favor of empty coils, so strikes naturally spread themselves across the array. - Tesla Coils take damage every time they are struck by lightning, and will eventually break if not repaired. - Be sure to monitor the condition of the Tesla Coils and repair them as needed. + Ring the containment field with coils. Output grows with every coil you add until each bolt reliably finds an empty coil waiting; beyond that point, additional coils add no output but spread the wear. - When lightning strikes Tesla Coils, they fill an internal battery, which is rapidly discharged to the grid. - It will discharge this power even if there is no consumer to take it, so it's a good idea to have an SMES nearby to store the power and discharge it smoothly. + Coils take damage every time they are struck, and a hard-driven array needs regular attention. Watch for cracks and repair coils with a welder before they fail, or stock spares. + + A coil arcing is normal, it is simply holding charge. If the entire array arcs continuously, your grid isn't drawing enough power: add SMES capacity to soak up the surplus, or the engine will waste its strikes. ## Grounding Rods Grounding Rods help protect sensitive equipment from being struck and prevent a loosed tesla (tesloose). @@ -76,7 +86,7 @@ Grounding rods do not take damage from lightning strikes. - This makes them beneficial for forming a saftey net of grounding rods to rely on in case the tesla coils are damaged or destroyed. + This makes them beneficial for forming a safety net of grounding rods to rely on in case the tesla coils are damaged or destroyed. Engineers should use grounding rods to protect sensitive equipment from lightning strikes, such as the Emitters powering the containment field generators. @@ -84,7 +94,7 @@ If the lightning ball escapes the containment field, it is referred to as a loosed tesla, or tesloose. An escaped tesla will randomly walk around the station, attracted to objects that can be powered, such as APCs, Substations, and machinery. - It will also gladly strike crew members and mobs, shocking them. + It will also gladly strike crew members and mobs, electrocuting them. Wearing insulated gloves will protect you from being shocked by the tesla, but it won't prevent the tesla from striking you. @@ -92,7 +102,9 @@ - The tesla can be destroyed by firing antiparticles at it using a Portable Particle Decelerator, however, the Tesla is much more powerful than the Singularity, and it will take a lot of antiparticles to destroy it. + Remember that the ball starves without its accelerator. Shut the Particle Accelerator down and a loose ball will collapse on its own within a couple of minutes, provided it doesn't find enough to eat along the way. Evacuate its path, cut the feed, and wait it out. + + The tesla can also be destroyed by firing antiparticles at it using a Portable Particle Decelerator, however, the Tesla is much more powerful than the Singularity, and it will take a lot of antiparticles to destroy it. A group of people using decelerators is recommended to destroy a tesloose. Portable Particle Decelerators can be either researched and made by the Research Department, or they can be bought from Cargo. From 5e86b3cb9a81d3bcd6609c16d7903f2c9098b11e Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:57:39 -0400 Subject: [PATCH 13/14] Guidebook: a tesloose is already starving Containment failure means the ball has left the particle stream, so it is cut off from feed the moment it escapes. Drop the shut-down-the- PA advice and document the real behavior: it collapses on its own within a few minutes, and decelerators just speed that up. --- Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml index 9a023064f7a..70b30f470ba 100644 --- a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml +++ b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml @@ -102,9 +102,9 @@ - Remember that the ball starves without its accelerator. Shut the Particle Accelerator down and a loose ball will collapse on its own within a couple of minutes, provided it doesn't find enough to eat along the way. Evacuate its path, cut the feed, and wait it out. + Remember that the ball starves without its accelerator. An escaped ball has left the particle stream behind, so it is already dying: expect it to collapse on its own within a few minutes. Evacuate its path and let it burn itself out. - The tesla can also be destroyed by firing antiparticles at it using a Portable Particle Decelerator, however, the Tesla is much more powerful than the Singularity, and it will take a lot of antiparticles to destroy it. + To end it faster, fire antiparticles at it using a Portable Particle Decelerator, however, the Tesla is much more powerful than the Singularity, and it will take a lot of antiparticles to destroy it. A group of people using decelerators is recommended to destroy a tesloose. Portable Particle Decelerators can be either researched and made by the Research Department, or they can be bought from Cargo. From 18a5cb996def1f6abefff428b5837a1ca777b2f0 Mon Sep 17 00:00:00 2001 From: rebaserHEAD <38984539+rebaserHEAD@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:58:21 -0400 Subject: [PATCH 14/14] Guidebook: drop particle decelerator advice Decelerators are unobtainable on this fork: Frontier abstracted the cargo product and commented the gun out of research and the lathe pack. Waiting out the starving ball is the actual tesloose response. --- .../ServerInfo/Guidebook/Engineering/TeslaEngine.xml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml index 70b30f470ba..5ca71f3b99e 100644 --- a/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml +++ b/Resources/ServerInfo/Guidebook/Engineering/TeslaEngine.xml @@ -102,16 +102,6 @@ - Remember that the ball starves without its accelerator. An escaped ball has left the particle stream behind, so it is already dying: expect it to collapse on its own within a few minutes. Evacuate its path and let it burn itself out. - - To end it faster, fire antiparticles at it using a Portable Particle Decelerator, however, the Tesla is much more powerful than the Singularity, and it will take a lot of antiparticles to destroy it. - A group of people using decelerators is recommended to destroy a tesloose. - - Portable Particle Decelerators can be either researched and made by the Research Department, or they can be bought from Cargo. - - - - - + Remember that the ball starves without its accelerator. An escaped ball has left the particle stream behind, so it is already dying: expect it to collapse on its own within a few minutes. Evacuate its path, keep your distance, and let it burn itself out.