diff --git a/Content.Client/Entry/IgnoredComponents.cs b/Content.Client/Entry/IgnoredComponents.cs index 48256031b0..c052a17946 100644 --- a/Content.Client/Entry/IgnoredComponents.cs +++ b/Content.Client/Entry/IgnoredComponents.cs @@ -348,7 +348,8 @@ namespace Content.Client.Entry "HealthAnalyzer", "Thirst", "CanEscapeInventory", - "Wires" + "PowerSink", + "Wires", }; } } diff --git a/Content.Server/PowerSink/PowerSinkComponent.cs b/Content.Server/PowerSink/PowerSinkComponent.cs new file mode 100644 index 0000000000..4654205a38 --- /dev/null +++ b/Content.Server/PowerSink/PowerSinkComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server.PowerSink +{ + /// + /// Absorbs power up to its capacity when anchored then explodes. + /// + [RegisterComponent] + public sealed class PowerSinkComponent : Component {} +} diff --git a/Content.Server/PowerSink/PowerSinkSystem.cs b/Content.Server/PowerSink/PowerSinkSystem.cs new file mode 100644 index 0000000000..f72713e52e --- /dev/null +++ b/Content.Server/PowerSink/PowerSinkSystem.cs @@ -0,0 +1,56 @@ +using Content.Server.Explosion.EntitySystems; +using Content.Server.Power.Components; +using Content.Shared.Body.Events; +using Content.Shared.Examine; +using Robust.Shared.Utility; + +namespace Content.Server.PowerSink +{ + public sealed class PowerSinkSystem : EntitySystem + { + [Dependency] private readonly ExplosionSystem _explosionSystem = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnExamine); + } + + private void OnExamine(EntityUid uid, PowerSinkComponent component, ExaminedEvent args) + { + if (!args.IsInDetailsRange || !TryComp(uid, out var consumer)) + return; + + var drainAmount = (int) consumer.NetworkLoad.ReceivingPower / 1000; + args.PushMarkup( + Loc.GetString( + "powersink-examine-drain-amount", + ("amount", drainAmount), + ("markupDrainColor", "orange")) + ); + } + + public override void Update(float frameTime) + { + var toRemove = new RemQueue<(PowerSinkComponent Sink, BatteryComponent Battery)>(); + + // Realistically it's gonna be like <5 per station. + foreach (var (comp, networkLoad, battery, xform) in EntityManager.EntityQuery()) + { + if (!xform.Anchored) continue; + + battery.CurrentCharge += networkLoad.NetworkLoad.ReceivingPower / 1000; + if (battery.CurrentCharge < battery.MaxCharge) continue; + + toRemove.Add((comp, battery)); + } + + foreach (var (comp, battery) in toRemove) + { + _explosionSystem.QueueExplosion(comp.Owner, "Default", 5 * (battery.MaxCharge / 2500000), 0.5f, 10, canCreateVacuum: false); + EntityManager.RemoveComponent(comp.Owner, comp); + } + } + } +} diff --git a/Resources/Locale/en-US/powersink/powersink.ftl b/Resources/Locale/en-US/powersink/powersink.ftl new file mode 100644 index 0000000000..2d5b73be19 --- /dev/null +++ b/Resources/Locale/en-US/powersink/powersink.ftl @@ -0,0 +1 @@ +powersink-examine-drain-amount = The power sink is draining [color={$markupDrainColor}]{$amount} kW[/color]. diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 71bac31e75..305c0ea1ec 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -255,6 +255,12 @@ itemId: ClothingBackpackDuffelSyndicateFilledMedical price: 5 +- type : uplinkListing + id: UplinkPowerSink + category: Tools + itemId: PowerSink + price: 5 + - type: uplinkListing id: UplinkCarpDehydrated category: Tools diff --git a/Resources/Prototypes/Entities/Objects/Power/powersink.yml b/Resources/Prototypes/Entities/Objects/Power/powersink.yml new file mode 100644 index 0000000000..a2db90d32a --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Power/powersink.yml @@ -0,0 +1,46 @@ +- type: entity + id: PowerSink + parent: BaseMachine + name: power sink + description: Drains immense amounts of electricity from the grid. + components: + - type: Item + size: 150 + - type: NodeContainer + examinable: true + nodes: + input: + !type:CableDeviceNode + nodeGroupID: HVPower + - type: Transform + anchored: true + - type: Physics + - type: Fixtures + fixtures: + - shape: + !type:PhysShapeAabb + bounds: "-0.40,-0.40,0.40,0.40" + mass: 15 + mask: + - MachineMask + layer: + - MachineLayer + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 25 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: PowerSink + - type: Battery + maxCharge: 7500000 + - type: ExaminableBattery + - type: PowerConsumer + voltage: High + drawRate: 1000000 + - type: Sprite + netsync: false + sprite: Objects/Power/powersink.rsi + state: powersink diff --git a/Resources/Textures/Objects/Power/powersink.rsi/meta.json b/Resources/Textures/Objects/Power/powersink.rsi/meta.json new file mode 100644 index 0000000000..d85868d1db --- /dev/null +++ b/Resources/Textures/Objects/Power/powersink.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-NC-SA-3.0", + "copyright": "Taken from goonstation at commit https://github.com/goonstation/goonstation/commit/17c4392b75abd87a0f740e116c44dd4c7dfff6f7", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "powersink" + } + ] +} diff --git a/Resources/Textures/Objects/Power/powersink.rsi/powersink.png b/Resources/Textures/Objects/Power/powersink.rsi/powersink.png new file mode 100644 index 0000000000..9a8db0358a Binary files /dev/null and b/Resources/Textures/Objects/Power/powersink.rsi/powersink.png differ